How to use StatelessSession with Spring Data JPA and Hibernate? - spring

I'm using Spring + Spring Data JPA with Hibernate and I need to perform some large and expensive database operations.
How I can use a StatelessSession to perform these kind of operations?

A solution is to implement a Spring factory bean to create this StatelessSession and inject it in your custom repositories implementation:
public class MyRepositoryImpl implements MyRepositoryCustom {
#Autowired
private StatelessSession statelessSession;
#Override
#Transactional
public void myBatchStatements() {
Criteria c = statelessSession.createCriteria(User.class);
ScrollableResults itemCursor = c.scroll();
while (itemCursor.next()) {
myUpdate((User) itemCursor.get(0));
}
itemCursor.close();
return true;
}
}
Check out the StatelessSessionFactoryBean and the full Gist here. Using Spring 3.2.2, Spring Data JPA 1.2.0 and Hibernate 4.1.9.
Thanks to this JIRA and the guy who attached StatelessSessionFactoryBean code. Hope this helps somebody, it worked like a charm for me.

To get even better performance results you can enable jdbc batch statements on the SessionFactory / EntityManager by setting the hibernate.jdbc.batch_size property on the SessionFactory configuration (i.e.: LocalEntityManagerFactoryBean).
To have an optimal benefit of the jdbc batch insert / updates write as much entities of the same type as possible. Hibernate will detect when you write another entity type and flushes the batch automatically even when it has not reached the configured batch size.
Using the StatelessSession behaves basically the same as using something like Spring's JdbcTemplate. The benefit of using the StatelessSession is that the mapping and translation to SQL is handled by Hibernate. When you use my StatelessSessionFactoryBean you can even mix the Session and the StatelessSession mixed in one transaction. But be careful of modifying an Entity loaded by the Session and persisting it with the StatelessSession because it will result into locking problems.

Related

Does it make sense to use Spring's #Transactional annotation in a method which doesn't talk to database?

I am trying to understand a project which involves spring's declarative transactional annotation. The body of the function is not making any JDBC calls or calling JPA repository methods. All it is doing is call some third party API and transform it's results, it's not even saving the response in the database. So no database interactions at all.
My question is that is it worth using #Transactional annotation on this method? Because as per my understanding #Transactional only helps in maintaining consistency in databases.
The #Transactional annotation defines the scope of a single database transaction - all it does is it begins the transaction and either commit it or rollback. It allows to manage transaction declarative way rather than do it programatically every time.
It looks something like this:
UserTransaction utx = entityManager.getTransaction();
try {
utx.begin();
// your method invocation here
utx.commit();
} catch(RuntimeException ex) {
utx.rollback();
throw ex;
}
By making method #Transactional when there is no database calls you only make its performance worse as redundant steps have to take place when not necessary.

two datasource in Spring integration inbound channel

I am using int-jdbc:inbound-channel-adapter of Spring Integration.
My Query is how to use two different datasource i.e. datasource A for querying and datasource B for update , in a single adapter?
You cannot; the same JdbcTemplate is used for both operations; you can omit the update query and do the update on an outbound channel adapter.
In Spring JDBC module we have something like AbstractRoutingDataSource.
Which you can implement based on some ThreadLocal variable.
From other side the JdbcPollingChannelAdapter has code like this:
private Object poll() {
List<?> payload = doPoll(this.sqlQueryParameterSource);
...
executeUpdateQuery(payload);
return payload;
}
So, you should somehow to hook in between doPoll() and executeUpdateQuery and, therefore, change the key in the ThreadLocal to be able to switch to another DataSource in the AbstractRoutingDataSource.
I only the hack like custom sqlParameterSourceFactory.createParameterSource() and the ThreadLocal modification there. Just because the code is like:
private void executeUpdateQuery(Object obj) {
SqlParameterSource updateParamaterSource = this.sqlParameterSourceFactory.createParameterSource(obj);
this.jdbcOperations.update(this.updateSql, updateParamaterSource);
}
(Will commit the fix for updateParamaterSource typo soon :-)).
But! As Gary mentioned in his answer, it would be better to have several JDBC adapters for different DataSources : one for SELECT and another for UPDATE. Both of them may work in the same XA Transaction (<transactional> on the <poller>). And from there we really differentiate the business logic and level of responsibility.

Flush MyBatis Cache externally (outside of mapper)

