walsh
walsh

Reputation: 3273

Can I place the @Transactional annotation to an entity class?

I am trying the Active Record pattern using Spring and Hibernate framework. Below is the description of this pattern:

An object carries both data and behavior. Much of this data is persistent and needs to be stored in a database. Active Record uses the most obvious approach, putting data access logic in the domain object. This way all people know how to read and write their data to and from the database.

So, I removed the traditional Service class and moved its logic and the @Transactional annotation to the entity class. But when I run my application again, the following exception was thrown.

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)

Source Code

The UserController class:

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

The User entity class:

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

The UserDao class. No @Transactional annotated.

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

Why?

UPDATE

As @cristianhh said, the @Transactional annotation must be used in a Spring-Managed bean. However, the entity class is not.

Upvotes: 2

Views: 1852

Answers (1)

cristianhh
cristianhh

Reputation: 138

No, while @Transactional is managed by Spring, @Entity is managed by Hibernate.

Hibernate beans are not managed by Spring and respectively not wrappable by the @Transactional annotation.

You can however, use @Transactional in the service/repository layer and wrap a function sending the entity's data access object (DAO).

Upvotes: 4

Related Questions