当我在一个方法中有多个操作时,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> {
}
答案 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可以优化事务资源。