persistence@glassfish.java.net

Re: row updates outside of JPA not reflected in JPA

From: Marina Vatkina <Marina.Vatkina_at_Sun.COM>
Date: Wed, 16 Jan 2008 10:05:35 -0800

Hi Girish,

Your results will depend on the caching strategy of the persistence provider.
TopLink Essentials (the default provider in GlassFish) has caching enabled by
default, i.e. it relies on the internal cache for the values of instances that
had been created or fetched by the EMs of the same EMF.

To see changes that had been done to the database outside JPA you need to either
disable the caching or use em.refresh() API.

Regards,
-marina

Girish Kumar Balachandran wrote:
> (Not sure if this is the right alias to ask this question. If not please
> forward to the right alias.)
>
> Modifications to a row that are directly made on the DB externally via
> SQL does not seem to reflect in the JPA returned objects. New row
> additions are recognized though. Is this something that JPA supports or
> is it a bug?
>
> I have attached a simple program that demonstrates the scenario. I
> created this program in netbeans. Run the following table creation SQL
> statement first to the DB connection:
>
> CREATE TABLE VIR.GIRISH(
> ID BIGINT generated always as identity NOT NULL,
> STRING VARCHAR(20),
> VERSION INT DEFAULT 0,
> CONSTRAINT PRINCIPAL_PK PRIMARY KEY (ID)
> );
>
> Then compile and run the program. While it is running execute:
>
> UPDATE VIR.GIRISH SET STRING = 'modified', VERSION=2 WHERE ID = 1;
>
> and observe that the output of the program does not get the changes.
> Restarting the program will get the changes though.
>
> Is there a special thing I need to do to cover this usecase? I wonder
> how clustered environments use JPA if this is not supported inherently.
>
>
> Thanks,
> -Girish
>
>
>
> ------------------------------------------------------------------------
>
> import java.io.UnsupportedEncodingException;
> import java.sql.DriverManager;
> import java.sql.SQLException;
> import java.util.HashMap;
> import java.util.List;
> import javax.persistence.EntityManager;
> import javax.persistence.EntityManagerFactory;
> import javax.persistence.Persistence;
> import javax.persistence.Query;
>
> /**
> *
> * @author girix
> */
> public class JPATester {
>
> private static HashMap properties;
>
> private static String jdbcURL;
>
> private static String dbDriver;
>
> private static EntityManagerFactory emf;
>
> private static EntityManager em;
>
> /** Creates a new instance of Main */
> public JPATester() {
> }
>
> /**
> * @param args the command line arguments
> */
> public static void main(String[] args) throws SQLException, UnsupportedEncodingException, InterruptedException {
> DriverManager.registerDriver(new org.apache.derby.jdbc.ClientDriver());
>
> properties = new HashMap<String,String>();
> jdbcURL = "jdbc:derby://localhost:1527/vir";
> dbDriver = "org.apache.derby.jdbc.ClientDriver";
>
> properties.put("toplink.jdbc.user","app");
> properties.put("toplink.jdbc.password","app");
> properties.put("toplink.jdbc.url",jdbcURL);
> properties.put("toplink.jdbc.driver",dbDriver);
> properties.put("toplink.logging.level","FINE");
>
> emf = Persistence.createEntityManagerFactory("ScratchpadProjectPU", properties);
>
>
> em = emf.createEntityManager();
>
> DbGirish girish = new DbGirish();
> girish.setString("kumar");
>
> em.getTransaction().begin();
> em.persist(girish);
> em.getTransaction().commit();
>
>
> int j = 0;
> while(true){
> //re-creating a new EMF also does not solve the problem.
> //emf = Persistence.createEntityManagerFactory("ScratchpadProjectPU", properties);
> //creating a new EM also does not help
> //em = emf.createEntityManager();
> Query q = em.createQuery("SELECT girish FROM DbGirish girish");
> Thread.sleep(3000);
> System.out.println("\n\nIteration number:"+j++);
> List<DbGirish> lis = q.getResultList();
> int i = 0;
> for(DbGirish gir : lis){
> System.out.println(i+". Entry ID:"+gir.getId()+" String:"+
> gir.getString()+" Version:"+gir.getVersion());
> i++;
> }
> em.close();
> }
>
> }
> }
>
>
>
> ------------------------------------------------------------------------
>
>
>
> import java.io.Serializable;
> import javax.persistence.Column;
> import javax.persistence.Entity;
> import javax.persistence.GeneratedValue;
> import javax.persistence.GenerationType;
> import javax.persistence.Id;
> import javax.persistence.NamedQueries;
> import javax.persistence.NamedQuery;
> import javax.persistence.Table;
> import javax.persistence.Version;
>
> /**
> *
> * @author girix
> */
> @Entity
> @Table(name = "VIR.GIRISH")
> @NamedQueries({_at_NamedQuery(name = "DbGirish.findById", query = "SELECT d FROM DbGirish d WHERE d.id = :id"), @NamedQuery(name = "DbGirish.findByString", query = "SELECT d FROM DbGirish d WHERE d.string = :string"), @NamedQuery(name = "DbGirish.findByVersion", query = "SELECT d FROM DbGirish d WHERE d.version = :version")})
> public class DbGirish implements Serializable {
> private static final long serialVersionUID = 1L;
> @Id
> @GeneratedValue(strategy=GenerationType.IDENTITY)
> @Column(name = "ID", nullable = false)
> private Long id;
> @Column(name = "STRING")
> private String string;
> @Version
> @Column(name = "VERSION")
> private Integer version;
>
> public DbGirish() {
> }
>
> public DbGirish(Long id) {
> this.id = id;
> }
>
> public Long getId() {
> return id;
> }
>
> public void setId(Long id) {
> this.id = id;
> }
>
> public String getString() {
> return string;
> }
>
> public void setString(String string) {
> this.string = string;
> }
>
> public Integer getVersion() {
> return version;
> }
>
> public void setVersion(Integer version) {
> this.version = version;
> }
>
> @Override
> public int hashCode() {
> int hash = 0;
> hash += (id != null ? id.hashCode() : 0);
> return hash;
> }
>
> @Override
> public boolean equals(Object object) {
> // TODO: Warning - this method won't work in the case the id fields are not set
> if (!(object instanceof DbGirish)) {
> return false;
> }
> DbGirish other = (DbGirish) object;
> if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
> return false;
> }
> return true;
> }
>
> @Override
> public String toString() {
> return "grt.DbGirish[id=" + id + "]";
> }
>
> }
>
>
>
> ------------------------------------------------------------------------
>
> <?xml version="1.0" encoding="UTF-8"?>
> <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
> <persistence-unit name="ScratchpadProjectPU" transaction-type="RESOURCE_LOCAL">
> <provider>oracle.toplink.essentials.PersistenceProvider</provider>
> <!-- <class>scratchpadproject.Table2</class>
> <class>scratchpadproject.Table1</class>
> <class>scratchpadproject.DbRefrencer</class> -->
> <class>DbGirish</class>
> </persistence-unit>
> </persistence>
>