Spring Data Jpa 简单使用事务

本文介绍如何使用SpringData JPA确保跨表操作的一致性。通过对比带有和不带有事务注解的方法,展示了当遇到唯一键冲突时,如何回滚所有已执行的操作。
Spring Data Jpa 简单使用事务

对于两张表,需要顺序操作,必须全部表均操作成功才可,否则两张表不操作。
例如,现在有device,collectionpoint两张表,向两张表顺序执行insert操作
SQL如下

INSERT INTO device (dev_id, tenant_id, user_id)
VALUES
    ('bangjile', 909, 909);
INSERT INTO collectionpoint (
    device_id,
    tenant_id,
    point_name
)
VALUES
    (808,808,'ceshihahah');

这种方式下,必须两条语句均成功才可,否则均不成功

使用JPA进行操作
现有device的repository

@Repository
public interface DeviceEntityRepository extends JpaRepository<DeviceEntity,Integer> {}

collectionpoint的repository

@Repository
public interface CollectionPointRepository extends JpaRepository<CollectionpointEntity,Integer> {}

新建一个测试repository,用来测试事务操作

@Repository
public class TestRepository {
    @Autowired
    DeviceEntityRepository deviceEntityRepository;
    @Autowired
    CollectionPointRepository repository;
    public void testMethod(){
        DeviceEntity deviceEntity=new DeviceEntity();
        deviceEntity.setDevId("gogogo12");
        deviceEntity.setTenantId(88);
        deviceEntity.setUserId(88);
        deviceEntityRepository.save(deviceEntity);
        CollectionpointEntity collectionpointEntity=new CollectionpointEntity();
        collectionpointEntity.setDeviceId(8);
        collectionpointEntity.setTenantId(88);
        collectionpointEntity.setPointName("chongtu11");
        repository.save(collectionpointEntity);
    }
}

执行该测试方法,两条数据均写入成功。

由于测试方法中的实体类赋值了非空键和唯一键。下面来测试device写入成功,collectionpoint写入冲突的情况

 public void testMethod(){
        DeviceEntity deviceEntity=new DeviceEntity();
        deviceEntity.setDevId("gogogo122");
...
        CollectionpointEntity collectionpointEntity=new CollectionpointEntity();
        collectionpointEntity.setDeviceId(8);
        collectionpointEntity.setTenantId(88);
        collectionpointEntity.setPointName("chongtu11");
        repository.save(collectionpointEntity);
    }

执行方法,调试窗口显示collectionpoint冲突,但查看数据库显示device表中新增了gogogo122的数据,说明整个testMethod方法不具有事务性

事务实现:
只需要在testMethod上方添加一句注解即可

@Transactional(readOnly = false, rollbackFor = Throwable.class)
    public void testMethod(){
...
}

现在再次修改device实体数据,使写入非冲突,collectionpoint实体保持冲突。

执行方法,调试窗口显示collectionpoint冲突,但数据库中device表中为增加新数据。

调试信息如下,显示了jpa的整个过程

06-02 18:03:51.386 DEBUG 11624 --- [nio-8089-exec-1] org.hibernate.SQL                        : insert into public.device (dev_desc, dev_id, dev_manufacture, dev_note, dev_position1, dev_position2, dev_sn, dev_type, emp_id, tenant_id, user_id, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into public.device (dev_desc, dev_id, dev_manufacture, dev_note, dev_position1, dev_position2, dev_sn, dev_type, emp_id, tenant_id, user_id, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2017-06-02 18:03:51.392 DEBUG 11624 --- [nio-8089-exec-1] org.hibernate.SQL                        : insert into public.collectionpoint (device_id, point_alarm_contacts, point_alarm_flag, point_desc, point_downlimit, point_downlimit2, point_name, point_scale, point_type, point_unit, point_uplimit, point_uplimit2, tenant_id, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into public.collectionpoint (device_id, point_alarm_contacts, point_alarm_flag, point_desc, point_downlimit, point_downlimit2, point_name, point_scale, point_type, point_unit, point_uplimit, point_uplimit2, tenant_id, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2017-06-02 18:03:51.404 ERROR 11624 --- [nio-8089-exec-1] druid.sql.Statement                      : {conn-10005, pstmt-20004} execute error. insert into public.collectionpoint (device_id, point_alarm_contacts, point_alarm_flag, point_desc, point_downlimit, point_downlimit2, point_name, point_scale, point_type, point_unit, point_uplimit, point_uplimit2, tenant_id, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "collectionpoint_point_name_device_id_tenant_id_key"
  详细:Key (point_name, device_id, tenant_id)=(chongtu11, 8, 88) already exists.
  ................................此处为异常信息...................
2017-06-02 18:03:51.409 DEBUG 11624 --- [nio-8089-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : could not execute statement [n/a]
................................此处为异常信息...................
2017-06-02 18:03:51.410  WARN 11624 --- [nio-8089-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 0, SQLState: 23505
2017-06-02 18:03:51.410 ERROR 11624 --- [nio-8089-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : ERROR: duplicate key value violates unique constraint "collectionpoint_point_name_device_id_tenant_id_key"
  详细:Key (point_name, device_id, tenant_id)=(chongtu11, 8, 88) already exists.
2017-06-02 18:03:51.412  INFO 11624 --- [nio-8089-exec-1] o.h.e.j.b.internal.AbstractBatchImpl     : HHH000010: On release of batch it still contained JDBC statements
2017-06-02 18:03:51.413 DEBUG 11624 --- [nio-8089-exec-1] o.h.jpa.spi.AbstractEntityManagerImpl    : Mark transaction for rollback
2017-06-02 18:03:51.415 DEBUG 11624 --- [nio-8089-exec-1] cResourceLocalTransactionCoordinatorImpl : JDBC transaction marked for rollback-only (exception provided for stack trace)
................................此处为异常信息...................
2017-06-02 18:03:51.421 DEBUG 11624 --- [nio-8089-exec-1] o.h.jpa.spi.AbstractEntityManagerImpl    : Mark transaction for rollback
2017-06-02 18:03:51.421 DEBUG 11624 --- [nio-8089-exec-1] o.h.e.t.internal.TransactionImpl         : rollback() called on an inactive transaction
2017-06-02 18:03:51.422 DEBUG 11624 --- [nio-8089-exec-1] .m.m.a.ExceptionHandlerExceptionResolver : Resolving exception from handler [public void com.yginsight.adminservice.app.api.TestController.test()]: org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [collectionpoint_point_name_device_id_tenant_id_key]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
2017-06-02 18:03:51.424 DEBUG 11624 --- [nio-8089-exec-1] .w.s.m.a.ResponseStatusExceptionResolver : Resolving exception from handler [public void com.yginsight.adminservice.app.api.TestController.test()]: org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [collectionpoint_point_name_device_id_tenant_id_key]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
2017-06-02 18:03:51.424 DEBUG 11624 --- [nio-8089-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolving exception from handler [public void com.yginsight.adminservice.app.api.TestController.test()]: org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [collectionpoint_point_name_device_id_tenant_id_key]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
2017-06-02 18:03:51.424 DEBUG 11624 --- [nio-8089-exec-1] o.h.e.jdbc.internal.JdbcCoordinatorImpl  : HHH000420: Closing un-released batch
2017-06-02 18:03:51.428 DEBUG 11624 --- [nio-8089-exec-1] o.s.web.servlet.DispatcherServlet        : Could not complete request
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值