Hi all!
I've spent a week trying different solutions for my requirement (hibernate with jboss as 2nd level cache under tomcat 6). At first, it was a problem to configure transaction manager. I've rejected JOTM and use at present Atomikos as it seems to be working fine and sufficiently documented as well.
My configuration:
Spring context:Code:
<bean id="placeholderConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:config.properties</value>
</list>
</property>
</bean>
<aop:aspectj-autoproxy />
<tx:annotation-driven transaction-manager="transactionManager" />
<context:component-scan base-package="com.test" />
<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close">
<property name="forceShutdown" value="false" />
</bean>
<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout" value="300" />
</bean>
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="atomikosTransactionManager" />
<property name="userTransaction" ref="atomikosUserTransaction" />
</bean>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="dataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean"
init-method="init" destroy-method="close">
<property name="uniqueResourceName">
<value>XADBMS</value>
</property>
<property name="xaDataSourceClassName">
<value>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</value>
</property>
<property name="xaProperties">
<props>
<prop key="user">${ds_username}</prop>
<prop key="password">${ds_password}</prop>
<prop key="URL">${ds_url}</prop>
</props>
</property>
<property name="poolSize" value="5" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan">
<list>
<value>com.test</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate_dialect}</prop>
<prop key="hibernate.transaction.manager_lookup_class">com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup</prop>
<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.jbc.MultiplexedJBossCacheRegionFactory</prop>
<prop key="hibernate.cache.region_prefix">americasjobexchange.cache</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.use_structured_entries">true</prop>
<prop key="hibernate.cache.jbc.query.localonly">true</prop>
<prop key="hibernate.cache.jbc.cfg.entity">mvcc-entity</prop>
<prop key="hibernate.cache.jbc.cfg.timestamps">timestamps-cache</prop>
<prop key="hibernate.cache.jbc.cfg.query">local-query</prop>
<prop key="hibernate.cache.jbc.cfg.multiplexer.stacks">jgroups-stacks.xml</prop>
<prop key="hibernate.cache.jbc.configs">jbc-configs.xml</prop>
</props>
</property>
</bean>
Entity:Code:
package com.test.hibernate;
@Entity
@Table(name="table_name")
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
public class TestEntity {
private static final long serialVersionUID = 2459140185756215638L;
private Long id;
private Integer daily;
private Integer total;
public TestEntity() {
// Default constructor
}
@Id
@Column(name = "id", nullable = false, length = 20)
public Long getId() {
return this.id;
}
public void setId(final Long id) {
this.id = id;
}
@Column(name = "daily", nullable = false)
public Integer getDaily() {
return this.daily;
}
public void setDaily(final Integer daily) {
this.daily = daily;
}
@Column(name = "total", nullable = false)
public Integer getTotal() {
return this.total;
}
public void setTotal(final Integer total) {
this.total = total;
}
}
Dao:Code:
@Repository
@Transactional(readOnly = true)
public class TestDao {
@Autowired
private HibernateTemplate hibernateTemplate;
public List get(){
Session sess = hibernateTemplate.getSessionFactory().getCurrentSession();
return sess.createCriteria(TestEntity.class).list();
}
}
Junit:
Quote:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:/context.xml"})
@TransactionConfiguration(transactionManager="transactionManager")
@Transactional
public class TestHb {
@Autowired
private TestDao dao;
@Test
public void testHb(){
System.out.println(dao.get());
System.out.println(dao.get());
System.out.println(dao.get());
}
}
On classpath there are config.properties with db stuff, original jbc-configs.xml, jgroups-stacks.xml, modified transactions.properties, log4j.xml. Nothing special...
My question to hibernate gurus is: What I miss?
I see in logs that every seems to load properly, jgroups cluster starts okay, entity gets cached in jboss cache (used jconsole mbeans to check this), one hibernate session,
BUT database is hit 3 times (used mysql query log to check this)?
Do I have to write code to query cache in dao and annotations are not enough?
I use spring 3.0.3.RELEASE & hibernate+jbosscache 3.5.2-Final versions from maven.