服务层和 DAO 层中的 Spring 事务

Posted

技术标签:

【中文标题】服务层和 DAO 层中的 Spring 事务【英文标题】:Spring transaction in service and DAO layers 【发布时间】:2013-05-16 07:33:13 【问题描述】:

在我的示例中,我有一个 Hibernate 实体和一个 DAO。

@Entity
@Table(name="myEntity")
public class MyEntity 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id")
    private long id;

    @Column(name="action")
    private String actionName;



...................

@Repository("myDAO")
@Transactional(propagation = Propagation.REQUIRED)
public class MyDAO 

    @Autowired
    private SessionFactory sessionFactory;

    public void saveObject(MyEntity myEntity)
        sessionFactory.getCurrentSession().save(myEntity);
    


当我以这种方式在 Service 中使用 DAO 时

@Service("myService")
@Transactional(propagation = Propagation.REQUIRED)
public class MyService 


    @Autowired
    private MyDAO myDAO;

    public void executeTransaction()
        MyEntity myEntity = new MyEntity();

        myEntity.setActionName("Action1");
        myDAO.saveObject(myEntity);

//      myEntity = new MyEntity();
        myEntity.setActionName("Action2");
        myDAO.saveObject(myEntity);
    


只有一行(Action2)保存在数据库中。当我删除评论时,两行(Action1 和 Action2)都被保存(这是我需要的行为)。我的问题是服务层上的事务注释如何影响事务(方法执行事务())执行。为什么在服务层上没有事务注释,两行都保存在数据库中,并且只有最后一个与此注释一起保存?

【问题讨论】:

不要将 DAO 类标记为事务性的。我认为事务属于服务层。它了解工作单元和用例。如果您将多个 DAO 注入到需要在单个事务中协同工作的服务中,这将很有帮助。 【参考方案1】:

如果没有myEntity = new MyEntity();,您在数据库中的记录会更新,而不是插入,因为它是同一个实体。我建议在休眠配置中设置<property name="show_sql">true</property>。这会告诉你发生了什么。

【讨论】:

GenerationType.IDENTITY 让数据库负责 PK 生成。因此,如果您没有将数据库中的列作为自动增量和 PK,则为 0 是正常的 我设置了属性 show_sql,我看到第二个查询是更新。谢谢,这解释了我需要的东西。【参考方案2】:

只有当您存储两个不同的对象时,才会将两条不同的记录保存在数据库中。当您评论该行时,您正在同一对象中设置(意味着更新)属性。因此,休眠将更新同一行,而不是创建一个新行。 但是,当您取消注释该行时,您正在创建一个尚未持久化的新实例。因此,它将导致在数据库中插入一个新行。

【讨论】:

以上是关于服务层和 DAO 层中的 Spring 事务的主要内容,如果未能解决你的问题,请参考以下文章

java ee EJB中的服务层和dao层

Spring中层之间的@Transaction注解

事务注释在 Spring Boot 2.1.3 中不起作用

java中dao层和service层的区别是啥?

服务层和数据访问对象层如何适应 Spring MVC 架构?

带有涉及两个 DAO 的遗留代码的 Spring 事务