您应该将@Transactional放在DAO类和/或它们的方法中,还是更好地注释使用DAO对象调用的服务类?或者对两个“层”都加注释有意义吗?
当前回答
传统Spring体系结构的正确答案是将事务语义放在服务类上,原因其他人已经描述过了。
An emerging trend in Spring is toward domain-driven design (DDD). Spring Roo exemplifies the trend nicely. The idea is to make the domain object POJOs a lot richer than they are on typical Spring architectures (usually they are anemic), and in particular to put transaction and persistence semantics on the domain objects themselves. In cases where all that's needed is simple CRUD operations, the web controllers operate directly on the domain object POJOs (they're functioning as entities in this context), and there's no service tier. In cases where there's some kind of coordination needed between domain objects, you can have a service bean handle that, with @Transaction as per tradition. You can set the transaction propagation on the domain objects to something like REQUIRED so that the domain objects use any existing transactions, such as transactions that were started at the service bean.
从技术上讲,这种技术使用了AspectJ和<context:spring-configured />。Roo使用AspectJ类型间定义将实体语义(事务和持久性)与领域对象(基本上是字段和业务方法)分离开来。
其他回答
事务注释应该放在所有不可分割的操作周围。
例如,你的呼叫是“change password”。它由两个操作组成
修改密码。 审计变更。 通过电子邮件通知客户端密码已更改。
那么在上面,如果审计失败,那么修改密码也应该失败吗?如果是这样,那么事务应该在1和2左右(因此在服务层)。如果电子邮件失败了(可能应该有某种故障安全措施,这样它就不会失败),那么它是否应该回滚更改密码和审计?
在决定将@Transactional放在哪里时,您需要询问这些问题。
服务层中的@事务使用是通过使用控制器层(@Controller)调用的,服务层调用DAO层(@Repository),即数据库相关的操作。
@Transactional注释应该放在所有不可分割的操作周围。 使用@Transactional可以自动处理事务传播。在这种情况下,如果当前方法调用了另一个方法,那么该方法将可以选择加入正在进行的事务。
让我们举个例子:
我们有两个模型,即国家和城市。国家和城市模型的关系映射就像一个国家可以有多个城市,所以映射就像,
@OneToMany(fetch = FetchType.LAZY, mappedBy="country")
private Set<City> cities;
在这里国家映射到多个城市,获取他们懒惰。这里是@Transactinal的作用当我们从数据库中检索Country对象时,我们会得到Country对象的所有数据,但不会得到城市的集合,因为我们是懒洋洋地获取城市。
//Without @Transactional
public Country getCountry(){
Country country = countryRepository.getCountry();
//After getting Country Object connection between countryRepository and database is Closed
}
当我们想要从国家对象访问Set of Cities时,我们将在该Set中获得空值,因为只有该Set创建的对象没有初始化该Set的数据来获取Set的值,我们使用@Transactional,即,
//with @Transactional
@Transactional
public Country getCountry(){
Country country = countryRepository.getCountry();
//below when we initialize cities using object country so that directly communicate with database and retrieve all cities from database this happens just because of @Transactinal
Object object = country.getCities().size();
}
所以基本上@Transactional is Service可以在单个事务中进行多个调用,而无需关闭与端点的连接。
@Transactional应该用于服务层,因为它包含业务逻辑。DAO层通常只有数据库CRUD操作。
// the service class that we want to make transactional
@Transactional
public class DefaultFooService implements FooService {
Foo getFoo(String fooName);
Foo getFoo(String fooName, String barName);
void insertFoo(Foo foo);
void updateFoo(Foo foo);
}
春季文档:https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html
服务层是添加@Transactional注释的最佳位置,因为这里呈现的大多数业务逻辑都包含细节级用例行为。
假设我们将它添加到DAO,从服务调用2个DAO类,一个失败,另一个成功,在这种情况下,如果@Transactional不在服务上,一个DB将提交,另一个DB将回滚。
因此,我的建议是明智地使用这个注释,只在服务层使用。
Github项目- java-algos
推荐文章
- 导致java.lang.VerifyError错误的原因
- 如何在Java中监控计算机的CPU、内存和磁盘使用情况?
- 如何设置超时在改造库?
- java lambda可以有一个以上的参数吗?
- HashMap -获取第一个键值
- 使用Jackson将JSON字符串转换为漂亮的打印JSON输出
- Android - SPAN_EXCLUSIVE_EXCLUSIVE跨度不能为零长度
- Javadoc @see或{@link}?
- 在准备语句中使用“like”通配符
- Android Eclipse -无法找到*.apk
- javac和Eclipse编译器之间的区别是什么?
- 工厂模式和策略模式之间的区别是什么?
- 在Java中使用正则表达式提取值
- 如何允许所有网络连接类型HTTP和HTTPS在Android(9)馅饼?
- Intellij IDEA Java类在保存时不能自动编译