I work with Spring 3.1 + Hibernate 4.
I've created the following sessionFactory:
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">validate</prop>
</props>
</property>
<property name="packagesToScan" value="com.my.company"/>
</bean>
As you see, the above sessionFactory is for Hibernate 4.
I am trying to crate a HibernateTemplate (org.springframework.orm.hibernate3.HibernateTemplate) through Java code, by that sessionFactory, but I am not sure how to do this.
I've tried the following code:
#Resource(name="sessionFactory")
public void setSessionFactory(LocalSessionFactoryBean sessionFactory) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory.getObject());
}
But I'm getting the following error message:
org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'sessionFactory' must be of type [org.springframework.orm.hibernate4.LocalSessionFactoryBean], but was actually of type [org.hibernate.internal.SessionFactoryImpl]
Could you show how to do this?
As from this post:
HibernateTemplate isn't recommended for use anymore (about since the
release of hibernate 3.0.1) there is no more added value so that isn't
going to be in there anymore for hibernate 4. Simply use the plain
SessionFactory and use the getCurrentSession method to obtain the
current transactional session (don't use openSession!!!!) and you are
good to go...
From the javadoc of package org.springframework.orm.hibernate4:
Contains an implementation of Spring's transaction SPI for local
Hibernate transactions. This package is intentionally rather minimal,
with no template classes or the like, in order to follow native
Hibernate recommendations as closely as possible.
You don,t need to extends any hibernate dao support class in latest version of spring. You can directly inject hibernate sessionfactory from xml/java based configuration. And it also need to be injected into transaction manger. Refer this link for better understanding:
http://hantsy.blogspot.in/2013/07/use-native-hibernate-4-api.html
Related
I have some issues after changing my backend from Hibernate to JPA (+Hibernate). I am using Websphere and container transaction management through org.springframework.transaction.jta.WebSphereUowTransactionManager. Some operations don't behave as expected:
DELETE OPERATION: If I don't flush the EntityManager manually it won't issue the delete, nothing happens actually.
#Transactional
#Override
public void deleteApplication(Integer appId) {
Application app = appDAO.findOne(appId);
//em.flush(); to force the flush(), otherwise it doesn't do anything
appDAO.delete(app);
}
INSERT WITH CASCADE OPERATION: The Application entity has a N:M relation with Attribute. I try to persist an Application with some Attribute added to its Application.attributes List. Right after the appDAO.save() I see a insert into Application sentence. However, there are never any inserts for the cascaded Attributes into the join table. Again, I need to manually flush() the em to issue de sql statements left.
#Transactional
#Override
public Application createApplication(Application application) {
appDAO.save(application);
//em.flush(); Needed to force the cascade into the join table
return application
}
I have tried changing the transactionManager for a non-container-managed one (org.springframework.orm.jpa.JpaTransactionManager) and it works perfectly without needing to use manual flush.
I am not using the persistence.xml file, following the approach introduced in Spring 3.1 (jtaDataSource + packagesToScan). However I have also tried with the traditional config with a persistence.xml file and I experienced the same wrong behaviour.
¿Any suggestions?
My setup:
<bean id="mainEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="mainPersistenceUnit"/>
<property name="jtaDataSource" ref="mainDataSource"/>
<property name="packagesToScan" ref="packages-mainEntityManagerFactory"/>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.WebSphereExtendedJTATransactionLookup</prop>
<prop key="hibernate.current_session_context_class">jta</prop>
<prop key="hibernate.transaction.flush_before_completion">true</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">false</prop>
<prop key="hibernate.format_sql">false</prop>
<prop key="hibernate.transaction.factory_class">org.hibernate.transaction.CMTTransactionFactory</prop>
</props>
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
</property>
</bean>
<tx:annotation-driven order="0" />
<!-- Drives transactions using local JPA APIs -->
<bean name="transactionManager" class="org.springframework.transaction.jta.WebSphereUowTransactionManager"/>
In case someone has the same problem. The solution comes down to using
<prop key="hibernate.transaction.factory_class">org.hibernate.ejb.transaction.JoinableCMTTransactionFactory</prop>
instead of
<prop key="hibernate.transaction.factory_class">org.hibernate.transaction.CMTTransactionFactory</prop>
I'm used to have persistence.xml in my projects in which I define the provider to use (hibernate in most cases).
However, I'm starting a new project in which it is mandatory to use Spring framework. I've seen some blogs describing the integration of Hibernate in Spring and I've understood that I should declare a session factory in spring's beans descriptor org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean
All the examples I've seen don't mention the use of persistence.xml, persistence context, entity manager...
I'm not sure I understand this point, I always thought that Hibernate is just a provider of JPA unless the factory declared in application-context.xml is doing something in background. If it is the case, I would like to understand how it is working..
thanks in advance...
AnnotationSessionFactoryBean is Factory bean implemented by Spring to create Hibernate Session Factory and shared to Spring's Application Context.if you are planning to use Direct Hibernate ( in case you dont need persistent.xml / per-cont.xml / entityManager) you can provide the properties in AnnotationSession FactoryBean. and can be injected in Any DAO.
How ever if you are planing to wire through JPA. Then you need ( persistent and persistent-context and entity Manager). In order to do that you required three steps
1. declare / configure Spring's JPA Adapter to create EntityManager instance for you
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
Inside JPA Bean declaration provide details about your database and who is ORM provider such as ( hibernate /toplink / ....) in your case Hibernate
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="false" />
<property name="databasePlatform" value="org.hibernate.dialect.Oracle9Dialect"/>
</bean>
</property>
then Provide information about your persistent entity details in persistent.xml or some way
<property name="persistenceXmlLocation" value="classpath:persistence.xml" />
if you have any specific JPA properties then
<property name="jpaProperties">
<props>
<!-- <prop key="hibernate.cache.provider_class">
org.hibernate.cache.EhCacheProvider
</prop>
-->
<prop key="hibernate.format_sql">false</prop>
<prop key="hibernate.use_sql_comments">false</prop>
</props>
</property>
Bottom line, Spring provies adapters to directly to Hibernate ( in that case your dont need Jpa files such as persistent.xml and so but you need hibernate related files like hbm files) or adapters to the JPA ( in that case you have provide details about who is JPA vendor and instrut spring how to connect to the JPA vendor).
Hope the above clarifies.
I've got two Spring Hibernate modules that I'm trying to combine. They have separate application contexts. In one hibernate uses xml mapping files while in the second module annotations are used to map the hibernate db tables.
Both modules seem to be scanned ok (service beans seem to be injected ok) except for the hibernate table scanning in the second table. One table occurs twice -- once in the xml mapping files and once in annotations but in different java packages with separated package scanning.
When I try to access the second module's table class in a hibernate select I get:
MappingException: Unknown entity: msg.entity: message
I tried substituting another annotated table entity in the hibernate query to check where the problem was mapping to the same table but I get the same MappingException so it seems like the problem is that hibernate is just not picking up any #Entity #Table annotations in the second module. But I tested this module on it's own and all the annotations did get picked up ok.
Could it be that the hibernate session factory is somehow being carried over from the calling module and masking the second module's session factory and its associated list of entities? Yet I'm not in a transaction in the calling method.
<context:component-scan base-package="msg"/>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSourceJmsMod"/>
<property name="packagesToScan" value="msg.entity"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="javax.persistence.validation.mode">none</prop>
</props>
</property>
</bean>
Thanks for any help
I am in a rather nasty situation. We use compass for Hibernate search integration with Lucene and have implemented database directory search (using JdbcDirectory) instead of FSDirectoryProvider, RAMDirectoryProvider etc.
The problem is that the directory provider is passed as a property inside the META-INF/persistence.xml like the one below:
<property name="hibernate.search.default.directory_provider" value="uk.company.package.JdbcDirectoryProvider" />
We need to pass the database details to the the JdbcDirectoryProvider as JdbcDirectory requires a datasource to be passed.
We are constructing the datasource (for the directory provider) in an unconventional way using a property file (in the class path) with the database and index details.
If we have uk.company.JdbcDirectoryProvider configured as a spring bean, we can inject the datasource. This works well with Tomcat but not with OAS or Weblogic as still as we are passing the directory_provider in the persistence.xml. Probably becasue the datasource is initialized by the spring (becasue of the way classloaders work in these app servers).
My question is how can we configure the hibernate.search.default.directory_provider directly inside aSpring bean instead of the persistence.xml?
The closest place is:
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
But it only takes three properties:
<property name="showSql" value="true" />
<property name="generateDdl" value="false" />
<property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect" />
Solution
You could pass the hibernate properties in spring bean as jpaProperties
<property name="jpaProperties">
<props>
<prop key="hibernate.search.default.directory_provider">
uk.company.package.JdbcDirectoryProvider
</prop>
</props>
</property>
I found the solution.
You could pass the hibernate properties in spring bean as jpaProperties
<property name="jpaProperties">
<props>
<prop key="hibernate.search.default.directory_provider">
uk.company.package.JdbcDirectoryProvider
</prop>
</props>
</property>
I'm having some trouble migrating to hibernate 4 while using a JTA Transaction Manager.
Maybe you can help, cause I'm all out of ideas.
Software:
Spring: 3.1.1.RELEASE
Hibernate: 4.1.3.Final
Database: Oracle 11g
Application: Ejb 3.0 deployed in Websphere Application Server 7.0 (using #Interceptors(SpringBeanAutowiringInterceptor.class) to initialize the spring context)
Spring configuration:
<context:annotation-config />
<context:component-scan base-package="myServicePackage,myDaoPackage" />
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/MyDataSource" />
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="myModelPackage" />
<property name="mappingResources" value="queries.xml" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
</props>
</property>
</bean>
<tx:jta-transaction-manager />
<!-- <bean id="transactionManager" class="org.springframework.transaction.jta.WebSphereUowTransactionManager" /> -->
<tx:annotation-driven />
Service:
#Service
public class TradeService {
#Autowired
private TradeDao tradeDao;
}
Dao:
#Repository
#Transactional
public class TradeDao {
#Autowired
private SessionFactory sessionFactory;
public Trade getTrade(){
return (Trade) sessionFactory.getCurrentSession().getNamedQuery("get_trade").uniqueResult();
}
Throws:
org.hibernate.HibernateException: No Session found for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1041)
at myDaoPackage.TradeDao.getTrade(TradeDao.java:26)
Notes:
I've also tried using #Transactional on the service instead of the
dao. Same result.
Similar config, but using Spring 3.0.5.RELEASE, Hibernate 3.6.5.Final, and TradeDao extending HibernateDaoSupport works.
So, does anyone have any ideas?
I've been trying a lot of things all day today.
My head is spinning and I'm annoyed, so I must be missing something very simple, but at this point I can't really tell :)
I finally got this working.
As I was expecting I was missing just some small configuration :)
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.transaction.factory_class">org.hibernate.transaction.CMTTransactionFactory</prop>
<prop key="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.WebSphereExtendedJTATransactionLookup</prop>
</props>
</property>
I found these configuration options earlier while browsing, but for some reason they didn't work when I tried them. Probably I had something else wrong at that time... (see Transaction strategy configuration chapter)
Thank you all for trying to help!
It's probably much like the problem that this person was having: http://forum.springsource.org/showthread.php?121109-Transaction-Propagations-and-Hibernate-4
That is, HibernateDaoSupport (and, presumably, HibernateTemplate) was creating a Session if one wasn't found on the Thread, whereas it sounds like the new approach does not.
EDIT: I just realized that the included link is using a HibernateTransactionManager. I believe that if you use a JtaTransactionManager and do not use a HibernateTemplate, you have to manually apply advice around the target which creates a session.
It might also be something they missed in Spring: https://jira.springsource.org/browse/SPR-9404
By default the #Transactional annotation works on interfaces. Since you're going sans interface, you should add the proxy-target-class="true" attribute to the <tx:annotation-driven /> tag in your configuration.