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 .
Related
In the applicationContext file I have added the package to map it.
The call arrives, but the variable is still null and does not pass to the server. In other classes, the same is working correctly.
Thanks in advance!
#ManagedBean(name="registerUser")
#SessionScoped
public class RegisterUser{
#ManagedProperty("#{userService}")
private DAOUser userService;
private User user = new User();
public DAOUser getUserService() {
return userService;
}
public void setUserService(DAOUser userService) {
this.userService = userService;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String register() {
// Calling Business Service
String passwordEncripada = PasswordControl.encriptString(user.getPassword());
user.setPassword(passwordEncripada);
userService.register(user);
// Add message
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage("Registro realizado"));
return "";
}
and DAOUser class:
#Component
public class DAOUser implements Serializable {
#Autowired
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
#Transactional
public void register(User user){
// Acquire session
Session session = sessionFactory.getCurrentSession();
// Save employee, saving behavior get done in a transactional manner
session.save(user);
}
}
EDIT: The setter is called, but the object it sends is null
I think the problem was in the normalization of the DAOUser class name. I have gone to use #Repository ("userService") instead of #Component and it is already working.
#Repository("userService")
public class DAOUser implements Serializable {
#Autowired
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
#Transactional
public void register(User user){
// Acquire session
Session session = sessionFactory.getCurrentSession();
// Save employee, saving behavior get done in a transactional manner
session.save(user);
}
}
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?
In my Spring project I want to update mysql table field according to the url :
I have url below:
localhost:9191/access/name/article?key=xyz
I want to fetch the article from url and then update the status and article field of the corrsponding mysql table
In my database I have the table name "user".
user(stu_id,name,email,article,status)
mysql query is:
UPDATE user
SET article='null', status=true
WHERE article='xyz'; here xyz=user.getArticle()
To achieve this I have done the below
User.java is:
public User(String article, String status) {
super();
this.article = article;
this.status = status;
}
UserDao.java
public interface UserDao {
public void updateUser(User user);
}
UserDaoImpl.java is:
#Transactional
#Repository("userDao")
public class UserDaoImpl implements UserDao {
#Autowired
private SessionFactory sessionFactory;
public void updateUser(User user) {
String hql = "update user set article = null,status=true"
+"where article=:key1";
sessionFactory.getCurrentSession().createQuery(hql)
.setParameter("key1", user.getArticle());
}
}
UserService.java is:
public interface UserService {
User updateUser(String article, String status);
}
UserServiceImpl.java is:
#Service("userService")
#Transactional(propagation = Propagation.SUPPORTS)
public class UserServiceImpl implements UserService {
public User updateUser(String article, String status) {
User user = new User(article,status);
userDao.updateUser(user);
return user;
return user;
}
UserController.java is:
//localhost:9191/access/name/article?key=xyz
#RequestMapping(value="/access/name/id", method=RequestMethod.GET)
public #ResponseBody String byParameter( User user, HttpServletRequest request) {
boolean ps=true;
String foo= request.getParameter("key");
userService.updateUserinfo(foo, ps);
return "signupLogin";
}
but it is showing error:
ERROR [] (ErrorCounter.java:56) - line 1:51: unexpected token: key
ERROR [] (ErrorCounter.java:56) - line 1:58: unexpected token: =
java.lang.IllegalArgumentException: node to traverse cannot be null!
at org.hibernate.impl.SessionImpl.createQuery(SessionImpl.java:1760)
at com.student.dao.UserDaoImpl.updateUser(UserDaoImpl.java:40)
at com.student.service.UserServiceImpl.updateUserinfo(UserServiceImpl.java:66)
where is the problem?What am I doing wrong??
Make following correction into sql query use User in place of user into query.
String hql = "update User set article = null, status = true where article = :key1";
if you don't want to change this method then you can use createSqlQuery method in place of createQuery method .
this solution may be help.
at com.student.dao.UserDaoImpl.updateUser(UserDaoImpl.java:40)
you were executing the wrong query.you should do like below code:
#Transactional
#Repository("userDao")
public class UserDaoImpl implements UserDao {
#Autowired
private SessionFactory sessionFactory;
public void updateUser(User user) {
String hql = "update user set article = null,status=true"
+"where article=:key1";
sessionFactory.getCurrentSession().createSQLQuery(hql)
.setParameter("key1", user.getArticle());
}
}
the syntax is like:
where user(this is the database table ) and article,status are the fields
I created a spring application where i decided to add a BaseDAO to eliminate redundant create,
update,delete,findByid,and findAll methods for every dao. So i created a baseDao and every dao should extend this BaseDAO.
BaseDaoImpl
public class BaseDAOImpl implements BaseDAO{
SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sf){
this.sessionFactory = sf;
}
#Override
public void create(ModelBase modelBase) {
Session session = this.sessionFactory.getCurrentSession();
session.persist(modelBase);
}
#Override
public void update(ModelBase modelBase) {
Session session = this.sessionFactory.getCurrentSession();
session.update(modelBase);
}
#Override
public Collection findAll(Class aClass) {
Session session = this.sessionFactory.getCurrentSession();
Collection modelCols = session.createQuery("from "+aClass.getSimpleName()).list();
return modelCols;
}
#Override
public ModelBase findById(Class aClass, Integer id) {
Session session = this.sessionFactory.getCurrentSession();
ModelBase modelBase = (ModelBase) session.load(aClass, new Integer(id));
return modelBase;
}
}
Then i extends this Dao to each DAO
EmployeeDAOImp
public class EmployeeDAOImpl extends BaseDAOImpl implements EmployeeDAO{
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sf){
this.sessionFactory = sf;
}
}
I created a BaseService like this. But when i try to access BaseDAO methods from EmployeeDAO it returns null pointer exception.
Why this happen. I dont want to use genericDAO from google. Because we should create DAOs
for each model. I want to eliminate this. So I follow this method.
Have you though about Spring Data project & Spring Data JPA in particular?
This would save you lots of time, since you would no longer need to write your DAO / Repositories from scratch, all you need to do is enable Spring Data JPA, and add needed interfaces. It should save you tons of time.
http://projects.spring.io/spring-data-jpa/
http://spring.io/guides/gs/accessing-data-jpa/ - Sample project
Your are overriding setSessionFactory from base class for no reason, its already available with extending class EmployeeDAOImpl , either remove it or try below:
public class EmployeeDAOImpl extends BaseDAOImpl implements EmployeeDAO{
//this reference should be from base class,
// the extending class ref is hiding base ref.
// private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sf){
super.setSessionFactory(sf);
}
}
Something like the following should work (note the use of constructor rather than setter injection). In the BaseDAO:
public class BaseDAOImpl implements BaseDAO {
private final SessionFactory sessionFactory;
public BaseDAOImpl(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
}
Then in the Employee DAO:
public class EmployeeDAOImpl extends BaseDAOImpl implements EmployeeDAO {
#Inject
public EmployeeDAOImpl (SessionFactory sessionFactory) {
super(sessionFactory);
}
}
You can create generic dao.
#Repository("genericDao")
public class GenericDaoImpl<T,PK extends Serializable> implements GenericDao<T, PK> {
protected Class<T> entityClass;
public T create(T t) {
this.entityManager.persist(t);
return t;
}
public T read(PK id,Class<T> c) {
return (T)this.entityManager.find(c, id);
}
public T update(T t) {
return this.entityManager.merge(t);
}
public void delete(T t) {
t = this.entityManager.merge(t);
this.entityManager.remove(t);
}
public List<T> getAll(Class<T> c){
return this.entityManager.createQuery("SELECT o FROM "+ c.getName() +" o").getResultList();
}
}
UPDATED
You can use as following, TimeRange is a pojo class in the following example. If you do not want a service layer. You can use timeRangeDao in controller.
#Service("timeRangeService")
public class TimeRangeServiceImpl implements TimeRangeService{
#Autowired
GenericDao<TimeRange,Long> timeRangeDao;
public List<TimeRange> getAllTimeRanges(){
return timeRangeDao.getAll(TimeRange.class);
}
#Transactional
public void createTimeRange(TimeRange c) {
timeRangeDao.create(c);
}
#Transactional
public void update(TimeRange p) {
timeRangeDao.update(p);
}
#Transactional
public TimeRange getTimeRange(long id) {
return timeRangeDao.read(id, TimeRange.class);
}
#Transactional
public void delete(long id) {
TimeRange timeRange = new TimeRange();
timeRange.setId(id);
timeRangeDao.delete(timeRange);
}
}
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.