I have this hibernate.transaction.manager_lookup_class property in my persistence.xml, Then i have this warning message when running my application.
Using deprecated org.hibernate.transaction.TransactionManagerLookup strategy [hibernate.transaction.manager_lookup_class], use newer org.hibernate.service.jta.platform.spi.JtaPlatform strategy instead [hibernate.transaction.jta.platform]
I don't know what is the different between the 2 properties ? And what is the use of them ?
Could anyone explain the difference and the use of them
I'm using hibernate 4 with websphere 8.5
The JtaPlatform offers more transaction-like integrations besides just the transaction manager, notably:
how to locate transaction manager
how to user transaction
how to register transaction synchronization
You can see the full JtaPlatform interface on GitHub here: https://github.com/hibernate/hibernate-orm/blob/master/hibernate-core/src/main/java/org/hibernate/engine/transaction/jta/platform/spi/JtaPlatform.java
Replace the following:
<property name = "hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
with
<property name = "hibernate.transaction.jta.platform" value ="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform"/>
in the Hibernate configuration/persistence.xml.
Related
I usually use a persistence.xml to configure hibernate, via properties like
<properties>
<property name="javax.persistence.lock.timeout" value="90000"/>
<property name="javax.persistence.query.timeout" value="90000" />
<property name="hibernate.dialect" value="org.hibernate.dialect.SQLServer2012Dialect" />
<!-- ... -->
However, I need to change one property at runtime (more specifically I need to adjust the value of javax.persistence.query.timeout at runtime). Therefore I tried configuring the session manually in situations where I need non-default properties, like that:
Configuration config = new Configuration();
config.addResource("persistence.xml");
config.setProperty("javax.persistence.query.timeout", "100000");
Session session = config.buildSessionFactory().getCurrentSession();
However, this yields the following exception:
org.hibernate.boot.MappingNotFoundException: Mapping (RESOURCE) not found : persistence.xml : origin(persistence.xml)
Which makes sense, as the persistence.xml isn't a normal hibernate resource file. So how do I set the configuration on the basis of the persistenc.xml (I don't want to configure all the properties twice)? Or more generally, how do I reconfigure hibernate at runtime?
Note that this is similar to, but not duplicating (as it's more specific), this post.
It can be overridden/set per query:
query.setHint("javax.persistence.query.timeout", 5000); // 5 seconds
If your query object is of type org.hibernate.Query you can do:
query.setTimeout(5);
https://docs.jboss.org/hibernate/orm/3.2/api/org/hibernate/Query.html#setTimeout(int)
Changing the properties in the EntityManagerFactory at runtime (To affect all queries) will not change the configuration in effect.
You can create a new EntityManagerFactory altogether if you want to, described here:
Changing Persistence Unit dynamically - JPA
I am working on an application consisting of Spring and Hibernate frameworks. In one particular module, the application fetches the data from database (select queries). Along with the select queries, application also issues an update statement. After further debugging, I found that the update query is fired from some TransactionInterceptor.
I think, transaction interceptor is not required here as all are select queries. Can anyone please suggest me a way to disable/suppress this interceptor at runtime?
This problem might sound too abstract at first. However, I am new to this application and don't have much knowledge about it's architecture. If you need any configuration details, please let me know.
Thanks in advance.
Can you post your application-context.xml transaction management declarations part. Where the bean : org.springframework.jdbc.datasource.DataSourceTransactionManager is defined.
If the annotaion is not enabled you should activate it like this :
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="yourDataSource" />
</bean>
<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true" />
#Transactional(propagation = Propagation.NOT_SUPPORTED)
on your method will disable any Spring transactions on this proxy method call. Note that by disabling the transaction you also lose other benefits, like isolation.
However, the fact that you have an update query fired is NOT because of a transaction. You are likely to encounter a different error if you simply remove the transaction (likely stale object exception when hibernate tries to update outside of a transaction, or a malfunction of some module). Hibernate does not fire spurious updates, you should look for updates to the object in question during your transaction.
Here you have the JavaDoc of the interface org.hibernate.Session method clear() :
Completely clear the session. Evict all loaded instances and cancel all pending saves, updates and deletions. Do not close open iterators or instances of ScrollableResults
So when you use clear you will clear whole the Session. That ok, you will ask me : have I only one session per transaction ? I will answer you it's depends on your application HibernateTemplate configuration, if the HibernateTemplate.alwaysUseNewSession==true but the default value is false. The solution is to not intercepte your dao method with the Transaction Manager because it will be executed by default in a non Transactional Session.
Did you get a look to the Spring Framework AOP Proxy configuration. section 10.5 Declarative transaction management
I managed to suppress the update query by writing the following line in my DAO class (which was extending HibernateDAOSupport)
super.getSessionFactory().getCurrentSession().clear();
I just cleared the session as there was no update required while fetching the data and interceptor was updating the table.
Also, the original issue which I was facing is, the application was encountering org.hibernate.StaleStateException: Batch update returned unexpected row count from update: 0 actual row count: 0 expected: 1 from this update statement when it got executed twice (God knows why!).
Hence, we figured out that the update was never required and wanted to suppress it.
Can this fix have any consequences on the application? Is this the right way to do it? Will appreciate the inputs.
So your PlatformTransactionManager instance is HibernateTransactionManager. TransactionInterceptor will delegate the transaction handling to HibernateTransactionManager. All that means : all calls that you make to your data access methods annotated with #Transactional will be path throw spring AOP Proxy (which is a Proxy Design pattern).
If you don't use annotation-based and you have declared an AOP Proxy (search for aop:config tag in your ApplicationContext.xml).
So in the AOP Proxy configuration you will find the politic that your application use for intercepting data access methods and handling transactions.
For finding if you are using annotation-based you should know what is 'transactionAttributeSource' : AnnotationTransactionAttributeSource or AttributesTransactionAttributeSource ?
I try some code from hibernate 4.0 interceptors, which gives this code for use session-level interceptors:
Session session = sf.openSession( new AuditInterceptor() );
however, I check both the hibernate-core 4.0 source code and onlie hibernate 4.0 java-doc, the class SessionFactory does not have method openSession(Interceptor interceptor) , but hibernate 3.6 java-doc do have this method.
anyone knows where is the method move to? if deprecated, why the document still keeps it in tutorial document? and how should I use session-level interceptor in 4.0?
It's implemented using Builder pattern now:
Session session = sf.withOptions()
.interceptor(new AuditInterceptor())
.openSession();
I have a properties set like so :
<context:property-placeholder
location="file:${catalina.home}/conf/my.properties"
ignore-unresolvable="true" />
they are then referenced in app context (specifically app.email) like so :
<bean id="alertMailMessage" class="org.springframework.mail.SimpleMailMessage">
<property name="to">
<value>${app.email}</value>
</property>
</bean>
However when I try to access that property within an actual pojo, not a spring bean - actually a pojo annotated as a hibernate entity (not the alertMailMessage bean) it is coming back as null ?
#Value("${app.email}")
private String defaultEmailAddress;
I want to use the value of property setting "app.email" elsewhere, other than alertMailMessage, whats the best way ? (alertMailMessage is working fine btw)
You can't set it in a hibernate entity, because hibernate entities are not managed by spring.
Use the #Value annotation in your spring service which creates the hibernate entity, and set it manually if needed. But it looks odd to store a default value in the database, so reconsider that.
As a sidenote: you can have hibernate entities managed by spring if using aspectJ and #Configurable, but that may complicate things unnecessarily.
It looks to me as though support for multi tenancy has been added to hibernate for nearly six months now and updated at least once since.
It looks fairly trivial to obtain a multi-tenant Session outside of JPA:
Session session = sessionFactory.withOptions().tenantIdentifier( "jboss" ).openSession();
But how would you enable it in an application that uses hibernate via JPA? (If possible).
Thanks in advance.
You can configure it via properties in persistence.xml as follows:
<property name="hibernate.multiTenancy" value="DATABASE"/>
<property name="hibernate.multi_tenant_connection_provider" value="com.example.MyConnectionProvider" />
<property name="hibernate.tenant_identifier_resolver" value="com.example.MyTenantIdResolver" />
If you use SCHEMA as multi-tenancy strategy hibernate.multi_tenant_connection_provider is not needed.
You can also set these properties in your code and pass them in a map to Persistence.createEntityManagerFactory(). In this case you can pass an object instance, not just a class name.
More info in Hibernate documentation.
EntityManager.getDelegate() will return underlying SessionImpl.