【问题标题】:Can I place the @Transactional annotation to an entity class?我可以将@Transactional 注释放在实体类中吗?
【发布时间】:2017-03-16 15:24:52
【问题描述】:

我正在尝试使用 Spring 和 Hibernate 框架的Active Record 模式。下面是对这种模式的描述:

一个对象同时携带数据和行为。这些数据大部分是持久的,需要存储在数据库中。 Active Record 使用最明显的方法,将数据访问逻辑放在域对象中。这样,所有人都知道如何在数据库中读取和写入数据。

所以,我删除了传统的Service 类,并将其逻辑和@Transactional 注释移动到实体类中。但是当我再次运行我的应用程序时,抛出了以下异常。

org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
    org.springframework.orm.hibernate5.SpringSessionContext.currentSession(SpringSessionContext.java:133)
    org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:454)
    weibo.datasource.UserDao.save(UserDao.java:17)
    weibo.domain.User.register(User.java:32)
    weibo.web.UserController.register(UserController.java:29)

源代码

UserController 类:

@PostMapping("/users/register")
public String register(@RequestParam("username") String username,
                       @RequestParam("password") String password) {
    User user = new User(userDao, username, password);
    user.register();
    return "redirect:/users/login";
}

User 实体类:

@Entity
@Table(name="USERS")
@Transactional
public class User {
    @Id
    @GeneratedValue
    private int id;
    private String name;
    private String password;

    @Transient
    private UserDao userDao;

    public User() {}
    public User(UserDao userDao, String username, String password) {
        ...
    }

    public void register() {
        userDao.save(this);
    }
}

UserDao 类。没有 @Transactional 注释。

public UserDao(SessionFactory sessionFactory) {
    this.sessionFactory = sessionFactory;
}
public void save(User user) {
    sessionFactory.getCurrentSession().save(user);
}

为什么?

更新

正如@cristianhh 所说,@Transactional 注释必须在 Spring-Managed bean 中使用。但是实体类不是。

【问题讨论】:

  • 不,@Transactional 必须在您的 UserDao 类中。
  • @EssexBoy 在传统的Controller-Service-Dao 实现中,最好将此注解添加到Service 类而不是Dao 类。请看stackoverflow.com/questions/1079114/…

标签: java spring hibernate activerecord transactional


【解决方案1】:

不,@Transactional 由 Spring 管理,@Entity 由 Hibernate 管理。

Hibernate bean 不由 Spring 管理,并且分别不能由 @Transactional 注释包装。

但是,您可以在服务/存储库层中使用 @Transactional 并包装一个发送实体的数据访问对象 (DAO) 的函数。

【讨论】:

  • 另一个问题:我将注释移动到UserController 类,但抛出了同样的异常。为什么?
  • 当然这不是一个好习惯,我只是想知道源代码的原因。
  • @walsh 是你的UserController 类,用@Controller 注释标记?
  • 是的。我添加@Controller 来注释UserController 类。
猜你喜欢
  • 2012-01-01
  • 2011-03-08
  • 2010-11-05
  • 2014-12-25
  • 1970-01-01
  • 2016-10-17
  • 1970-01-01
  • 2016-11-17
  • 1970-01-01
相关资源
最近更新 更多