persistence@glassfish.java.net

Re: row updates outside of JPA not reflected in JPA

From: Girish Kumar Balachandran <Girish.Balachandran_at_Sun.COM>
Date: Wed, 16 Jan 2008 12:28:41 -0800

Thanks Marina for the reply! I used |toplink.cache.type.<ENTITY> and it
seems to work well for me.

For the benefit of the others, here is the list of all properties
supported by Toplink.

http://www.oracle.com/technology/products/ias/toplink/JPA/essentials/toplink-jpa-extensions.html

-Girish
|
Marina Vatkina wrote:
> 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>
>>
>