I am new in Hibernate currently want to implement the Hibernate Template classes , any one please tell me about the Hibernate Template classes.
xml file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/test" />
<property name="username" value="root" />
<property name="password" value="mnrpass" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mappingResources">
<list>
<value>employee.hbm.xml</value>
</list>
</property>
<property name="configLocation" value="classpath:hibernate.cfg.xml" />
</bean>
<bean id="springHibernateExample" class="com.javarticles.spring.hibernate.SpringHibernateExample">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
Copied from Hibernate Interview Questions:
Hibernate Template
When Spring and Hibernate integration started, Spring ORM provided two
helper classes – HibernateDaoSupport and HibernateTemplate. The reason
to use them was to get the Session from Hibernate and get the benefit
of Spring transaction management. However from Hibernate 3.0.1, we can
use SessionFactory getCurrentSession() method to get the current
session and use it to get the spring transaction management benefits.
If you go through above examples, you will see how easy it is and
that’s why we should not use these classes anymore.
One other benefit of HibernateTemplate was exception translation but that can be achieved easily by using #Repository annotation with
service classes, shown in above spring mvc example. This is a trick
question to judge your knowledge and whether you are aware of recent
developments or not.
HibernateTemplate is a helper class that is used to simplify the data access code. This class supports automatically converts HibernateExceptions which is a checked exception into DataAccessExceptions which is an unchecked exception. HibernateTemplate is typically used to implement data access or business logic services. The central method is execute(), that supports the Hibernate code that implements HibernateCallback interface.
Define HibernateTemplate.
org.springframework.orm.hibernate.HibernateTemplate is a helper class which provides different methods for querying/retrieving data from the database. It also converts checked HibernateExceptions into unchecked DataAccessExceptions.
HibernateTemplate benefits :
HibernateTemplate simplifies interactions with Hibernate Session.
The functions that are common are simplified to single method calls.
The sessions get automatically closed.
The exceptions get automatically caught and are converted to runtime exceptions.
Visit this link for the proper example
http://www.javarticles.com/2015/04/spring-hibernatetempate-example.html
HibernateTemplate is the class of org.springframework.orm.hibernate3. HibernateTemplate provides the integration of hibernate and spring. Spring manages database connection DML, DDL etc commands by itself. HibernateTemplate has the methods like save,update, delete etc.
Try to understand how to configure HibernateTemplate in our spring application.
Add xml configuration in application.xml of spring application.
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
hibernateTemplate will be used in the dao classes. Initialize hibernateTemplate. Provide a setter method to set hibernateTemplate by spring.
private HibernateTemplate hibernateTemplate;
public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
this.hibernateTemplate = hibernateTemplate;
}
public void persist(){
User u1= new User(1,"Ankita");
hibernateTemplate.save(u1);
User u2= new User(2,"Renu");
hibernateTemplate.save(u2);
}
Related
I have working code that saves entity to DB with using EJB+JPA+Hibernate. Now I need to change EJB to Spring.
Below is my simplified manager class.
//#Stateless - changed to #Service
#Service
public class Manager {
//#EJB - changed to Autowired
#Autowired
private ClientDao clientDao;
public void addClient(Client client) {
clientDao.addClient(client);
}
}
Below is my DAO class.
//#Stateless - changed to #Repository
#Repository
public class JpaClientDao implements ClientDao {
#PersistenceContext(unitName="ClientsService")
private EntityManager em;
public void addClient(Client client) {
em.persist(client);
}
}
Below is persistence.xml.
<?xml version="1.0" encoding="UTF-8"?>
<persistence 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_2_0.xsd"
version="2.0">
<persistence-unit name="ClientsService" transaction-type = "JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<jta-data-source>myJtaDatabase</jta-data-source>
<class>com.entity.Client</class>
<properties>
<property name="hibernate.archive.autodetection" value="class"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
</persistence>
applicationContext.xml
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:component-scan base-package="com" />
<context:annotation-config/>
</beans>
resoures.xml
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<Resource id="myJtaDatabase" type="DataSource">
JdbcDriver org.apache.derby.jdbc.ClientDriver
JdbcUrl jdbc:derby://localhost:1527/C:/ClientDB
UserName test
Password 123456
validationQuery = SELECT 1
JtaManaged true
</Resource>
</resources>
Questions.
1) When I used EJB, I had Container-Managed Transactions. Who should manage transactions with using Spring?
2) Do I need to necessarily use Spring Framework transaction management? Is there any alternatives?
I found some examples like this http://www.codingpedia.org/ama/java-persistence-example-with-spring-jpa2-and-hibernate/, and I cant undestand is code below spring specific or it suits for me.
<!-- ************ JPA configuration *********** -->
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath:config/persistence-demo.xml" />
<property name="dataSource" ref="restDemoDS" />
<property name="packagesToScan" value="org.codingpedia.demo.*" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
</bean>
</property>
</bean>
3) Do I need to edit Java code or should my steps be in xml configuration?
Any useful links are encouraged.
1) When I used EJB, I had Container-Managed Transactions. Who should
manage transactions with using Spring?
Answer : Spring provides container managed transaction support too (See JTA transaction manager , sample oracle article) and also application managed transaction (which means your application can declaratively/programatically manage the transactions with minimal effort by using Spring transaction API ) . See Spring transaction doc
2) Do I need to necessarily use Spring Framework transaction
management? Is there any alternatives?
Answer: If spring framework is not managing your transactions, then your container will need to manage them..you have alternatives of any Java EE JTA implementations like opensource JBossTS or enterprise JTA implementations Oracle-WebLogicJtaTransactionManager or IBM-WebSphereUowTransactionManager, you can find how to use them in the same point 1 spring documentation. You can even have your own transaction manager implemented.
But if you are already using Spring framework why not benefit from spring transaction management with plenty of configurations possible, (Spring + Hibernate transaction manager, Spring + JPAContainerManager, Spring+ JTAContainerManager etc..)
3) Do I need to edit Java code or should my steps be in xml
configuration?
Answer: Your transcation manager xml config seems fine to use a JpaTransactionManager, now you can initiate transactions in your service layer java code by annotating #Transactional which typically handles your service methods to participate in a transaction according to the configured transaction manager.
#Service
#org.springframework.transaction.annotation.Transactional
public class Manager {
Example of spring configuration file:
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory"ref="entityManagerFactory"/>
<property name="jpaDialect"ref="jpaDialect"/>
</bean>
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
....
</bean>
and the persistence.xml jpa file:
<persistence-unit name="EmployeeService">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
</persistence-unit>
As you can see the jpa provider-related information is set 3 times. In transaction manager bean, entity manager factory bean and in the persistence unit configuration:
<property name="jpaDialect"ref="jpaDialect"/>
...
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
...
<provider>org.hibernate.ejb.HibernatePersistence</provider>
But actually in my project I configured only the persistence unit with provider. And it worked.
So my question is what's the difference between provider, dialect and vendor options?
Must I set all of them or, I can skip some of them?
Can I set, for example as a vendor for EntityMangerFactory - Hibernate, as a dialect in transaction manager - Eclipse and as a provider in the persistence unit configuration - something else, TopLink, for example.
It's no clear to me. Please explain.
Will try to explain it to you line by line:
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
//Should ideally be
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
This bean defines the jpaDialect that you are going to use. JpaDialect is an interface encapsulates certain functionality that standard JPA 1.0 does not offer, such as access to the underlying JDBC Connection. This strategy is mainly intended for standalone usage of a JPA provider; most of its functionality is not relevant when running with JTA transactions.
Also allows for the provision of value-added methods for portable yet more capable EntityManager and EntityManagerFactory subinterfaces offered by Spring.
Since you have provided the class as class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>, this allows Spring to plug in vendor-specific behavior into Spring's EntityManagerFactory creators and it serves as single configuration point for all vendor-specific properties.It's a custom implementation of spring's own JpaVendorAdapter.
For the second bean where you have declared:
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory"ref="entityManagerFactory"/>
<property name="jpaDialect"ref="jpaDialect"/>
</bean>
You tell 'Spring' to configure a transactionManager whose properties are entityManagerFactory and jpaDialect. Since these properties have to specific to hibernate these are set according. The entityManagerFactory and jpaDialect are now set specifically to hibernate (or Vendor).
As for the third bean
<property name="jpaDialect"ref="jpaDialect"/>
...
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
...
<provider>org.hibernate.ejb.HibernatePersistence</provider>
The <provider> tells spring to use the hibernate provider and the class org.hibernate.ejb.HibernatePersistence is Hibernate EJB3 persistence provider implementation.
In short, you need to configure these in order to tell spring which ORM's functionality should be used.
The reason that your application worked with configuring just persistence and provider is because the vendor adapter is automatically passed the persistence provided i.e. HibernatePersistence via the getPersistenceProvider in JpaVendorAdapter.
Tinker around the documentation to understand how these classes are interlinked.
EDIT : As pointed out by #TheKojuEffect , the first bean should ideally be in the form of :
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
Thanks. Missed the vendorAdapter.
You can refer :
HibernateJpaDialect
HibernateVendorAdapter
HibernatePersistence
Hope it helps. :)
I tried to shorten this to what I think is relevant, I hope it's sufficient and not overwhelming. Please help!
I'm converting a small wicket+databinder+hibernate web application to use wicket+spring+hibernate. I have a DAO service class, with a hibernate SessionFactory injected by Spring. I am able to do read-only operations using the session factory (autocommit is on by default). What I want to do is use the HibernateTransactionManager and the #Transactional annotation to do a transactional operation.
I define a DAO service implementation, which uses an injected SessionFactory in a method marked #Transactional:
public class DAO implements IDAO {
#SpringBean
private SessionFactory sessionFactory;
public DAO() {
super();
}
#Transactional
public Object execute(SessionUnit sessionUnit) {
Session sess = sessionFactory.getCurrentSession();
Object result;
result = sessionUnit.run(sess);
sess.flush();
return result;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
#Transactional
public boolean isObjectPersistent(Object object) {
return sessionFactory.getCurrentSession().contains(object);
}
}
When I try to call isObjectPersistent(), I get a hibernate exception because no one has called session.beginTransaction():
Caused by: org.hibernate.HibernateException: contains is not valid without active transaction
at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:338)
at $Proxy38.contains(Unknown Source)
at com.gorkwobbler.shadowrun.karma.db.hibernate.DAO.isObjectPersistent(DAO.java:35)
(reflection stuff omitted...)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
(reflection stuff omitted...)
at org.apache.wicket.proxy.LazyInitProxyFactory$JdkHandler.invoke(LazyInitProxyFactory.java:416)
at org.apache.wicket.proxy.$Proxy36.isObjectPersistent(Unknown Source)
I also notice from the full stack trace that the OpenSessionInViewFilter is being invoked, I'm not sure if that's relevant. Let me know if you need the rest of the stack trace.
If I create a custom WebRequestCycle subclass, which begins a transaction, I can get past this. This seems to me to undermine the purpose of #Transactional, and my implementation of it also turned out to be problematic.
Here is my applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Reference: http://wicketinaction.com/2009/06/wicketspringhibernate-configuration/ -->
<beans default-autowire="autodetect"
xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<!-- bean definitions -->
<bean id="wicketApplication" class="com.gorkwobbler.shadowrun.karma.view.wicket.core.WicketApplication" />
<bean id="placeholderConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="false" />
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="ignoreResourceNotFound" value="false" />
<property name="locations">
<list>
<value>classpath*:/application.properties</value>
</list>
</property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName">
<value>${jdbc.driver}</value>
</property>
<property name="url">
<value>${jdbc.url}</value>
</property>
<property name="username">
<value>${jdbc.username}</value>
</property>
<property name="password">
<value>${jdbc.password}</value>
</property>
</bean>
<tx:annotation-driven transaction-manager="txManager" />
<!-- setup transaction manager -->
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<!-- hibernate session factory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="configLocation">
<value>classpath:/hibernate.cfg.xml</value>
</property>
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>
</props>
</property>
<property name="packagesToScan">
<list>
<value>com.gorkwobbler.shadowrun.karma.domain</value>
<value>com.gorkwobbler.shadowrun.karma.domain.*</value>
</list>
</property>
</bean>
<bean id="dao"
class="com.gorkwobbler.shadowrun.karma.db.hibernate.DAO">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<!-- Don't know what this is for, but it was in the sample config I started from -->
<!-- <context:component-scan base-package="com.gorkwobbler.shadowrun.karma" /> -->
</beans>
How can I get my DAO to begin a transaction, commit at the end of that method, or rollback on error? I want to use the most minimal/standard configuration possible; I prefer annotations over XML if given the choice.
Edit:
I revised the applicationContext above to remove the AOP configuration stuff, which wasn't working, anyway.
Using the debugger, I determined that the SessionImpl stored in the TransactionInterceptor's session holder map is not the same session as the SessionImpl that is retrieved in the DAO method when I call sessionFactory.getCurrentSession(). Can anyone explain why this is? What am I doing wrong? The magic is not working. =(
Edit
I also notice the following message in my console during startup:
WARN - stractEhcacheRegionFactory - No TransactionManagerLookup found in Hibernate config, XA Caches will be participating in the two-phase commit!
It turns out that the problem was not actually in the configuration information that I posted. Sorry!
My above configuration links to an externalized hibernate.cfg.xml, which declared the following property:
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
I must've copied this from some sample hibernate config file somewhere. This property caused my SessionFactory to ignore the session context provided by spring, and use a thread-local context in its place. Removing this property fixed the problem (hibernate uses the JTA context by default if none is specified).
This can be made much simpler. Read this section 13.3.3 (Hibernate) Declarative transaction demarcation, especially the last part. This is usually enough configuration if you use #Transactional:
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<!-- SessionFactory, DataSource, etc. omitted -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<tx:annotation-driven/>
<bean id="myProductService" class="product.SimpleProductService">
<property name="productDao" ref="myProductDao"/>
</bean>
</beans>
To answer your comments:
No, if you inject the components via Spring, Spring does the wiring, hibernate doesn't need to know anything about spring, that's the whole point of using spring (to decouple the individual layers). Service and dao is a separation that not everybody uses. The important part is that the public methods backed by the interface are marked as transactional, because all methods marked as transactional will be intercepted by a proxy that does the transaction handling, while others won't.
You may want to read the general section about Declarative Transaction Managmenet in Spring to understand the process (this applies to all transactional technologies, not just to hibernate).
I posted this to the spring forums, sorry for the xpost.
I am new to spring. I am working on an existing project that uses spring 1.2.8 (old, I know), and java 1.5 so annotations should work.
I am trying to use the #Transactional annotation on a concrete class, following the docs at: http://static.springsource.org/spring/docs/1.2.8/reference/transaction.html#d0e6062
So I have something like so:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="DataSource"/>
</bean>
<bean id="MyDAO"
class="com.company.package.dao.spring.MyDAOImpl">
<property name="dataSource" ref="DataSource" />
</bean>
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
<bean class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
<property name="transactionInterceptor" ref="txInterceptor"/>
</bean>
<bean id="txInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributeSource">
<bean class="org.springframework.transaction.annotation.AnnotationTransactionAttributeSource"/>
</property>
</bean>
and I annotate my class:
#Transactional(propagation = Propagation.REQUIRED)
public class MyDAOImpl extends JdbcDaoSupport implements MyDAO{
...
}
When I run it I can see in my debug logs that spring is finding all of the classes:
Code:
01-07-10 12:10:45 DEBUG [DefaultXmlBeanDefinitionParser] Neither XML 'id' nor 'name' specified - using generated bean name [org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator]
01-07-10 12:10:45 DEBUG [DefaultXmlBeanDefinitionParser] Neither XML 'id' nor 'name' specified - using generated bean name [org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor]
01-07-10 12:10:45 DEBUG [DefaultXmlBeanDefinitionParser] Neither XML 'id' nor 'name' specified - using generated bean name [org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#329f3d]
but after that there is no mention of annotations or transactions. I don't even know if there are supposed to be. I am verifying in my mysql log that the queries are not being performed transactionally.
Any ideas?
One thing that I frequently overlook is that the proxy can only intercept calls if they are made from outside the class itself: If you have one method calling a transactional method in the same class, it will not be wrapped by the proxy. But that's when individual methods are annotated, not the whole class, so it's probably not what's causing your problem.
Ignore the DEBUG lines (they just say you havent specified id or name you just have a bean class="")
Have you put the line,
<tx:annotation-driven transaction-manager="transactionManager" />
You also need to add the schemaLocation at the top something like
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
</beans>
Otherwise the annotations dont get processed :)
This question is similar to a previous one. I am trying to #Autowire a Hibernate Session in one of my Spring-JUnit-Transactional tests but I am getting this exception:
java.lang.IllegalStateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional ...
Here is my JUnit class:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations={"/applicationContext.xml"})
#TransactionConfiguration(transactionManager="transactionManager")
#Transactional
public class MyTest {
#Qualifier("session")
#Autowired
private Session session;
#Test
public void testSomething() {
session.get(User.class, "me#here.com");
}
}
Every works fine if I #Autowire a SessionFactory and get my Session programmatically (instead of defining it in the Spring XML) like so:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations={"/applicationContext.xml"})
#TransactionConfiguration(transactionManager="transactionManager")
#Transactional
public class MyTest{
#Qualifier("sessionFactory")
#Autowired
private SessionFactory sessionFactory;
#Test
public void testSomething() {
Session session = SessionFactoryUtils.getSession(sessionFactory, false);
session.get(User.class, "me#here.com");
}
}
I can, however, get my original example to work if I define my Session in my Spring XML with <aop:scoped-proxy /> like so:
<?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:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
">
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
...
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation"><value>classpath:/hibernate.cfg.xml</value></property>
<property name="configurationClass">
<value>org.hibernate.cfg.AnnotationConfiguration</value>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="session" class="org.springframework.orm.hibernate3.SessionFactoryUtils" factory-method="getSession" scope="prototype">
<constructor-arg ref="sessionFactory" />
<constructor-arg value="false" />
<!-- This is seems to be needed to get rid of the 'No Hibernate Session' error' -->
<aop:scoped-proxy />
</bean>
</beans>
My question is: Why is <aop:scoped-proxy /> needed given that there should only one thread-bounded transaction context in my unit test? What is the proper way to define my Hibernate Session bean?
SessionFactoryUtils.getSession() is as good as any other way of getting the Session. It does the same thing HibernateDaoSupport.getSession() would do.
The reason you need scoped-proxy is because of timing. Without the scoped-proxy it seems that it is injecting the Session before the test begins and thus before the transaction begins and so you get the errors.
By adding the scoped-proxy it proxies the Session and injects that so it does not inject the actual session upfront (before the transaction starts) but only fetches it and makes calls on it once the test is running, when it actually needs to make a call against it.
I think the "proper" way is the injection of the SessionFactory, and programmatically fetching the Session from it. The reason that you're getting the exception is down to the documented behaviour of SessionFactoryUtils.getSession():
Get a Hibernate Session for the given
SessionFactory. Is aware of and will
return any existing corresponding
Session bound to the current thread,
for example when using
HibernateTransactionManager. Will
create a new Session otherwise, if
"allowCreate" is true.
Since nothing has bound a session to the current transaction, it fails.
My suggestion would be to use HibernateTemplate - define one in your context, and autowire that into your test. HibernateTemplate has most of the same operations as a war Session, but does the session handling bit for you. You should just be able to do:
hibernateTemplate.get(User.class, "me#here.com");