CDI JPA - DAO pattern without EJB - java

I am writing a CDI-JPA DAO pattern that not using EJB because I am using Tomcat.
Here is my code:
#ApplicationScoped
public class UserDao {
#PersistenceContext(unitName = "unitName1")
EntityManager entityManager;
public void saveUser(User user) {
this.entityManager.persist(user);
}
public void removeUser(User user) {
this.entityManager.remove(user);
}
public void getUser(int id) {
this.entityManager.find(User.class, id);
}
}
Since all my DAO classes are annotated with #ApplicationScoped so I was wondering whether IT IS SAFE to inject entityManager using #PersistenceContext as I did? Can someone tell me is that ok? If NOT, please give me your ideas.

Related

EntityManager injected only once if declared into two different EJBs

I am on Weblogic 12c + JPA/Hibernate + EJB 3.
I wish to simplify my class model as follow:
public abstract class AbstractEJBBean {
#PersistenceContext(unitName = "myPU")
private EntityManager entityManager;
}
#Local
public interface FirstEJB {
void someMethod1();
}
#Stateless
public class FirstEJBImpl extends AbstractEJBBean implements FirstEJB {
#Override
public void someMethod1() {
// Here entityManager has been injected.
}
}
#Local
public interface SecondEJB {
void someMethod2();
}
#Stateless
public class SecondEJBImpl extends AbstractEJBBean implements SecondEJB {
#Override
public void someMethod2() {
// Here entityManager has NOT been injected!!!
}
}
In such situation, Weblogic starts (no errors logged), the application starts, but: only then entity manager into FirstEJBImpl instance have been injected. The one inside SecondEJBImpl is null!!!
I never seen any like this.
Could somebody tell my why and how to avoid it?
Thank you so much!!!
I found the solution on my own.
I suppose it is a Weblogic bug, but I am not so sure, but my solution works as expected.
I had to remove the abstract base class and inject the entity manager directly inside each EJB.
#Local
public interface FirstEJB {
void someMethod1();
}
#Stateless
public class FirstEJBImpl implements FirstEJB {
#PersistenceContext(unitName = "myPU")
private EntityManager entityManager;
#Override
public void someMethod1() {
// Here entityManager has been injected.
}
}
#Local
public interface SecondEJB {
void someMethod2();
}
#Stateless
public class SecondEJBImpl implements SecondEJB {
#PersistenceContext(unitName = "myPU")
private EntityManager entityManager;
#Override
public void someMethod2() {
// Here entityManager has been injected too! :)
}
}

Spring-boot with two EntityManager and abstract dao layer

I have a Spring-boot project, in my project I defined two EntityManager - for two different DB.
All of my entities (tables) are common for the two different DB.
The only thing that is different is the Dao layer - but because some of my db queries are shared I decided to create - a common Dao abstract layer. and i added a getEntityManager() function to the class that extend the abstract class.
Example:
#Repository
#Transactional(value = "secondaryTransactionManager")
#javax.transaction.Transactional
public class TasksSecondaryDao extends TasksDaoAbstract {
#PersistenceContext(unitName = "secondary")
private EntityManager entityManager;
#Override
public EntityManager getEntityManager() {
return entityManager;
}
public void updateTask(Task task) {
entityManager.merge(task);
}
}
#Repository
#Transactional
public class TasksFirstDao extends TasksDaoAbstract {
#PersistenceContext
private EntityManager entityManager;
#Override
public EntityManager getEntityManager() {
return entityManager;
}
public void updateTask(Task task) { entityManager.merge(task); }
}
public abstract class TasksDaoAbstract {
#Transactional(Transactional.TxType.NEVER)
public List<Task> getAll() {
return getEntityManager().createQuery("FROM Task",
Task.class).getResultList();
}
public abstract EntityManager getEntityManager();
}
In general this code is working. But if I am trying to put updateTask method in the abstract class (with #Transactional) it look like the code is working (no error) but the DB is not updating.
I can not understand why the query is not working from the abstract class, the query that only getting data from the db is working from the abstract class.

#Transactional method calling another method without #Transactional annotation works for save but does not work for update

I know this question has been asked before, but I can't still understand what is wrong with the following code:
#Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public void doStuff(User user, Address address) {
userService.save(user);
addressService.update(address);
}
Below the following classes using Spring Data
#Service
public class UserService {
public User save(User user) {
return userRepository.save(user);
}
}
-
public interface UserRepository extends JpaRepository<User, Long>, UserRepositoryCustom {
}
-
#Service
public class AddressService {
public Address update(Address address) {
return addressRepository.update(address);
}
}
-
public interface AddressRepository extends JpaRepository<Address, Long>, AddressRepositoryCustom {
}
-
public interface AddressRepositoryCustom {
void update(Address address);
}
-
#Repository
public class AddressRepositoryImpl implements AddressRepositoryCustom {
#PersistenceContext
private EntityManager entityManager;
private JPAQueryFactory query;
#PostConstruct
public void setUp(){
query = new JPAQueryFactory(entityManager);
}
#Override
public void update(Address entity) {
QAddress qAddress = QAddress.address;
JPAUpdateClause update = new JPAUpdateClause(entityManager, qAddress);
update.where(qAddress.id.eq(entity.getId())).set(qAddress.number,entity.getNumber()).execute();
}
}
Based on the answer, "When you call a method without #Transactional within a transaction block, the parent transaction will continue to the new method". This actually works with the save method. However, on the update method, the following exception is thrown:
javax.persistence.TransactionRequiredException: Executing an update/delete query
I want to know why this happens, what is the explanation?

