Spring/Hibernate/TestNG - manual session and transaction setup - java

I am trying to create a testcase for my DAO classes that use plain Hibernate API (no Spring stuff like HibernateTemplate,HibernateDaoSupport), just like this:
sessionFactory.getCurrentSession().save(obj);
I have the appropriate sessionFactory and transactionManager definition in spring context as shown in the spring docs.
What I want is to open a transaction in my start up code and rollback at the end.
So this is different from the default Spring unit testing supporting concept of transaction for every test method call and so I could not extend AbstractTransactionalTestNGSpringContextTests.
I need a way to start a transaction and somehow feed it in session factory. I feel this should be extremely easy but could not achieve after lot of reading and experiments.
Any help would be greatly appreciated.

If you don't want to use HibernateTemplate, you can use transactionManager directly as described in 10.6.2 Using the PlatformTransactionManager.

try {
Session session = factory.openSession();
Transaction tx = session.beginTransaction();
...
tx.commit();
session.close();
} catch (SomeException e) {
tx.rollback();
...
}

#Transactional(readOnly = false, propagation = Propagation.REQUIRED)
annotate the test method using above

Related

Hibernate + Spring openSession in Transaction

I have this code and I have a question :
#Service
class SimpleServiceImpl implements SimpleService{
#PersistenceContext
private EntityManager em;
#Transactional
public void doSmth(){
// here I want to have a new session
Session session = em.unwrap(Session.class).getSessionFactory().openSession();
// do smth in new session
session.close();
}
What about a transaction ??? Actually as I understand if I open session I have to manage this session explicitly and I have to close it. But what's going on with transaction? Should I begin a new transaction and manage it by myself or my action s continue in the same transaction which method doSmth began?
You have annotated with #Transactional that's why Spring will handle transaction using AOP concept.
If you use a Transactional annotation your method will be done within one transaction.
For more information you could also check this: spring transactional what happens in background.

Is there any difference in using Hibernate with Spring as compared to Hibernate alone?

So far we have been using Hibernate alone - I am moving to JPA. Spring is used for MVC in our projects. They are used completely separately.
I checked the new Spring 4.0 Petclinic project with Hibernate JPA implementation (https://github.com/SpringSource/spring-petclinic.git). Again I do not see that influence of Spring on the Hibernate code. For example JpaPetRepositoryImpl is used without Spring except the #Repository annotation. Have I missed something?
The whole point of Spring is to be as unintrusive to your code as possible, you should see as little of spring as possible in your code. Basically that is the whole point and aim of Spring.
When you normally use hibernate without spring you would have some kind of singleton which constructs the hibernate SessionFactory.
public class HibernateUtil {
private static SessionFactory sf;
static {
sf = ew Configuration().configure().buildSessionFactory();
}
public static getSessionFactory() {
return sf;
}
}
The next thing you would see is code that is filling up with calls to HibernateUtils.getSesionFactory(). You would manually need to create your Session and start/commit transactions.
public void save(Entity e) {
SessionFactory sf = HibernateUtil.getSessionFactory();
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
try {
session.save(e);
tx.commit();
} catch (HIbernateException he) {
tx.rollback();
} finally {
session.close();
}
}
However this code is bad due to 2 reasons. The first you are manually managing your transactions, which after a while becomes a pain, you want to use declarative transaction management. The second you are managing transactions at the wrong layer, transactions should be managed at the service layer. Now to make that possible you would have to get the SessionFactory in your Service layer, which would suddenly turns data access layer into a leaky abstraction.
Spring can help you with both things, it can do declarative tx management and hide the fact that you are using Hibernate, not making it a leaky abstraction.
#Inject
private SessionFactory sf;
public void save(Entity e) {
sf.getCurrentSession().save(e);
}
This would be the same in a Spring way. The transaction would be started at the service level (with a #Transactional or #TransactionAttributes annotation).
For JPA this is more or less the same, however as JPA is a standard Spring tries to follow those as much as possible. So plain JPA code and JPA code in Spring doesn't differ that much (unless you are using JPA in a standalone application and not a JEE container, than the JPA code would be like the hibernate code).
one of the big advantages is declarative transaction management using #Transactional annotation, where Spring manages the transaction commit/rollback, have a look at this example.
I like the #PersistenceContext annotation that injects an EntityManager into my Spring beans. If you are familiar with the SoC ideology, it makes everything a lot clearer to use Spring, but some find it confusing and too magic I guess.
I for sure would totally advise you against using hibernate/jpa/persistence manually without any IoC framework.
Spring with declarative transactions requires proxies or byte code transformations. It complicates debugging and slows down application startup time. There are many ways to avoid this complexity, one of ways is Command Design pattern:
public class Transaction {
public void execute(Command command) {
SessionFactory sf = HibernateUtil.getSessionFactory();
Session session = sf.openSession();
try{
Transaction tx = session.beginTransaction();
try {
command.execute(session);
tx.commit();
} catch (HIbernateException he) {
tx.rollback();
}
}finally{
session.close();
}
}
}
Probably you will need "Context" parameter instead of "Session" for "command.execute(context)" to abstract this design in practice but for example it is more clear to have "Session" parameter.
Multiple commands can be executed in the same transaction using composite command wrapper. This design pattern can be used to add command validation, security: "command.isValid(context)", "command.checkPermissions(context)". Many other aspects can be implemented by this simple but powerful design pattern without dependency on any heavy weight frameworks. You can use this design with Spring too, Spring is fine to configure factories in XML but I think Spring is too heavy weight and it is too complicated for other use cases.

How does Spring Data Neo4j begin transaction work?

I have a comprehension question. I cannot understand how the database actions from the Neo4jTemplate like "getOrCreateNode()" belong to the surrounding transction. How is it implemented? The Neo4jTemplate would be shared in a multi-threaded environment? I cannot see a distinct membership of the transaction. I would understand if the actions are directly in the transaction object (e.g. tx.getOrCreateNode()).
#Service
public class TestService {
#Autowired
private Neo4jTemplate template;
public void save(IndexedTriple triple) {
GraphDatabase gdb = template.getGraphDatabase();
Transaction tx = gdb.beginTx();
Node subject = gdb.getOrCreateNode()
...
tx.success();
tx.finish();
}
}
Thanks in advance.
The below extract from the reference documentation pretty much sums it up. Use the spring transaction manager instead of using the Neo4j transactions and let spring take care of demarcation. Also, the transaction management is completely thread-safe. For you, I suggest using #Transactional annotation. If there is an existing transaction already, then spring joins that existing transaction as well.
Transactions
The Neo4jTemplate provides implicit transactions for some of its
methods. For instance save uses them. For other modifying operations
please provide Spring Transaction management using #Transactional or
the TransactionTemplate.

JPA persist not writing to database

I'm just trying to get to know JSF and JPA but whenever I try to persist an object into the database it seems to not write away.
Here's the code I'm using:
#Named
#ManagedBean
#SessionScoped
public class BestemmingController implements Serializable{
#PersistenceUnit(unitName="RealDolmenTravelShopPU")
#PersistenceContext(unitName="RealDolmenTravelShopPU")
EntityManagerFactory emf = null;
public void submit(){
try{
emf = Persistence.createEntityManagerFactory("RealDolmenTravelShopPU");
EntityManager em = emf.createEntityManager();
//EntityTransaction et = em.getTransaction();
//et.begin();
Bestemming nieuweBestemming = new Bestemming();
Land gezochtLand = em.find(Land.class, selectedLand);
nieuweBestemming.setLand(gezochtLand);
nieuweBestemming.setNaam(bestemmingNaam);
em.persist(nieuweBestemming);
//et.commit();
//em.flush();
em.close();
}catch (Exception e){
e.printStackTrace();
}finally{
emf.close();
}
}
I tried using the EntityTransaction but it just stopped my application, without any errors or anything. So I left it out, but still it didn't write away.
So then I tried calling flush seperately, but that didn't do anything either.
I'm really stumped as to why this isn't working. It's probably some newbie mistake, but I would love it if someone here could help me out.
Thanks in advance!
First, are you able to write to the logs? Starting a transaction when specifying the persistence unit uses JTA will throw an exception, so it is likely you have just been missing exceptions in your container log files.
Second, this is a JTA PU, so it needs a JTA transaction started that the EM gets associated to, and you will want to inject the em rather than create a factory yourself. Check out the JPA application server examples here first to see how they are set up:
http://wiki.eclipse.org/EclipseLink/Examples/JPA
Hey I found out why it was that the transaction wasn't running: the implementation I used didn't use JTA, it used a RESOURCE_LOCAL persistence unit. That was something I just looked over when I set up my project.
Good thing my buddy told me to check the server logs.

Transaction Management

In my code I am updating two table, one after the other.
update(table1_details);
update(table2_details);
So if the update fails in table1 , table2 should not be updated or should be rolled back.
How to handle this situation. I know I have to use transaction. Can some one help with code !!!
I am using Java with spring and hibernate .
The question is a bit broad and there are several ways to implement this but I would:
Use Spring to inject Hibernate SessionFactory into DAOs objects.
Use Spring to inject DAOs in a service object and call them inside a business method.
Use Spring declarative transaction management at the business method level (either with Spring AOP or #Transactional).
Something like this:
#Transactional
public void doSomething() {
dao1.foo();
dao2.bar();
}
For more details on the configuration, check the Chapter 9. Transaction management of the Spring documentation.
I can't recall the correct api, but something like this:
Transaction tx = em.getTransaction();
tx.begin();
try {
update1(); update2();
}
catch(Exception e) {
failed = true
}
finally {
if( !failed ) tx.commit();
else tx.rollbacl();
}

Categories