@Transactional 与 JPA 和 Hibernate 有啥用?
Posted
技术标签:
【中文标题】@Transactional 与 JPA 和 Hibernate 有啥用?【英文标题】:What is the use of @Transactional with JPA and Hibernate?@Transactional 与 JPA 和 Hibernate 有什么用? 【发布时间】:2019-06-16 23:42:48 【问题描述】:我正在学习如何使用 JPA 和 Hibernate 以及 mysql 数据库创建 REST API,我看到了这个 @Transactional 注释。有人可以解释这个注释的用途吗?
例如我有这个简单的 DAO 类:
@Repository
public class EmployeeDAOHibernateImpl implements EmployeeDAO
// define field for entitymanager
private EntityManager entityManager;
// set up constructor injection
@Autowired
public EmployeeDAOHibernateImpl(EntityManager entityManager)
this.entityManager = entityManager;
@Override
@Transactional
public List<Employee> findAll()
// get the current hibernate session
Session currentSession = entityManager.unwrap(Session.class);
// create a query
Query<Employee> theQuery =
currentSession.createQuery("from Employee", Employee.class);
// execute query and get result list
List<Employee> employees = theQuery.getResultList();
// return the results
return employees;
您可以看到用于 findAll() 方法的@Transactional,但是如果我删除这个@Transactional 我会得到相同的输出...那么这个@Transactional 有什么用?
【问题讨论】:
Spring - @Transactional - What happens in background?的可能重复 这与 JPA ... FWIW 无关。那是春天 【参考方案1】:@Transactional
注释用于当您希望某个方法/类(=内部的所有方法)在事务中执行时。
假设用户 A
想要将 100 美元转给用户 B
。会发生什么:
-
我们将 A 的账户减少 100 美元
我们向 B 的帐户添加 100 美元
假设在成功1)
之后和执行2)
之前抛出异常。现在我们会出现某种不一致,因为A
损失了 100 美元,而B
一无所获。
交易意味着全部或全部。如果方法中某处抛出异常,则更改不会持久保存在数据库中。发生了名为rollback
的事情。
如果您不指定@Transactional
,每个数据库调用将在不同的事务中。
【讨论】:
一个不错的答案,但应该添加一件事 - 如果示例代码@Transactional
是不必要的,也许它是“迷信编程”,有人总是添加 @Transactional 即使它没有效果“只是万一”:)【参考方案2】:
一般@Transactional
注解写在服务层。
它用于将多个写入在数据库上作为单个原子操作。
当有人调用带有@Transactional
注释的方法时数据库上的所有或没有写入被执行。
在读取操作的情况下它没有用,因此在单个原子写入的情况下也是如此。您在单次读取(选择)中使用它,因此添加或删除 @Transactional
注释没有影响。
【讨论】:
在读取操作中,如果使用 Java Streams 来放置选择结果会很有用... 值得补充的是,当对处于persistent
状态(由实体管理器管理)的实体进行多次更新时,应使用@Transactional
,因此save()
不能显式放入代码,但设置器在实体上调用
@viruskimera 你能详细说明或提供一些链接吗?【参考方案3】:
该类在其自身或其成员上声明@Transactional
,Spring 创建一个代理,该代理实现与您正在注释的类相同的接口。换句话说,Spring 将 bean 包装在代理中,而 bean 本身不知道它。
代理为 Spring 提供了一种在方法调用之前、之后或周围将行为注入被代理对象的方法。
在内部,它与使用事务通知(使用 AOP)相同,其中首先创建代理并在目标 bean 的方法之前/之后调用。
生成的代理对象由 Spring 创建的 TransactionInterceptor
提供。因此,当从客户端代码调用@Transactional
方法时,首先从代理对象调用TransactionInterceptor
,代理对象开始事务并最终调用目标bean 上的方法。当调用完成时,TransactionInterceptor
相应地提交/回滚事务
【讨论】:
以上是关于@Transactional 与 JPA 和 Hibernate 有啥用?的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot 和 Spring Data JPA @Transactional 不工作
如何处理来自catch块的spring jpa @transactional和新插入[重复]
Spring Data JPA @Modifying 注解使用@Transactional