I'm trying to include dbunit and spring dbunit to my project for testing.
I have 2 folders:
"src/test/java/dao"
and
"src/test/resources/dao".
In resources dao
<?xml version='1.0' encoding='UTF-8'?>
<dataset>
<Brands id="1" brandName="Apple" />
</dataset>
Tried with uppercase and lower case(BRANDS, brands), still having same problem.
In main java
public class BrandsDaoTest {
#Autowired
private BrandsDao brandsDao;
private Brand brand;
private static final int ID = 1;
private static final String BRANDNAME = "apple";
private static final String UBRANDNAME = "horizont";
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration({ "classpath:app-context.xml","classpath:test-context.xml" })
#TestExecutionListeners({ DependencyInjectionTestExecutionListener.class,
DbUnitTestExecutionListener.class })
#Test
#DatabaseSetup("schema.xml")
public void find(){
Brand brand = brandsDao.find(1);
assertNotNull(brand);
brandsDao.delete(ID);
assertNull(brandsDao.find(ID));
}
}
My brand entity:
#Entity
#Table(name = "brands")
public class Brand {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
#Column(name="BrandName",nullable=false)
private String brandName;
#OneToMany(fetch = FetchType.LAZY)
#JoinColumn(name="BrandId",updatable=false)
private List<Device> devices;
public Brand(){
}
public Brand(int id,String brandName){
this.id = id;
this.brandName = brandName;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getBrandName() {
return this.brandName;
}
public void setBrandName(String brandName) {
this.brandName = brandName;
}
public List<Device> getDevices(){
return this.devices;
}
public void setDevices(List<Device> devices){
this.devices = devices;
}
public boolean equals(Object obj) {
boolean result = false;
if (!(obj instanceof Brand))
return result;
Brand brand = (Brand)obj;
if(this.getId() == brand.getId())
result = true;
return result;
}
}
This is my connection:
bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.h2.Driver"/>
<property name="url" value="jdbc:h2:mem:dbtest;
MODE=MySQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE" />
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan"
value="com.entities" />
<property name="hibernateProperties">
<props>
<prop key="dialect">org.hibernate.dialect.H2Dialect</prop>
<prop key="connection.useUnicode">true</prop>
<prop key="connection.characterEncoding">UTF-8</prop>
<prop key="hibernate.hbm2ddl.auto">create-drop</prop>
</props>
</property>
</bean>
Before using dbunit, had the same problem, and
<prop key="hibernate.hbm2ddl.auto">create-drop</prop>
solved the problem for me. Now if my schema.xml file is empty and
I'm adding brands in one of the test methods with "brandsDao.create( new Brand() )" method,
everything works fine. But when I add
<Brands id="1" brandName="Apple" />
to my schema.xml, I get this "NoSuchTableException: Brands".
Also, before I've inserted this to my context xml:
<bean id="dbUnitDatabaseConfig" class="com.github.springtestdbunit.bean.DatabaseConfigBean">
<property name="datatypeFactory">
<bean class="org.dbunit.ext.mysql.MySqlDataTypeFactory" />
</property>
<property name="caseSensitiveTableNames" value="true" />
</bean>
<bean id="dbUnitDatabaseConnection" class="com.github.springtestdbunit.bean.
DatabaseDataSourceConnectionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="databaseConfig" ref="dbUnitDatabaseConfig"/>
</bean>
I had "Did not find table 'BRANDS' in schema null". Tried different articles on
this errors, but still nothing helped. I guess my database is not created when dbunit is
trying to insert data from schema.
Will be grateful for some hints or advices.
Thanks Alan Hay for your reply. I've tried your set of hibernate properties to my sessionFactory bean
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan"
value="com.entities" />
<property name="hibernateProperties">
<props>
<prop key="dialect">${hibernate.dialect}</prop>
<prop key="connection.useUnicode">true</prop>
<prop key="connection.characterEncoding">UTF-8</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.cache.use_second_level_cache">false</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
</props>
</property>
</bean>
And what was most helpfull is
<prop key="hibernate.show_sql">true</prop>
which provided me with full trace of my virtual db creation. All names where lowercase there,
so after changing
<Brands id="1" brandName="Apple" />
to
<brands id="1" brandName="Apple" />
<brands id="2" brandName="Apple2" />
It worked. I'm pretty sure I've tried this before, maybe I didn't include
<bean id="dbUnitDatabaseConfig" class="com.github.springtestdbunit.bean.DatabaseConfigBean">
<property name="datatypeFactory">
<bean class="org.dbunit.ext.mysql.MySqlDataTypeFactory" />
</property>
<property name="caseSensitiveTableNames" value="true" />
</bean>
at that time. Nevertheless it works fine now. Thanks for hints again.
Now my hibernate properties look like:
<props>
<prop key="dialect">org.hibernate.dialect.H2Dialect</prop>
<prop key="connection.useUnicode">true</prop>
<prop key="connection.characterEncoding">UTF-8</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
<!--<prop key="hibernate.show_sql">true</prop> -->
</props>
Related
I am having an issue when we migrated from Hibernate 4 to 5.
I have been struggling from a week and read numerous blogs and pages, but could not resolve.
Following are more information on the issue:-
1) Hibernate Version :
From: 4.3.11.Final
To : 5.4.28.Final
2) Spring ORM version : 4.3.29.RELEASE
3) Spring Batch Infrastructre/Core: 3.0.10.Release
4) Hibernate XML Configuration :
<?xml version="1.0" encoding="UTF-8"?>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource"/> <!-- set in another xml using org.apache.commons.dbcp.BasicDataSource -->
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.id.new_generator_mappings">true</prop>
<!-- -->
<prop key="hibernate.jdbc.batch_size">1000</prop>
<prop key="hibernate.jdbc.fetch_size">1000</prop>
<prop key="hibernate.order_inserts">true</prop>
<prop key="hibernate.order_updates">true</prop>
</props>
</property>
<property name="annotatedClasses">
<list>
<value>com.company.ParentTable</value>
<value>com.company.ChildTable</value>
</list>
</property>
</bean>
<bean id="transactionTemplate"
class="org.springframework.transaction.support.TransactionTemplate"
p:isolationLevelName="ISOLATION_READ_COMMITTED"
p:propagationBehaviorName="PROPAGATION_REQUIRES_NEW"
p:transactionManager-ref="transactionManager"
/>
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- Spring transaction management -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate5.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory"
/>
5) Spring Batch Configuration
<?xml version="1.0" encoding="UTF-8"?>
<batch:job id="loaderJob" job-repository="jobRepository">
<batch:step id="initLoader" next="pipeline">
<batch:tasklet transaction-manager="transactionManager">
<bean class="com.company.InitialLoaderTask" scope="step">
<constructor-arg name="dao" ref="dao"/>
<constructor-arg name="filter" value="#{jobParameters['filter']}"/>
</bean>
</batch:tasklet>
</batch:step>
<batch:step id="pipeline">
<batch:tasklet transaction-manager="transactionManager" task-executor="loader_multi_thread_taskExecutor" throttle-limit="50">
<batch:chunk
reader="reader"
writer="processorAndWriter"
commit-interval="1000">
</batch:tasklet>
</batch:step>
</batch:job>
<bean id="reader" class="com.company.SynchronizedItemStreamReader" scope="step" > <!-- Custom Synchrnized Item Reader -->
<constructor-arg name="delegate" ref="#{ jobExecutionContext['region'] ? 'hibernateReader':'hibernateReader2' }"/> <!-- hibernateReader2 is same as hibernateReader but with more params -->
</bean>
<bean id="hibernateReader"
class="org.springframework.batch.item.database.HibernateCursorItemReader"
scope="step" >
<property name="sessionFactory" ref="sessionFactory"/>
<property name="queryName" value="ParentTable.query1"/>
<property name="useStatelessSession" value="false"/>
<property name="saveState" value="false"/>
<property name="fetchSize" value="10000"/>
<property name="parameterValues">
<map>
<entry key="param1" value="#{jobExecutionContext['param1']}"/>
<entry key="param2" value="#{jobExecutionContext['param2']}"/>
</map>
</property>
</bean>
<bean id="processorAndWriter"
class="com.company.LoaderAndWriter"
>
<constructor-arg name="generator" ref="processor"/>
<constructor-arg name="writer" ref="hibernateWriter"/>
</bean>
<bean id="processor" class="org.springframework.batch.item.support.CompositeItemProcessor" >
<property name="delegates">
<list>
<bean class="com.company.Generator" scope="step">
<constructor-arg name="param1" value="#{jobExecutionContext['param1']}"/>
</bean>
<bean class="com.company.Processor" scope="step">
<constructor-arg name="param3" value="#{jobExecutionContext['param3']}"/>
</bean>
</list>
</property>
</bean>
<bean id="hibernateWriter" class="org.springframework.batch.item.database.HibernateItemWriter">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="loader_multi_thread_taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="25"/>
<property name="maxPoolSize" value="50"/>
</bean>
6) Entity Objects
#Entity
#Table(name = "PARENT_TABLE")
#NamedNativeQueries({
#NamedNativeQuery(
name = "ParentTable.query1",
query = "SELECT * FROM PARENT_TABLE where param = :param1",
resultClass = ParentTable.class
)
})
#BatchSize(size = 1000)
public class ParentTable extends PersistentEntity<Long> {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "PARENT_TABLE_SEQ")
#SequenceGenerator(name = "PARENT_TABLE_SEQ", sequenceName = "PARENT_TABLE_SEQ", allocationSize=5)
private Long id;
#Column
private Long field1;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "fieldId", fetch = FetchType.EAGER)
#BatchSize(size = 1000)
private List<ChildTable> childTable;
}
#Entity
#Table(name = "CHILD_TABLE")
#BatchSize(size = 1000)
public class ChildTable extends PersistentEntity<Long> {
private static final long serialVersionUID = 1L;
#Id
private Long id;
#ManyToOne
#JoinColumn(name = "field1")
private ParentTable parentData;
#Column
private String field2;
}
7) Generator Class where error is thrown when access Childtable data from ParentData List
public class Generator implements ItemProcessor<List<? extends ParentTable>, RequestPojoBean> {
private final int param1;
public Generator(int param1) {
this.param1 = param1;
}
#Override
public RequestPojoBean process(List<? extends ParentTable> parentDataList) throws Exception {
RequestPojoBean result = new RequestPojoBean();
result.setParentDataList(convertToRequestList(parentDataList));
result.setparam1(param1);
return result;
}
private List<ParentRequestPojoBean> convertToRequestList(List<? extends ParentTable> parentDataList) {
List<ParentRequestPojoBean> parentRequestBean = new ArrayList<>();
for (ParentTable parentData : parentDataList) {
LOGGER.info("Parent detail " + parentData.getField1());
ParentRequestPojoBean bean1 = new ParentRequestPojoBean();
bean1.setSomeData(callToSomeServiceViaHibernate(parentData.somedata, param1));
// attach References if any
List<RequestPojoBeanChildData> childList = new ArrayList<>();
for (ChildTable child : parentData.getChildTable()) { *****<--- Exception is thrown at this line*****
RequestPojoBeanChildData childPojoData = new RequestPojoBeanChildData();
childPojoData.setField2(child.getField2());
childList.add(childPojoData);
}
bean1.setChildData(childList);
parentRequestBean.add(bean1);
}
return parentRequestBean;
}
}
8) Exception Stack Trace :
2021-04-12 13:33:42,548 ERROR [main] [org.springframework.batch.core.step.AbstractStep] - <Encountered an error executing step pipeline in job loaderJob>
java.util.ConcurrentModificationException
at java.util.LinkedHashMap$LinkedHashIterator.nextNode(LinkedHashMap.java:719)
at java.util.LinkedHashMap$LinkedEntryIterator.next(LinkedHashMap.java:752)
at java.util.LinkedHashMap$LinkedEntryIterator.next(LinkedHashMap.java:750)
at org.hibernate.engine.spi.BatchFetchQueue.getCollectionBatch(BatchFetchQueue.java:311)
at org.hibernate.loader.collection.plan.LegacyBatchingCollectionInitializerBuilder$LegacyBatchingCollectionInitializer.initialize(LegacyBatchingCollectionInitializerBuilder.java:79)
at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:710)
at org.hibernate.event.internal.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:76)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:93)
at org.hibernate.internal.SessionImpl.initializeCollection(SessionImpl.java:2163)
at org.hibernate.collection.internal.AbstractPersistentCollection$4.doWork(AbstractPersistentCollection.java:589)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:264)
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:585)
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:149)
at org.hibernate.collection.internal.PersistentBag.iterator(PersistentBag.java:387)
As part of migration, I have updated
Hibernate version
Hibernate5.LocalSessionFactoryBean
Hibernate5.HibernateTransactionManager
If I revert back above mentioned changes for Hibernate4, the code works fine in Multi-Threaded Pool, but throws ConcurrentModificationException with above updates.
I am sure I must be missing something very silly OR some setting which needs to be added as part of Hibernate 5 migration.
Any suggestion is greatly appreciated.
Thanks in advance.
An Hibernate Session and the objects loaded from that session, altogether, are not thread safe. So you cannot load objects from a session and then use these objects in different threads.
Among other problems these objects might trigger the initialization of lazy collection/proxies, which ultimately falls on the underlying JDBC connection and that connection is not thread safe either.
You need to give each thread it's own session and you must not share objects loaded from sessions between threads
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="DataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>
<prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
<prop key="hibernate.generate_statistics">${hibernate.generate_statistics}</prop>
<prop key="org.hibernate.cache.ehcache.configurationResourceName">classpath:hibernate-ehcache.xml</prop>
<prop key="cache.provider_class">${cache.provider_class}</prop>
<prop key="hibernate.cache.region.factory_class">${hibernate.cache.region.factory_class}</prop>
<prop key="hibernate.enable_lazy_load_no_trans">true</prop>
</props>
</property>
</bean>
<!-- Hibernate template for hibernateSessionFactory -->
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate4.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- Transaction Manager for hibernateSessionFactory -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="dataSource" ref="DataSource" />
<property name="sessionFactory" ref="sessionFactory" />
</bean>
Above is the Hibernate config for the spring boot application. We have addition added the following c3po config. But still the connection pool is getting maxed out.
<bean id="DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClassName}"></property name>
<property name="jdbcUrl" value="${ondot.jdbc.url}"></property name>
<property name="user" value="${jdbc.user}"></property name>
<property name="password" value="${jdbc.password}"></property name>
<property name="initialPoolSize" value="${initialPoolSize}" /></property name>
<property name="minPoolSize" value="${minPoolSize}"></property name>
<property name="maxPoolSize" value="${maxPoolSize}"></property name>
<property name="acquireIncrement" value="${acquireIncrement}"></property name>
<property name="maxStatements" value="${maxStatements}"></property name>
<property name="acquireRetryAttempts" value="${acquireRetryAttempts}"></property name>
<property name="acquireRetryDelay" value="${acquireRetryDelay}"> </property name>
<property name="breakAfterAcquireFailure"
value="${breakAfterAcquireFailure}"></property name>
<property name="maxIdleTime" value="${maxIdleTime}"> </property name>
and following is the property file:
hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
hibernate.show_sql=true
hibernate.format_sql=true
hibernate.cache.use_second_level_cache=true
hibernate.cache.use_query_cache=true
hibernate.generate_statistics=true
cache.provider_class=org.hibernate.cache.EhCacheProvider
initialPoolSize=5
minPoolSize=100
maxPoolSize=250
acquireIncrement=5
maxStatements=100
acquireRetryAttempts=10
acquireRetryDelay=1000
breakAfterAcquireFailure=false
maxIdleTime=1800
The session factory is autowired and a simple code with Open and close session is written.
public class BasicAunthenticationImpl {
private static SessionFactory sessionFactory;
public static SessionFactory getSessionFactory()
{
return sessionFactory;
}
public static void setSessionFactory(SessionFactory sessionFactory)
{
BasicAunthenticationImpl.sessionFactory = sessionFactory;
}
}
public class Module1
{
#Autowired
private SessionFactory sessionFactory;
private Session session = null;
#Override
public void process(List<RoutableModuleData> routableProcessObjects)
throws OndotException
{
try
{
session = sessionFactory.openSession();
session.flush();
canonicalMessage =
lookupprocesser.processInput(canonicalMessage,
Constants.L1_LOOKUP_CACHE, session);
}
catch (Exception Ex)
{
}
finally
{
if (session != null && session.isOpen()){
session.close();
}
}
}
}
public class Lookupprocesser{
public CanonicalMessage processInput(CanonicalMessage canonicalMessage,
String cacheLookup, Session session) throws DataInsightsCommonException
{
lookupSearchForL1(canonicalMessage, session, cacheLookup);
return canonicalMessage;
}
}
public class Query{
public List<TerminalData> searchByMatchKey1AndMatchKey2(Session
session, String matchKey1, String matchKey2) throws
DataInsightsCommonException
{
Query query;
List<Data> t = null;
query = session.createQuery("from Data as odt where odt.Key1 is
null and odt.Key2 = :Key2");
query.setParameter(Constants.KEY2, Key2);
query.setCacheable(true);
terminals = (List<Data>) query.list();
return (null != t && !t.isEmpty()) ? t : null;
}
}
The Session object is shared among all classes and object, I edited the code below , BasicAuth class creates the SessionFactory
The Module1 will call LookupProcessor and which will call the query class. We are closing the session on the Module1.
I'm making the maintenance of a app with Struts 1, Spring 3 and Hibernate 3.
I want join two services, but each service have 1 transaction. The solution that i am thinking is make 1 service with 1 transaction that include the two services. It's possible this?
-The transaction located in the DAO's.
*Service Expediente:
public void saveExpedienteCoactivo(CoaTExpc coaTExpc, Auditoria auditoria, String numeracionAutomaticaExpediente) throws Exception, BusinessException{
IExpedienteCoactivoDAO dao = (IExpedienteCoactivoDAO)getDao();
try{
//business rules
dao.saveExpedienteCoactivo(coaTExpc, numeracionAutomaticaExpediente);
catch{...}
}
*DAO Expediente:
public synchronized void saveExpedienteCoactivo(CoaTExpc coaTExpc, String numeracionAutomaticaExpediente) throws Exception {
Session sessionHibernate = this.getSessionFactory().getCurrentSession();
Savepoint savePoint = sessionHibernate.connection().setSavepoint();
try{
sessionHibernate.saveOrUpdate(coaTExpc);
sessionHibernate.connection().commit();
}catch(Exception e) {
sessionHibernate.connection().rollback(savePoint);
sessionHibernate.getTransaction().rollback();
System.out.println(this.getClass().getName()+", Error="+e);
throw new Exception(e);
}
}
*Service Resolucion:
public void saveResolucion(CoaTRcoa coaTRcoa, Auditoria auditoria) throws Exception, BusinessException{
IResolucionDAO dao = (IResolucionDAO)getDao();
try{
//business rules
dao.saveResolucion(coaTRcoa);
}catch{...}
}
*DAO Resolucion:
public synchronized void saveResolucion(CoaTRcoa coaTRcoa) throws Exception {
Session sessionHibernate = this.getSessionFactory().getCurrentSession();
Savepoint savePoint = sessionHibernate.connection().setSavepoint();
try{
//more code and sql here
sessionHibernate.saveOrUpdate(coaTRcoa);
//more code sql
sessionHibernate.connection().commit();
}catch(Exception e) {
sessionHibernate.connection().rollback(savePoint);
sessionHibernate.getTransaction().rollback();
System.out.println(this.getClass().getName()+", Error="+e);
throw new Exception(e);
}
}
*applicationContext.xml:
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref local="dataSource"/>
</property>
<property name="mappingDirectoryLocations">
<list>
<value>classpath:gob/osinerg/spjc/configuracion/domain/mapping</value>
<value>classpath:gob/osinerg/spjc/notificaciones/domain/mapping</value>
<value>classpath:gob/osinerg/spjc/judicial/domain/mapping</value>
<value>classpath:gob/osinerg/spjc/coactiva/domain/mapping</value>
<value>classpath:gob/osinerg/spjc/common/domain/mapping</value>
<value>classpath:gob/osinerg/alfresco/domain/mapping</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory"/>
</property>
</bean>
<bean id="txProxyTemplate" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref local="transactionManager"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
Now, It's possible this?
public class ServiceTransactionImp implements ServiceTransaction{
public void doTwoSaveTransaction(){
Session sessionHibernate = this.getSessionFactory().getCurrentSession();
Savepoint savePoint = sessionHibernate.connection().setSavepoint();
try{
serviceExpediente.saveExpedienteCoactivo(coaTExpc,auditoria,numeracionAutomaticaExpediente);
serviceResolucion.saveResolucion(coaTRcoa,auditoria);
sessionHibernate.connection().commit();
}catch(Exception e) {
sessionHibernate.connection().rollback(savePoint);
sessionHibernate.getTransaction().rollback();
System.out.println(this.getClass().getName()+", Error="+e);
throw new Exception(e);
}
}
I'm not sure if it works, because the session is distinct between the proceses and if the possible rollback of saveResolucion will affect to the service of saveExpedienteCoactivo as have a commit(); the idea is execute rollback to all the proceses.
Or any other solution?
Want to use Spring to automatically work with Hibernate 4 sessions
Also I like to extends DAO, for not create many DAO for many entities
But there is problem:
SessionDAO.java
public abstract class SessionDAO extends HibernateDaoSupport{
public void startSession() {
getSession().beginTransaction();
}
public void closeSession() {
getSession().getTransaction().commit();
}
public void addObject() {
startSession();
getSession().save(this);
closeSession();
}
public Session getSession()
{
return getHibernateTemplate().getSessionFactory().getCurrentSession();
}
}
Values.java
#Entity
#Table
public class Values extends SessionDAO {
private int valuesId;
private double amount;
private Date date;
//...getters, setters, etc
}
dispatcher-servlet.xml
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>entity.Crypto</value>
<value>entity.Values</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="dataSource"
class="org.apache.tomcat.dbcp.dbcp.BasicDataSource">
<property name="driverClassName" value="oracle.jdbc.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:#my.****.us-east-1.rds.amazonaws.com:1521:ORCL" />
<property name="username" value="****" />
<property name="password" value="****" />
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="persistenceExceptionTranslationPostProcessor"
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
When start server, receive:
INFO: HHH000206: hibernate.properties not found
When try to load page receive:
SEVERE: Servlet.service() for servlet [dispatcher] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
java.lang.NullPointerException
on line
return getHibernateTemplate().getSessionFactory().getCurrentSession();
What's wrong?
Don't get the session by extend HibernateDaoSupport, just inject SessionFactory in DAO.
private HibernateTemplate hibernateTemplate;
public void setSessionFactory(SessionFactory sessionFactory) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
I have a Using c3p0 0.9.1.2 , hibernate 3.2.1.ga and spring 2.5.5. The problem is the database connection doesn't close itself. Here are the logs :
[22 mars 2012 12:29:56,091] DEBUG com.mchange.v2.resourcepool.BasicResourcePool ["http-apr-8080"-exec-4] acquire test -- pool is already maxed out. [managed: 20; max: 20]
[22 mars 2012 12:29:56,091] DEBUG com.mchange.v2.resourcepool.BasicResourcePool ["http-apr-8080"-exec-4] awaitAvailable(): com.mchange.v2.c3p0.impl.NewPooledConnection#15cc604
[22 mars 2012 12:29:56,091] DEBUG com.mchange.v2.resourcepool.BasicResourcePool ["http-apr-8080"-exec-4] trace com.mchange.v2.resourcepool.BasicResourcePool#6b0524 [managed: 20, unused: 0, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection#15cc604)
Here's the datasource configuration :
<!-- Local DataSource that works in any environment -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${database.driver}"/>
<property name="jdbcUrl" value="${database.url}"/>
<property name="user" value="${database.user}"/>
<property name="password" value="${database.password}"/>
<!--<property name="connectionCustomizerClassName" value="org.xxx.webapp.common.persistence.WatchConnectionCustomizer"/>-->
<property name="maxStatements" value="500"/>
<property name="maxIdleTime" value="1800"/>
<property name="maxPoolSize" value="100"/>
<property name="minPoolSize" value="2"/>
<property name="initialPoolSize" value="2"/>
<property name="acquireIncrement" value="3"/>
<property name="idleConnectionTestPeriod" value="3000"/>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" >
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
<prop key="hibernate.connection.autocommit">${hibernate.connection.autocommit}</prop>
<prop key="hibernate.transaction.auto_close_session">${hibernate.transaction.auto_close_session}</prop>
<prop key="hibernate.connection.release_mode">${hibernate.connection.release_mode}</prop>
<prop key="hibernate.bytecode.use_reflection_optimizer">${hibernate.bytecode.use_reflection_optimizer}</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.region.factory_class">net.sf.ehcache.hibernate.EhCacheRegionFactory</prop>
</props>
</property>
<property name="annotatedClasses">
<list>
...
</list>
</property>
<property name="dataSource">
<ref bean="dataSource" />
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
Here's our generic Dao
public class GenericDAO<T, PK extends Serializable> extends HibernateDaoSupport
implements IGenericDAO<T, PK> {
private Class<T> clazz;
private Logger logger = Logger.getLogger(GenericDAO.class);
private static Session session;
public GenericDAO(Class<T> clazz) {
this.clazz = clazz;
}
public void refresh(T instanceToRefresh) throws DataAccessException {
getHibernateTemplate().refresh(instanceToRefresh);
//getCurrentSession().refresh(instanceToRefresh);
}
public void saveOrUpdate(T instanceToSaveOrUpdate)
throws DataAccessException {
//getCurrentSession().saveOrUpdate(instanceToSaveOrUpdate);
getHibernateTemplate().saveOrUpdate(instanceToSaveOrUpdate);
}
public void persist(T instanceToPersist) throws DataAccessException {
getHibernateTemplate().persist(instanceToPersist);
//getCurrentSession().persist(instanceToPersist);
}
#SuppressWarnings("unchecked")
public T merge(T instanceToMerge) throws DataAccessException {
T instanceMerged = (T) getHibernateTemplate().merge(instanceToMerge);
//T instanceMerged = (T) getCurrentSession().merge(instanceToMerge);
return instanceMerged;
}
#SuppressWarnings("unchecked")
public PK save(T newInstance) throws DataAccessException {
return (PK) getHibernateTemplate().save(newInstance);
//return (PK) getCurrentSession().save(newInstance);
}
public void delete(T persistentObject) throws DataAccessException {
getHibernateTemplate().delete(persistentObject);
//getCurrentSession().delete(persistentObject);
}
#SuppressWarnings("unchecked")
public T load(PK id) {
return (T) getHibernateTemplate().get(clazz, id);
//return (T) getCurrentSession().get(clazz, id);
}
public void update(T transientObject) throws DataAccessException {
//getCurrentSession().update(transientObject);
getHibernateTemplate().update(transientObject);
}
#SuppressWarnings("unchecked")
public List<T> loadAll() throws DataAccessException {
//Session session = this.getCurrentSession();
//return session.createQuery("from " + clazz.getName()).list();
return getHibernateTemplate().loadAll(clazz);
}
}
Thanks in advance.
Normally, the connection is automatically closed by hibernate. However, a few things to note:
long-running transactions may occupy a connection
improper session management may mean you don't close your session, which in turn means the connection remains in use
The typical setup when using spring is to annotate your service methods with #Transactional. That way spring will manage your transactions and sessions.
We have used the following line in the dispatcher-servlet.xml file and database physical connections are now closing.
<tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager"/>