摘要:Spring事务管理基于底层数据库本身的事务处理机制,对数据库事务操作的一次封装,相当于把使用JDBC代码开启、提交、回滚事务进行了封装。其传播特性共有七个
因为业务的需要,业务逻辑优先在单个Service中实现,同样为了保证数据的一致性需要使用事务,在单个Service中实现会出现嵌套事务。
如我们使用service C同时调用service A和service B ,如果service B抛出异常那么service C(外部事务)如果没有特殊配置(如异常时事务提交)那么整个事务是一定会rollback的。
测试代码: Service C: 如下代码所示,使用声明式注解@Transactional(rollbackFor=Exception.class)默认传播特性是Propagation.REQUIRED。
@Transactional(rollbackFor=Exception.class,propagation=Propagation.REQUIRED)@Overridepublic int insert(Users users) throws Exception{ int i = users1Service.insert(users); int j = users2Service.insert1(users); return i+j;} |
---|
Controller层:
@RequestMapping(value = "/", method = RequestMethod.POST)public ResponseInfo postUser1(@RequestBody Users user) throws Exception { ResponseInfo resInfo = new ResponseInfo(); int i = usersService.insert(user); resInfo.setResponseInfo("users一共新增了" + i + "条数据"); return resInfo;} |
---|
Service A:
@Transactional(rollbackFor=Exception.class,propagation=Propagation.REQUIRES_NEW)@Overridepublic int insert(Users users) throws Exception{ return usersMapper.insert(users);} |
---|
Service B:
@Transactional(rollbackFor=Exception.class,propagation=Propagation.REQUIRED)@Overridepublic int insert1(Users users) throws Exception{ return usersMapper.insert1(users);} |
---|
根据以上代码可以通过测试两张表同时插入而一张表失败最后返回的数据进行分析: 本次使用Postman测试工具,数据库oracle 11g。 两张表其中一张age字段为number6位,一张为number2位,测试数据为三位,会有一张表插入失败,测试数据如下图所示。
结果是两张表都没有插入,如下图所示。
经过测试,说明嵌套事务与事务的传播特性有关,都使用默认的传播属性REQUIRED第一张插入后,第二张失败会导致外部事务(Service C)rollback,保证了数据的一致性。 若内部事务有使用REQUIRES_NEW属性,则会单独开一事务其运行结果不会影响外部数据会出现数据不一致。 若内部事务有使用NESTED属性,内部事务如果出现异常则会rollback到save point,从而外部事务可以使用try-catch进行分支执行(try里执行Service A,catch里执行Service B)。 查询语句应该设置为read-only,传播范围设置为NOT_SUPPORTED 如下代码所示:
/** * {@inheritDoc} * {@link newframe.business.demo.service.SecurityInfoService#queryAll()} * */ @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true) @Override public List<SecurityInfo> queryAll() throws MessageException { List<SecurityInfo> list = securityInfoMapper.queryAll(); return list; } |
---|
具体使用哪个属性根据业务来进行选择。
在项目中如果大量组件采用xml的bean定义来配置,显然会增加配置文件的体积,查找不太方便。而注解可以很方便的标注完将其放入spring容器管理。
业务层注解 @Service:用于标注业务层组件。 @Controller:用于标注控制层组件。 @Repository:用于标注数据访问组件,即Dao组件。 @Component:泛指组件,不容易归类可以使用该组件。
Bean容器相关的注解 @Autowired:等同autowire=byType,根据类型的自动注入依赖。 @Qualifier:等同autowire=byName,当@Autowired注解需要判断多个 bean类型相同时,就需要使用@Qualifier(“xxBean”)来指定依赖的bean 的id。 @Resource:属于JSR250标准,作用同@Autowired,是属于byName类 型的依赖注入,使用方式:@Resource(name=”xxBean”),不带参数是默 认类名首字母小写。
@RequestBody:用于读取request请求的body部分数据(Json串或XML数据),将其转化为需要的对象。 @ResponseBody:将Controller的方法返回的对象通过适当的转换(通过配置可以返回Json或XML数据),写入response对象的body数据区。新框架可以在Controller里使用该注解返回Json数据。