I'm using MyBatis with second level cache activated via <cache/> in xml mapper files.
Suppose I want to interact with the underlying DB/DataSource decoupled from MyBatis, for instance via direct jdbcTemplate.
How can I assure, that the MyBatis cache gets flushed appropriateley when I Insert/Update/Delete via jdbcTemplate on a table for that MyBatis holds cached query results.
In other words, how can I force MyBatis to flush its cache from outside of MyBatis mappers for certain cache namespace?
I'm aware of #Options(flushCache=true) annotation, but this seems not to work outside of mapper interfaces.
you can get cache from configuration and then get by namespace and clear it.
#Resource
SqlSessionFactory sqlSessionFactory;
public void clearCacheByNamespace(){
Configuration config = sqlSessionFactory.getConfiguration();
Cache cache = config.getCache("com.persia.dao.UserInfoMapper");
if(cache != null){
cache.clear();
}
}
Hi i have used another approach, because we used spring. Use autowire the Session implementation and call appropriate method
public class SomeServerClass{
#Autowired
private org.mybatis.spring.SqlSessionTemplate sqlSessionTemplate;
private void someClearMethod(){
sqlSessionTemplate.clearCache();
}
}
If I use interface org.apache.ibatis.session.SqlSession it refers to same instance

Spring+hibernate+jpa how does it work?

In the new project that I have joined, they keep using the terms Hibernate and JPA interchangeably. So, I tried to dive down into the code and try to understand how this whole thing works (I am new to Spring, JPA and Hibernate world). I'll try to put the code here for better understanding:
1) There is a #Configuration class where they have the following:
#Resource
private HibernateJpaVendorAdapter hibernateOracleJpaVendorAdapter;
LocalContainerEntityManagerFactoryBean entityManager =
new LocalContainerEntityManagerFactoryBean();
entityManager.setJpaVendorAdapter(hibernateOracleJpaVendorAdapter);
entityManager.setPersistenceUnitName("abc");
.
.
So, in this configuration class, we are returning an EntityManagerFactory.
2) Then there is a persistor class marked #Persistor, where a method of repository is invoked (for example, for a save operation):
blahblahRepository.save(blahblahEntity, abcdef);
3) Finally there is a repository class which is annotated #Repository. Then again, they have this piece of code:
#PersistenceContext(unitName = "same as the name in persistence.xml")
protected EntityManager entityManager;
The "save" method wraps around the persist method of JPA:
getEntityManager().persist(entityObject);
My questions are as follows:
1) There is no word about Hibernate other than in the hibernateJpaVendorAdapter. I searched the entire workspace and it showed just 3 occurences of the word hibernate, all in the configuration file.
2) From whatever knowledge I have, one should use either an EntityManagerFactory or an EntityManager but we are doing both?
Hibernate is one of the implementations of the JPA spec. Since your project chose Hibernate as its JPA implementation, it uses the JPA API, which delegates the Hibernate. Just like when you use the JDBC API, which delegates to a specific Oracle or PostgreSQL driver.
EntityManagerFactory, as its name indicates, is a factory for EntityManager. I don't see why you wouldn't use both. EntityManager is the main interface of the JPA API, used to execute all database operations (find, persist, merge, query, etc.). EntityManagerFactory must be configured before asking it to create an EntityManager.

JPA and DAO - what's the standard approach?

I'm developing my first app with JPA/Hibernate and Spring. My first attempt at a DAO class looks like this:
#Repository(value = "userDao")
public class UserDaoJpa implements UserDao {
#PersistenceContext
private EntityManager em;
public User getUser(Long id) {
return em.find(User.class, id);
}
public List getUsers() {
Query query = em.createQuery("select e from User e");
return query.getResultList();
}
}
I also found some examples using JpaDaoSupport and JpaTemplate. Which design do you prefer? Is there anything wrong with my example?
I'd say your approach looks totally sound. Personally I don't use JpaDaoSupport or JpaTemplate because you can do everything you need with the EntityManager and Criteria Queries.
Quote from the JavaDoc of JpaTemplate:
JpaTemplate mainly exists as a sibling of JdoTemplate and HibernateTemplate, offering the same style for people used to it. For newly started projects, consider adopting the standard JPA style of coding data access objects instead, based on a "shared EntityManager" reference injected via a Spring bean definition or the JPA PersistenceContext annotation.
I prefer the template-less approach (i.e. your current approach) because
it's less invasive, you don't tie DAOs to Spring
templates don't offer much value with APIs that use unchecked exceptions
And this is the Spring recommendation, as summarized in the blog post "So should you still use Spring's HibernateTemplate and/or JpaTemplate??" and the official javadoc:
The real question is: which approach to choose??
(...)
So in short (as the JavaDoc for
HibernateTemplate and
JpaTemplate already mention)
I'd recommend you to start using the
Session and/or EntityManager API
directly if you're starting to use
Hibernate or JPA respectively on a new
project–remember: Spring tries to be
non-invasive, this is another great
example!
I, personally, prefer your approach - inject EntityManager and use it directly. But JpaTemplate is also a good option. I don't like it, because adds yet another, unnecessary layer of abstraction.
I don't know if there's a "standard" approach.
If you're using JPA, you have your choice of implementations: Hibernate, TopLink, etc.
If you deploy to Google App Engine, you'll use JPA talking to BigTable.
So if your objectives are to maximize portability, stick with the JPA standard, and not tie yourself to a particular implementation like Hibernate, make sure that your DAOs only use JPA constructs.

Resources