Results 1 to 4 of 4

Thread: toplink cahe does not work with LocalContainerEntityManagerFactoryBean

  1. #1
    Join Date
    Apr 2008
    Posts
    5

    Default toplink cahe does not work with LocalContainerEntityManagerFactoryBean

    Hello,

    I encountered a strange problem. I was setting up a simple JPA example using LocalEntityManagerFactoryBean and toplink in order to measure some performance figures over toplink cache. But when I switched to LocalContainerEntityManagerFactoryBean the toplink cache stopped working.

    BTW I am using spring-2.5.3 and toplink 2.0-b41-beta2

    So here the are my configurations:
    A simple entity:

    Code:
    package entities;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.Table;
    
    @Entity
    @Table(name="orders")
    public class Order {
    	@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    	public int id;
    	public String name;
    	
    	public Order() {}
    	
    	public Order(String name) {
    		this.name = name;
    	}
    	
    	@Override
    	public String toString() {
    		return id+"/"+name;
    	}
    
    	@Override
    	public int hashCode() {
    		final int prime = 31;
    		int result = 1;
    		result = prime * result + id;
    		result = prime * result + ((name == null) ? 0 : name.hashCode());
    		return result;
    	}
    
    	@Override
    	public boolean equals(Object obj) {
    		if (this == obj)
    			return true;
    		if (obj == null)
    			return false;
    		if (getClass() != obj.getClass())
    			return false;
    		final Order other = (Order) obj;
    		if (id != other.id)
    			return false;
    		if (name == null) {
    			if (other.name != null)
    				return false;
    		} else if (!name.equals(other.name))
    			return false;
    		return true;
    	}
    	
    }
    A simple service:

    Code:
    package services;
    
    import javax.persistence.EntityManager;
    import javax.persistence.PersistenceContext;
    
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    
    import entities.Order;
    
    @Service
    public class DBService {
    	@PersistenceContext
    	private EntityManager em;
    	
    	@Transactional
    	public Order findOrder(int id) {
    		return em.find(Order.class, id);
    	}
    	
    	@Transactional
    	public int insertOrder(String name) {
    		Order no = new Order(name);
    		em.persist(no);
    		em.flush();
    		return no.id;
    	}
    }
    The two teste cases:

    Code:
    package tests;
    
    import junit.framework.Assert;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import entities.Order;
    
    import services.DBService;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations={"classpath:beans-local.xml"})
    public class TestLocal {
    	
    	@Autowired
    	private DBService dbs;
    	
    //	@Test
    //	public void testCacheInsert() {
    //		int id = dbs.insertOrder("hola");
    //		Order o1 = dbs.findOrder(id);
    //		Order o2 = dbs.findOrder(id);
    //	    Assert.assertNotNull(o1);
    //		Assert.assertEquals(o1, o2);
    //	}	
    	
    	@Test
    	public void testCacheNoInsert() {
    		int id = 14;
    		Order o1 = dbs.findOrder(id);
    		Order o2 = dbs.findOrder(id);
    		Assert.assertNotNull(o1);
    		Assert.assertEquals(o1, o2);
    	}
    	
    }
    and

    Code:
    package tests;
    
    import org.springframework.test.context.ContextConfiguration;
    
    @ContextConfiguration(locations={"classpath:beans-container.xml"})
    public class TestContainer extends TestLocal {}
    and the two configurations ( first the local one )

    beans-local.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schem...ring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schem...ng-context.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <bean class="org.springframework.orm.jpa.support.Persist enceAnnotationBeanPostProcessor"/>
    <context:annotation-config />
    <context:component-scan base-package="services" />
    <tx:annotation-driven transaction-manager="jpaTM"/>

    <bean id="jpaTM" class="org.springframework.orm.jpa.JpaTransactionM anager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityMana gerFactoryBean">
    <property name="persistenceUnitName" value="arena" />
    </bean>

    </beans>
    and the needed persistence.xml ( located in META-INF dir )

    <?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="arena" transaction-type="RESOURCE_LOCAL">
    <provider>oracle.toplink.essentials.PersistencePro vider</provider>
    <class>entities.Order</class>
    <properties>
    <property name="toplink.logging.level" value="FINE" />
    <property name="toplink.jdbc.user" value="******" />
    <property name="toplink.jdbc.password" value="******" />
    <property name="toplink.jdbc.url" value="jdbc:db2://localhost:50004/arena" />
    <property name="toplink.jdbc.driver" value="com.ibm.db2.jcc.DB2Driver" />
    </properties>
    </persistence-unit>
    </persistence>
    and the configuration files used for local-container:
    beans-container.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schem...ring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schem...ng-context.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <bean class="org.springframework.orm.jpa.support.Persist enceAnnotationBeanPostProcessor"/>
    <context:annotation-config />
    <context:component-scan base-package="service" />
    <context:load-time-weaver weaver-class="org.springframework.instrument.classloading .InstrumentationLoadTimeWeaver"/>
    <tx:annotation-driven transaction-manager="jpaTM"/>

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="url" value="jdbc:db2://localhost:50004/arena" />
    <property name="username" value="********" />
    <property name="password" value="********" />
    <property name="driverClassName" value="com.ibm.db2.jcc.DB2Driver" />
    </bean>

    <bean id="jpaTM"
    class="org.springframework.orm.jpa.JpaTransactionM anager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
    <property name="dataSource" ref="dataSource"/>
    </bean>

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerE ntityManagerFactoryBean">
    <property name="persistenceUnitName" value="arena" />
    <property name="dataSource" ref="dataSource"/>
    <property name="persistenceXmlLocation" value="META-INF/persistence-container.xml"></property>
    <property name="jpaVendorAdapter">
    <bean class="org.springframework.orm.jpa.vendor.TopLinkJ paVendorAdapter">
    <property name="showSql" value="true"/>
    <property name="databasePlatform" value="oracle.toplink.essentials.platform.database .DB2Platform"/>
    </bean>
    </property>
    </bean>

    </beans>
    and the corresponding persistence-container.xml
    <?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="arena" transaction-type="RESOURCE_LOCAL">
    <provider>oracle.toplink.essentials.PersistencePro vider</provider>
    <properties>
    <property name="toplink.logging.level" value="FINE" />
    </properties>
    </persistence-unit>
    </persistence>
    The container test case was started with -javaagent:lib/spring-agent.jar option of course.

    I knew that the cache was not working after monitorig the logs and observing that in the case of local-container test case the runtime issues two selects to the DB:
    [TopLink Fine]: 2008.04.14 10:44:14.301--ClientSession(25537913)--Connection(20978984)--Thread(Thread[main,5,main])--SELECT ID, NAME FROM orders WHERE (ID = ?)
    bind => [14]
    Since this is a simple setup I can provide the whole eclipse jar-ed project.

    The commented method testCacheInsert was used to insert some orders into the database. Event stranger is that if only this method is used the runtime does not (in either cases) issues any select statements to the DB. So if one wants to reproduce the problem, run one of the test with testCacheInsert uncommented (or just insert a row into the db ) and after that run the two test cases as they are posted here. ( em.flush(); from the insertOrder method is neccesary for running testCacheInsert method )

    Any help would be appreciated.

    Regards,
    Horia

  2. #2
    Join Date
    Apr 2008
    Posts
    5

    Default This is a cross-posting

    It seems however that somebody else faces a related problem: http://forums.oracle.com/forums/thre...95157&tstart=0

  3. #3
    Join Date
    Apr 2008
    Posts
    5

    Default ToplinkJpaVendorAdapter causes the cache bypass

    After further testing it seems that the cause of this is the use of TopLinkJpaVendorAdapter with the LocalContainerEntityManagerFactory because the moment I remove the jpaVendorAdapter property ( probably the EM factory will use the default JpaVendorAdapter ) the cache is used again.

    Still, the cache should work right or the cache bypass with the ToplinkJpaVendorAdapter is intentional?

    Regards,
    Horia

  4. #4
    Join Date
    Oct 2008
    Posts
    13

    Default

    Hi, I'm currently runing apache-tomcat-6.0.26 / spring-framework-3.0.2.RELEASE / TopLink 2.0.0.b41-beta2 and the above stated by 5hao is still true (more then two years past since then):

    After further testing it seems that the cause of this is the use of TopLinkJpaVendorAdapter with the LocalContainerEntityManagerFactory because the moment I remove the jpaVendorAdapter property ( probably the EM factory will use the default JpaVendorAdapter ) the cache is used again.
    Many thanks 5hao !!!

    In order to use this workaround I had to put the following
    Code:
    <provider>oracle.toplink.essentials.PersistenceProvider</provider>
    into my persistence.xml.

    So, probably to switch between Hibernate and TopLink one should change two files - persistence.xml and applicationContext.xml instead just one of them - applicationContext.xml.

    Please fix.

    Thanks in advance,
    bodrin

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •