服务层和数据访问层中的Spring事务

6
在我的示例中,我有一个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);
    }

}

使用DAO在Service中这样的方式时
@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)都被保存(这是我需要的行为)。我的问题是服务层上的Transactional注释如何影响事务(方法executeTransaction())执行。为什么没有服务层上的Transactional注释时,两行都保存在数据库中,而使用此注释时仅保存最后一行?


不要将DAO类标记为事务性的。我认为事务应该属于服务层。服务层知道工作单元和用例,如果您有多个DAO注入到一个需要在单个事务中一起工作的服务中,则非常有帮助。 - Jeevan Patil
2个回答

5

如果没有 myEntity = new MyEntity(); ,那么在数据库中更新记录而不是插入记录,因为它是相同的实体。我建议在hibernate配置中设置<property name="show_sql">true</property>。这将显示正在发生的情况。


GenerationType.IDENTITY让数据库负责PK生成。因此,如果您的列在数据库中不是自动递增和PK,则为0是正常的。 - Evgeni Dimitrov
我设置了show_sql属性,然后发现第二个查询是更新操作。谢谢,这解释了我需要的东西。 - mvb13

0

只有在存储两个不同的对象时,才会将两个不同的记录保存在数据库中。当您已经注释掉了那行代码时,您正在设置(即更新)同一对象中的属性。因此,Hibernate将更新相同的行,而不是创建新的行。 但是,当您取消注释该行时,您正在创建一个尚未持久化的新实例。因此,它将导致在数据库中插入新行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接