【问题标题】:Persist a value of an object when it is set设置对象时保持其值
【发布时间】:2011-05-03 18:20:17
【问题描述】:

我是 JPA+Hibernate+Spring 的新手(但我对 Web 应用程序和 SQL 的 Spring 框架有相当多的经验)所以我的问题可能不是在 JPA 中使用正确的技术术语。

我有一个典型的User POJO,它用javax.persistence.* 注释,我根据我发现的示例设置了 hibernate+hsqldb,这些示例目前工作正常。 User 类看起来像这样:

@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;
    }

}

这是我的UserDAOImpl 课程。

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);
    }
}

通过使用getGiUser 方法,我可以从数据库中获取持久对象(如果我理解正确的话)。我的问题是是否可以使User.setName() 方法在调用时立即提交到数据库而无需手动保存?我应该如何或从哪里开始或了解这一点?

【问题讨论】:

    标签: java hibernate spring jpa persistence


    【解决方案1】:

    据我所知,您正在寻找一个调用 UserDAO 的服务 bean:

    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 来自这里:

    http://static.springsource.org/spring/docs/current/spring-framework-reference/html/transaction.html

    此外,使用 HibernateTemplate 不再是使用 Hibernate 的首选方式。 Spring 文档的这一部分展示了如何使用直接的 Hibernate 代码:

    http://static.springsource.org/spring/docs/current/spring-framework-reference/html/orm.html

    但是,您实际上可能更喜欢将 Hibernate 作为 JPA 2 提供程序与 Spring 一起使用; ORM 章节(上)还展示了如何将 JPA 与 Spring 集成。 Hibernate 仍然可以继续作为您的 JPA 2 提供者。这样,您就可以将所有代码与 Spring 和 Hibernate 分离,只需将标准 JPA 2 注释与 EntityManager 一起使用。

    【讨论】:

    • 是否使用 EntityManager 处理事务提交?我之所以问是因为我在他们的实体管理器中使用了 openrdf-sesame。对实体对象的所有更改都会立即提交到三重存储。所以我想知道JPA中是否有相同的概念。
    • +1 关于使用 EntityManager 以及 HibernateTemplate 的使用不是首选方法的建议。
    • @gigadot:是的,您可以使用 JPA 2 指定事务块。不过,IIRC 是一个不同的注释。另外,请记住,我没有亲自通过 Spring 使用 Hibernate 作为持久性提供程序尝试过 JPA 2 - 但我更愿意现在使用它,而不是我现在拥有的“遗留” HibernateTemplate 代码。
    【解决方案2】:

    您可以使用拦截机制来实现这一点。事实是更改必须保存在某个地方,但是您的 User 类不是这样做的好地方,因此您可以在其他地方编写代码并使用拦截或面向方面的机制,使用像 Spring 这样的应用程序框架来监视正在调用的方法,并在调用特定方法(如 setName)时保存类的状态。

    这里是 an example 的 hibernate 和 spring 集成

    【讨论】:

      【解决方案3】:

      当您从会话中获取用户时(使用session.get()session.load()、关联遍历或 HQL 或 Criteria 查询),对用户所做的任何更改都将在提交周围事务时提交(没有任何需要致电saveupdatesaveOrUpdatemerge)。它不会立即写入数据库(刷新),但会在必要时写入:在提交之前,或在执行结果可能取决于刷新的查询之前。你通常不需要关心。

      如果“提交到数据库”是指在事务提交方面提交,那么这是不可能的。提交周围事务时提交更改。

      如果您希望在当前事务之外提交特定更新,则需要在另一个事务中进行更新,使用 BobG 答案中的代码,但使用 @Transactional(propagation = Propagation.REQUIRES_NEW) 注释。

      也许你应该更准确地解释你想做什么,以及为什么要这样做。

      【讨论】:

      • 我对 JPA 比较陌生,所以我仍然不太明白您所说的“提交周围事务时”是什么意思。是的,我的意思是这些值将提交给关系表。如果可能的话,我可以降低编码的复杂性(无需我需要额外的保存或更新)。
      猜你喜欢
      • 2022-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多