Write Less DAOs with Spring Hibernate using Annotations - java

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.

Related

Is javax.persistence.EntityManager thread safe

I’m using EntityManager in may Dao layer without #PersistenceContext but Dao method is calling service method which is marked as #Transactional. My question is should I use EntityManagerFactory in dao layer and every time get EntityManager to keep thread safety or it’s handled already?
Dao layer:
#RequiredArgsConstructor
public class UserDaoImpl {
private final EntityManager em;
public void save(User user){
em.persist(user);
}
}
Service layer:
#RequiredArgsConstructor
public class UserService {
private final UserDao userDao;
#Transactional
public void save(User user) {
userDao.save(user);
}
}
Tnx!
just add #PersistenceContext to your Entity Manager and the container will handle it for you, but if you are not in JEE environment so create your own entity manager factory, but I think in your current case the entity manager will still null. Also you must create you persistence unit XML file, and take attention in transaction-type, it must be JTA if you use #PersistenceContext and it should be RESSOURCE_LOCAL if you will create your own Entity Manager Factory.
This stackoverflow question Is EntityManager really thread-safe? already got answer to your question.
And this one "Future-Proofing Java Data Access - DAO Pattern Done Right" shows how to design DAO layer.
But if you are using Spring and Spring Data repository then I would suggest defining repository using CrusRepository or JpaRepository interface.
That would offload your concerns regarding EntityManager handling to Spring.

Multiple Sharded Databases Hibernate Transactions

I have a spring based tomcat service. I use annotations based hibernate mapping and I have multiple sharded databases. All the sharded databases have same tables say Student. I want to implement transaction on them using #Transactional annotation.
#Autowired
List<SessionFactory> sessionFactoryList;
#Transactional
public insertStudentBatch(List<Student> students) {
}
Now I want to insert entire batch. If any error occurs, I want all of them to roll back. What is the best way to do that? Can I write multiple TransactionManager qualifier like #Transactional("txManager1", "txManager2")?
No, unfortunately the spring #Transactional annotation is specific to a single transaction manager and does not behave in the desire you described.
It seems to me what you would likely want is a JTA transaction for 2PC commit where you basically start a master JTA transaction and then for each SessionFactory, you invoke each of the specific transaction managers for your shards and perform your operations.
#Service
public class StudentBatchServiceImpl implements StudentBatchService {
#Autowired List<StudentService> studentServices;
#Transactional(value = "jtaTransactionManager")
public void storeStudents(List<Student> students) {
for(StudentService service : studentServices)
service.storeStudents(students);
}
}
public interface StudentService {
void storeStudents(List<Student> students);
}
public abstract AbstractStudentServiceImpl implements StudentService {
protected void storeStudents(EntityManager em, List<Student> students) {
for(Student student : students) {
em.persist(student);
}
}
}
#Service
public class Shard1StudentServiceImpl extends AbstractStudentServiceImpl {
#PersistenceContext(name = "shard1")
private EntityManager entityManager;
#Override
#Transactional(value = "shard1TransactionManager")
public void storeStudents(List<Student> students) {
storeStudents(entityManager, students);
}
}
There may be some other ways to handle this without a 2PC commit setup with JTA, but tyically in container managed transactions (like JBoss, WebLogic, etc); this would be the approach.
As a side bar, if you're already down the spring path I might suggest you check out spring-batch. It provides a decent baseline for batch like operations for a plethora of use cases. What I described above is a poor-mans implementation of one case inside spring-batch.
UPDATE
If you want to avoid having to create multiple shard class implementations with annotation details, you could resort to XML configuration and have a single class implementation:
<bean id="shard1" class="default.ShardStudentServiceImpl">
<property name="entityManager" ref="shard1EntityManager" />
<property name="transactionManager" ref="shard1TransactionManager" />
</bean>
The only difference here is that you have to define your 25 shards in XML and then you have to write your own code to start, commit, and manage the transaction inside your ShardStudentServiceImpl class.
Using the abstract base class in conjunction with annotations in the final implementations shown above my update arrives at the same destination. In fact, if you look at spring-batch, you'll notice their batch configuration follows a similar premise with specifying the entity manager and transaction managers as input properties to a single class.

Manage rollback on transaction in my managed bean

I am using JPA/hibernate, Spring and JSF.
so my application is organized as following:
I have my entities,
My Dao Interface and implementation for each entity where I define basic methods: findById, add, update, remove ...
and then I have my service layer which just use DAO interfaces and where ther is basically the same methods as in my DAO.
My problem is that in my backing bean, I have a method Add_hospital(), which add a hospital and also services in that hospital, so my method looks like
add_hospital(){
add-hospital();
add-services();
add-Hospital-schedule();
}
so this method is a transaction and I want that if some issue happen, the transaction rollback, but I know that the rollback need to be managed in my DAO, will I need to define my method Add_hospital() in my managed bean, and it's in this stage where I have this combination of inserts.
Please how to solve this problem?
Transactions should be managed on the service layer, not data access.
Example from spring:
#Transactional(readOnly = true)
public class DefaultFooService implements FooService {
public Foo getFoo(String fooName) {
// do something
}
// these settings have precedence for this method
#Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public void updateFoo(Foo foo) {
// do something
}
}

