I am new to Hibernate and Spring.
I am trying to access data in Mysql using Hibernate Framework. But I feel confused which class to use to retrieve object.
Let me give examples. I found in some online tutorials and websites,
1 . Using HibernateTemplate as an interface to access Data
Using Persistence
EntityManagerFactory entityManagerFactory = Persistence
.createEntityManagerFactory("pl.edu.bogdan.training.db.entity");
EntityManager em = entityManagerFactory.createEntityManager();
Using SessionFactory
package com.journaldev.dao;
import java.util.List;
import org.hibernate.*;
import com.journaldev.model.Person;
public class PersonDAOImpl implements PersonDAO {
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
#Override
public void save(Person p) {
Session session = this.sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.persist(p);
tx.commit();
session.close();
}}
Could you please guide me in right way. Thanks
They're pretty much equivalent, at this point the only difference is the amount of code you need to write to access data.
Further you may need to fine-tune your queries. For example using Transaction tx = session.beginTransaction(); helps you control, which data manipulation / querying occurs within transaction, so that you don't hold connection to database too long. If you only need to save some entity, you may as well annotate the method of your bean with #Transactional.
Related
I've been struggling with this problem for days,
Here is the scenario:
I have several databases, one for each of my customers, all of them with the same
structure(same tables and columns), so my application needs to decide at runtime with which one it needs to connect. I'm using JPA2, EclipseLink and EJB3.
My first attempt was to implement a custom EntityManager with all the logic to performs the operations on the right database, then I configured this EntityManager as an Stateless EBJ in order to make it possible to inject it with the #EBJ annotation (as described at this link: http://www.hostettler.net/blog/2012/11/20/multi-tenancy/). I coundn't make it work because it was throwing an exception when trying to inject the EntityManager.
So I decided to try something else, I've created EntityManagerFactory and I passed the
JTA_DATASOURCE to it(after decide at runtime which one to use), so it could connect to the
right database.
Here is the code:
#Stateless
#TransactionManagement(TransactionManagementType.CONTAINER)
public class TestEntDAO {
private EntityManager em;
private EntityManagerFactory emf;
#PostConstruct
public void init() {
em = getEntityManager();
}
public EntityManager getEntityManager() {
Map props = new HashMap();
props.put(PersistenceUnitProperties.TRANSACTION_TYPE, "JTA");
props.put(PersistenceUnitProperties.JTA_DATASOURCE, dataSourceName());
emf = Persistence.createEntityManagerFactory("testePU", props);
em = emf.createEntityManager();
return em;
}
public String dataSourceName(){
if(someCondition){
return "db1";
}else{
return "db2";
}
}
}
This worked perfectly, the only problem is that the transaction is not managed by the
container, so I had to explicitly mark the transaction's boundaries(call begin() and
commit()). I could just use the #PersistenceContext annotation to make it work, but then I
wouldn't have the EntityManagerFactory to pass the datasource.
Does anyone know of a way to use the Container-Managed Transactions(CMT) and still be able
to pass the datasource?
Maybe try to define 3 Data sources and 3 Persistence units.
<persistence-unit name="PU1">
<jta-data-source>jdbc/DS1</jta-data-source>
...
</persistence-unit>
<persistence-unit name="PU2">
<jta-data-source>jdbc/DS2</jta-data-source>
...
</persistence-unit>
<persistence-unit name="PU3">
<jta-data-source>jdbc/DS3</jta-data-source>
...
</persistence-unit>
And inject Entity manager from whatever Persistence unit you want.
#PersistenceContext(unitName = "PU2")
EntityManager em;
This should work, although I didn't test it.
I'm trying to move out my project from Seam 3.
Now I'm stuck on JTA transactions after switching off Seam Faces module. There was integrated transaction management. Transactions were begun and commit automatically - without manual commit.
Now when I try to execute EntityManager.persist() or EntityManager.merge(Object entity), I've got error:
JBAS011469: Transaction is required to perform this operation (either use a transaction or extended persistence context)
Is there any way to force JTA to start transaction and commit it transparently?
Ps. Funny thing - some time ago I was looking for solution how to force manual commit/rollback in Seam3.
OK, if I put bean into #Stateless state - then it behaves as I expected.
But...
Isn't it - that if I put application managed EntityManager - then I should manage transaction on my own (method testApplicationJTA() in example below), but if I use container managed EntityManager - then it should work without transaction managing (method testContainterJTA() ) ?
My example:
#Named
#SessionScoped
public class Test implements Serializable {
private static final long serialVersionUID = 1L;
#PersistenceContext
private EntityManager em;
#PersistenceUnit
private EntityManagerFactory emf;
#Resource
private UserTransaction utx;
public void testContainerJTA() {
TestEntity entity = em.find(TestEntity.class, 1L);
entity.setName("dddddd");
em.merge(entity);
}
public void testApplicationJTA() {
EntityManager mgr = emf.createEntityManager();
TestEntity entity = em.find(TestEntity.class, 1L);
entity.setName("fffff");
try {
utx.begin();
mgr.joinTransaction();
mgr.merge(dict);
utx.commit();
} catch (Exception e) {
utx.rollback();
}
mgr.close();
}
}
In my example above method testContainerJTA() doesn't work. Why?
If I'll remove #SessionScoped and put #Stateless then method testApplicationJTA() doesn't work, but testContainerJTA() works. Why?
Should't they work both always - as application managed and container managed?
OK, so it is possible to make CDI bean tansactional - with interceptors :-)
Finally I managed to solve my problem reading this article:
http://smokeandice.blogspot.com/2009/12/cdi-and-declarative-transactions.html
Edit:
From JEE7 there is new #Transactional annotation which takes all JPA actions in CDI bean or method into transaction.
I am having some trouble understanding the proper usage of entity manager when querying for objects and or deleting/creating. Right now for any database transactions I have several service methods that open and close new entity managers like so:
public static Long getCountApplicants(String active){
EntityManager entityManager = factory.createEntityManager();
long value = (Long) entityManager.createQuery("select count(distinct a) from Applicant a where a.active = " +active).getSingleResult();
System.out.println("get count app query");
entityManager.close();
return value;
}
Since I have a Java EE app with a persistence.xml file that defines my unit, why can't I declare only one from my factory and use it throughout the life of my app? Is there any performance or memory leak issues with using just one of these objects?
Update:
I am using the following stack, Spring Framework/JPA Eclipselink
Long story short: Since you're using Spring, you're better off defining the Entity Manager as an attribute of your DAO like so:
#PersistenceContext
EntityManager em;
Your code then becomes:
public static Long getCountApplicants(String active){
long value = (Long) em.createQuery("select count(distinct a) from Applicant a where a.active = " +active).getSingleResult();
System.out.println("get count app query");
return value;
}
This will work only with Non Extended Persistence Contexts.
The EntityManager injected by Spring will be threadsafe.
Whether you need to configure an LocalEntityManagerFactorBean application-managed or LocalContainerEntityManagerFactoryBean container-managed Entity Manager is just a matter of configuration in the Spring configuration files.
EntityManager is generally not threadsafe when application managed.
http://docs.oracle.com/javaee/6/tutorial/doc/bnbqw.html
However, if you're using a container managed version, it should be. You would inject it:
#PersistenceContext
EntityManager entityManager;
Spring is one such container that can do this. The link above is a helpful resource.
My Spring+Hibernate configuration files are small and super tight. I use auto scanning to find my model entities/daos.
I don't want to have to write a DAO + DAOImpl for EVERY Entity in my hierarchy.
Some may qualify to have their own, like if they have complex relationships with other entities and require more than basic CRUD functionality. But for the rest...
Is there any way to circumvent the defacto standard?
Say, something like a generic DAO, ex:
http://www.ibm.com/developerworks/java/library/j-genericdao/index.html
Then I can do something like
GenericDao dao = appContext.getBean("genericDao");
dao.save(car);
dao.save(lease);
Is this possible with annotations? I don't want to have to configure anything in xml. If I cannot do above, is it still possible to have one GenericDaoImpl.java with something like:
#Repository("carDao")
#Repository("leaseDao")
class GenericDaoImpl extends CustomHibernateDaoSupport implements GenericDao {
...
}
and then
GenericDao dao = appContext.getBean("carDao");
dao.save(car);
dao = appContext.getBean("leaseDao"); //carDao is garbage coll.
dao.save(lease);
Is this practical at all?
Using generics, you might try something like this:
#Repository
#Transactional
public class GenericDAOImpl<T> implements GenericDAO<T> {
#Autowired
private SessionFactory factory;
public void persist(T entity) {
Session session = factory.getCurrentSession();
session.persist(entity);
}
#SuppressWarnings("unchecked")
public T merge(T entity) {
Session session = factory.getCurrentSession();
return (T) session.merge(entity);
}
public void saveOrUpdate(T entity) {
Session session = factory.getCurrentSession();
session.saveOrUpdate(entity);
}
public void delete(T entity) {
Session session = factory.getCurrentSession();
session.delete(entity);
}
}
The content may be different, but the general idea is applicable.
You should be able to then autowire the DAO in your controller and service classes by using
#Autowired
private GenericDAO<Car> carDao;
You can combine Spring/Hibernate with JPA, which provides the EntityManager for a large amount of basic persistence tasks:
#Service
public class CarService {
#PersistenceContext
private EntityManager em;
public void saveCarAndLease(Car car, Lease lease) {
em.persist(car);
em.persist(lease);
}
}
It will also handle transactions and simple queries without needing to write a DAO. For the more complex operations, you can still write a DAO and fall back to Hibernate's SessionFactory (although JPA is an option here too).
Some tutorials suggest you should still write the DAO for abstraction of the JPA plumbing. However, I have personally found this unnecessary (JPA has a very small integration footprint), and in fact this is also the way Spring Roo deals with the data layer behind the scenes.
Have you tried to use Spring Data. I mean to say Spring JPA where you can use repositories.
You can eliminate writing all stuffs for each entity.
I'm Spring and Hibernate newbie.
I've created the entity User and DAO - UserHibernateDao.
I want to test how the hibernate working in simple java-class with public static void main:
public class Starter {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("/org/jtalks/jcommune/model/entity/applicationContext-dao.xml");
Dao<User> uhd = (Dao) context.getBean("userDao");
User user = new User();
user.setNickName("UserName");
uhd.saveOrUpdate(user);
}
}
but I get the error
INFO: Using DataSource [org.springframework.jdbc.datasource.DriverManagerDataSource#17b4703] of Hibernate SessionFactory for HibernateTransactionManager
Exception in thread "main" org.springframework.orm.hibernate3.HibernateSystemException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here; nested exception is org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:679)
I understand I need to create something like session and transaction but I don't know how exactly I should do this.
my config
User.java
UserHibernateDao.java
Full Project
Thanks
Add the #Transactional annotation to your DAO's method.
That will initiate the transactional context.
import org.springframework.transaction.annotation.Transactional;
#Transactional
public User getUser(int id) {
..
}
I'd suggest you read this reference on Spring and Transaction Management as it will help you understand how to set this all up.