Spring Data JPARepository和@Transactional用于一个方法内的多个操作

时间:2013-09-16 22:49:28

标签: java spring jpa spring-data-jpa

当我在一个方法中有多个操作时,saveUser方法不会保存用户对象名称更改。如果我在saveUser服务方法之上使用@Transactional(propagation = Propagation.REQUIRED),它可以正常工作。当另一个类创建一个新的User对象并设置其所有值并调用createUser方法时,它可以正常工作。为什么我需要@Transactional作为saveUser方法?在什么情况下我需要包含@Transactional?我正在使用Spring Data和JPA(Hibernate impl)。有什么想法吗?

JPA实体:

@Entity
public class User{
    @Id
    @GeneratedValue
    private Long id;
    @Column
    private String name;

//getters/setters..etc

}

春季服务:

@Service
public class UserServiceImpl{
  @Autowired
  UserRepository userRepository;

  public void saveUser(Long id){
      User user = userRepository.findById(id);
      user.setName("newname");
      userRepository.save(user);
  }

  public void createUser(User user){
      userRepository.save(user);
  }
}

Spring Data JPA / Hibernate Impl Repository:

public interface UserRepository extends JpaRepository<User, Long> {
}

2 个答案:

答案 0 :(得分:3)

JpaRepository中的方法默认是事务性的(只读用于检索)。

现在,在您的saveUser()方法中,您需要@Transactional,因为您正在通过User检索id并更新它,然后再次持久保存到数据库。基本上,在阅读时使用@Transactional(readOnly=true),而在Spring Data JPA中使用了@Transactional

 User user = userRepository.findById(id);
如果找不到用户,

会将null返回user,而user.setName("newname");会提供NullPointerException

答案 1 :(得分:0)

如果更新数据库状态(插入/更新/删除),则需要事务,否则最终会出现此行为。

即使您在方法中执行只读操作,也应该使用@Transactional(readOnly=true)对它们进行注释,以便Spring可以优化事务资源。