Complete transaction with multiple dao in service class

How do I achieve a complete transaction where a service class requires more than one data access object. Assuming I have the following structure.
Currently, if my dao2 failed, the dao1 still being committed to the database which I do not want it to happen. However, I need my DAO to be reusable.
public class mainService(){
dao1.store(obj1);
dao2.store(obj2);
}
And my dao is written in this way.
Dao 1
private EntityManager entityManager;
#Transactional
public void store(Object obj1){
entityManager.persist(obj1);
}
Dao 2
private EntityManager entityManager;
#Transactional
public void store(Object obj2){
entityManager.persist(obj2);
}
Please help.
Make this happen in one transaction.
#Transactional
public void mainService(..){
dao1.store(obj1);
dao2.store(obj2);
}
Only one transaction will be created, and if dao2 fails, dao1 won't be committed as well. And remove #Transactional from store method. Making DB level methods transactional it's not a good idea. This level might be two low in some cases.
The obvious answer is to use:
private EntityManager entityManager;
#Transactional
public void store(Object obj1, Object obj2){
entityManager.persist(obj1);
entityManager.persist(obj2);
}
What's happened is that you have become hung up on using DAOs. The DAO is dead! If you look at the EntityManager API you will notice that it actually looks very much like a DAO type of interface. So just use it directly where ever you would normally consider using a DAO.
In your case, you should mark mainService() with #Transactional too, For transaction propagation rule is PROPAGATION_REQUIRED by default , and then both dao1.store() and dao2.store() with be under the same transaction.It's OK to keep dao1.store() and dao2.store() #Transactional, they will realize that there is already a transaction and then join the transaction.

Guice injected EntityManager in multi threaded application

I'm working on a desktop application using Java SE 7. The application uses multiple threads and in each thread that is created a DAO class is injected to gain access to my database. As persistence layer i'm using EclipseLink and JPA. The EntityManager is injected into my DAO class using constructor injection and since it is not thread safe, I went for the approach using a Provder like this:
public PluginInstanceJpaController implements IPluginInstanceDao {
private EntityManager em;
#Injected
public PluginInstanceJpaController(Provider<EntityManager> emp) {
this.em = emp.get();
}
#Transactional
public void create(PluginInstance foo) throws Exception {
em.persist(foo);
}
}
However, the very same EntityManager instance is injected into each DAO. For setting that up I used the JpaPersistModule as it is provided by guice and i'm sure that there are not singletons in my setup so far.
Does anyone know how to tell guice to create a new instance of the EntityManager when injecting?
In another approach I tried custom providers for the EntityManagerFactory and the EntityManager and leaving the JpaPersistModule out of my business. This resulted in a EntityManager instance per DAO, however #Transactional annotated methods were not intercepted then.
I'd appreciate any solution to this issue.
Thanks so far!
--- EDIT ---
The DAO classes are injected into a Runnable that is using them. The Runnable is also provided through a Provider. My module configuration looks something like this:
public class RepositoryModule extends AbstractModule {
#Override
protected void configure() {
// DAO bindings
bind(IObjectStoreDao.class).to(ObjectStoreJpaController.class);
bind(IPluginInstanceDao.class).to(PluginInstanceJpaController.class);
}
#Provides
public PluginMonitor newMonitor(IPluginInstanceDao plugDao, IObjectStoreDao osDao) {
PluginMonitor m = new PluginMonitor();
m.setPluginInstanceDao(plugDao);
m.setObjectStoreDao(osDao);
return m;
}
}
Here PluginMonitor is my Runnable. The Injector itself is created in my main thread... might this have been the issue?
This is very similiar issue: How Guice injects singletons and non-singletons into multiple threads
To your DAO, this should work.
public PluginInstanceJpaController implements IPluginInstanceDao {
private Provider<EntityManager> emProvider;
#Injected
public PluginInstanceJpaController(Provider<EntityManager> emp) {
this.em = emp;
}
#Transactional
public void create(PluginInstance foo) throws Exception {
em.get().persist(foo);
}
}
You should use Jpa Persistence Module or create custom EntityManager provider, which will return new EntityManager for each get() call, also it can be implemented with ThreadLocal to ensure EntityManager will be shared across thread.
I'm not familiar with JPA, but hopefully I can still help :-)
If you look at the source for EntityManagerProvider, you can see there's a ThreadLocal<EntityManager>. So by default, each thread should have its own EntityManager. That leads me to believe the problem is elsewhere. Are you sure that no module is setting the EntityManager to be a singleton? How are you determining that all the EntityManagers are the same object? Each DAO is definitely on its own thread? Can you provide details on how FooDao is configured in your module and how a new FooDao is provided to each thread?
Also, you should be fine to write your constructor as:
#Inject
public FooDao(EntityManager emp) {
this.em = emp;
}
Guice will do the magic for you of determining that EntityManagerProvider provides EntityManager instances, and will call get() on the EntityManagerProvider instance to get an EntityManager to give to your constructor.

Categories

Resources