Generifying Service layer classes

I'm trying to follow code reusing best practices.
I have generic DAO interface with some common methods:
public interface DaoInterface<T> {
T findById(int id);
//...more methods...
}
and its implementation class:
public class GenericDao<T> implements DaoInterface<T> {
#SuppressWarnings("unchecked")
private final Class<T> persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
#Autowired
protected SessionFactory sessionFactory;
#Override
#SuppressWarnings("unchecked")
public T findById(int id) {
Session session = sessionFactory.getCurrentSession();
return (T) session.get(persistentClass, id);
}
//...more methods...
}
Then my every concrete implementation class extends GenericDao and implements its interface.
I also have Service layer in my application. Some Services' methods completely delegate their work to DAO classes. So in the each concrete Service implementation I autowire appropriate DAO class and call its methods.
So now it looks:
public interface CustomerService {
Customer findById(int id);
}
and implementation:
#Service
#Transactional(readOnly = true, rollbackFor = Exception.class)
public class CustomerServiceImpl implements CustomerService {
#Autowired
private CustomerDao customerDao;
#Override
public Customer findById(int id) {
return customerDao.findById(id);
}
}
My question is - how to generify Service classes in the same way as DAO? So that my concrete class will look:
public class CustomerServiceImpl extends GenericService<Customer> implements CustomerService {
.....
}
The problem is that I cannot autowire DAO class in Generic Service:
#Autowired
private GenericDao<T> dao;
so that I could call dao's methods.
Should I do it in the constructor?
And one more question - where is the right place to annotate methods with #Transactional - in generic class or in every implementation class?
You have to create an instance of a generic Dao and put in the service layer some decision:
#Repository
public class GenericDao implements DaoInterface<T> {
//The type must be aquired at runtime,otherwise it may not be thread safe
#Autowired
protected SessionFactory sessionFactory;
#Override
#SuppressWarnings("unchecked")
public T findById(int id,Class<?> persistenceClass) {
Session session = sessionFactory.getCurrentSession();
return (T) session.get(persistenceClass, id);
}
//...more methods...
}
Also if you need a good generic repository layer take a look for Spring Data Jpa
This will make one and only one instance of the GenericDao.
Next you have 2 choice:
Create a singleton services for all your needs
Create a class service for every entity
abstract class GenericService<T> {
#Autowired
protected GenericDao dao;
#SuppressWarnings("unchecked")
protected final Class<T> persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
#Override
public T findById(int id) {
return dao.findById(id,persistenceClass);
}
}
Now every one of your service must extends the GenericService with a supplied persistence type and the job is done.

Java DAO Object Transactions

I have a question as to how this service and its DAO object are performing persistence transactions.
The service is performing transactions on the database - but it is not using a DAOImpl object - it is instead using an object which is an instance of the interface - and naturally has no implementation of any method signatures. This, in my mind, should not be able to perform any meaningful actions. Am I overlooking something here?
Full link to code
http://www.byteslounge.com/tutorials/spring-with-hibernate-persistence-and-transactions-example
#Service
public class UserManagerImpl implements UserManager {
#Autowired
private UserDAO userDAO;
#Override
#Transactional
public void insertUser(User user) {
userDAO.insertUser(user);
}
#Override
#Transactional
public User getUserById(int userId) {
return userDAO.getUserById(userId);
}
#Override
#Transactional
public User getUser(String username) {
return userDAO.getUser(username);
}
#Override
#Transactional
public List<User> getUsers() {
return userDAO.getUsers();
}
}
public interface UserDAO {
void insertUser(User user);
User getUserById(int userId);
User getUser(String username);
List<User> getUsers();
}
#Service
public class UserDAOImpl implements UserDAO {
#Autowired
private SessionFactory sessionFactory;
#Override
public void insertUser(User user) {
sessionFactory.getCurrentSession().save(user);
}
#Override
public User getUserById(int userId) {
return (User) sessionFactory.
getCurrentSession().
get(User.class, userId);
}
#Override
public User getUser(String username) {
Query query = sessionFactory.
getCurrentSession().
createQuery("from User where username = :username");
query.setParameter("username", username);
return (User) query.list().get(0);
}
#Override
#SuppressWarnings("unchecked")
public List<User> getUsers() {
Criteria criteria = sessionFactory.
getCurrentSession().
createCriteria(User.class);
return criteria.list();
}
}
first of all , instance of an interface can not be created , reference variable can be created for interfaces. Nevertheless ,as i followed the link and found that you are learning Spring with Hibernate. Spring provide you a facility called Dependency Injection which is why there is #Autowire annotation in your UserManagerImpl class which means you have injected a dependency UserDAO in UserManagerImpl class , so on rum time ,spring will provide the instance of the class which implements UserDAO interface .What you are overlooking is thorough study of Spring concepts.by the way all the best .

Categories