I am a completely new to JPA+Hibernate+Spring (but I have a fairly much experience with Spring framework for web application and SQL) so my question here may not be using the correct technical term in JPA.
I have a typical User
POJO which is annotated with javax.persistence.*
and I have set up hibernate+hsqldb according to examples I found which are currently working fine. The User
class looks like this :
@Entity
@Table(name = "USER")
public class User {
private Long id;
private String name;
// Ignore id getter and setter methods
@Column(name = "USER_NAME")
public String getName() {
开发者_运维技巧 return name;
}
public void setName(String name) {
this.name = name;
}
}
This is my UserDAOImpl
class.
public class UserDAOImpl implements UserDAO {
private HibernateTemplate hibernateTemplate;
public void setSessionFactory(SessionFactory sessionFactory) {
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
@Override
public void saveUser(User user) {
hibernateTemplate.saveOrUpdate(user);
}
// This method is made to return only one User object.
@Override
@SuppressWarnings("unchecked")
public User getGiUser() {
return hibernateTemplate.find("from User where User_Name ='gi'").get(0);
}
}
By using getGiUser
method, I can get the persistent object from the database (If I understand correctly). My question is whether it is possible to make the User.setName()
method to commit immediately to database when it is called without having to save it manually? How or where should I start or learn about this?
From what I've seen, you're looking for a service bean that calls UserDAO:
public class UserServiceImpl implements UserService {
private UserDAO userDao; // injected by Spring
@Transactional
public void changeUserName(String name) {
User user = userDao.getGiUser();
user.setName(name);
// I can't remember if this saveUser() call is required, or if
// Hibernate will automatically pick up the changes and save the
// user object
userDao.saveUser(user);
}
}
@Transactional comes from here:
http://static.springsource.org/spring/docs/current/spring-framework-reference/html/transaction.html
Also, usage of HibernateTemplate isn't the preferred way of using Hibernate anymore. This part of the Spring docs shows how to use straight Hibernate code:
http://static.springsource.org/spring/docs/current/spring-framework-reference/html/orm.html
You may actually prefer to use Hibernate as a JPA 2 provider with Spring, however; the ORM chapter (above) also shows how to integrate JPA with Spring. Hibernate can still continue to be your JPA 2 provider. That way you decouple all your code from Spring and Hibernate and just use the standard JPA 2 annotations with an EntityManager.
You can use an interception mechanism to achieve this. The truth is the change has to be saved somewhere along the line but your User class is not a good place to do that so you can write the code somewhere else and use an interception or Aspect Oriented mechanism using an application framework like Spring to monitor the methods that are being called and whenever a specific method (like setName) is called save the state of your class.
Here's an example of hibernate and spring integration
When you get a User from the session (with session.get()
, session.load()
, association traversal, or a HQL or Criteria query), any change made to the user will be committed when the surrounding transaction is committed (without any call to save
, update
, saveOrUpdate
or merge
needed). It will not be written to the database (flushed) immediately, but will be when necessary : before the commit, or before the execution of a query whose result might depend on the flush. You normally don't need to care.
If by "committed to the database", you mean committed in terms of transactional commit, then it's not possible. The changes are committed when the surrounding transaction is committed.
If you want a specific update to be committed outside of the current transaction, then you need to make the update in another transaction, using code such as the one in BobG's answer, but annotated with @Transactional(propagation = Propagation.REQUIRES_NEW)
.
Maybe you should explain more precisely what you want to do, and why you want to do it.
精彩评论