上一篇已经将mybatis\mybatis plus\数据库源初步集成完毕,还有很多细节没有处理,这章主要就是统一数据表对应的基类,以及统一事务处理。
统一数据表对应的基类
在做项目时,我们都是要记录每条数据的创建时间,创建者,修改时间,修改者,当然这些在实际开发中都是自动完成的,不需要开发者自己去手动的写入(这块需要再次封装Dao层)。我这里统一每张表都有6个字段,分别是 ID(主键)、deleted(删除状态)、create_user_id(创建者)、create_date_time(创建时间)、create_time_millis(创建时间戳)、update_user_id(修改)、update_date_time(修改时间)、update_time_millis(修改时间戳)。
先定义一个顶级的实体接口
这个接口主要是为了将来在封装Dao层时操作中间表时使用,一般中间表我们可能是用复合主键,且不会用到上面定义的几个共用字段。(我们在新的项目中中间表也统一使用上面的8个共用字段,主键统一用单个字段ID表示)
public interface IHnEntity extends Serializable {
String YES = "Y";
String NO = "N";
}
定义一个抽象类
public abstract class AbstractHnEntity implements IHnEntity {
private static final long serialVersionUID = 1401951763317527784L;
@TableId
private String id;
@TableField("deleted")
private String deleted;
@TableField("create_user_id")
private String createUserId;
@TableField("create_date_time")
private String createDateTime;
@TableField("create_time_millis")
private String createTimeMillis;
@TableField("update_user_id")
private String updateUserId;
@TableField("update_date_time")
private String updateDateTime;
@TableField("update_time_millis")
private String updateTimeMillis;
}
修改上一章中的自动生成代码的模版文件
添加2句设定
strategy.setSuperEntityClass("com.hnexm.framework.entity.AbstractHnEntity");
strategy.setSuperEntityColumns("id", "deleted", "create_user_id", "create_date_time", "create_time_millis",
"update_user_id", "update_date_time", "update_time_millis");
角色表 (sys_role)
表的结构如下,除了8个共用字段,只有一个角色名称 name。
运行模版文件,生成相对应的代码文件,有6个文件,分别是SysRoleController.java、SysRole.java(数据表对应实体类)、SysRoleMapper.java、ISysRoleService.java、SysRoleServiceImpl.java、SysRoleMapper.xml。
修改相对应的文件,如controller文件的对应@RequestMapping 名称,Dao层上添加注解@Mapper。
统一事务处理
上一篇虽然已经可以操作数据库了,但是并没有添加事务处理,在实际项目中这样肯定是不行的,而且在实际过程中,能够修改数据库的操作,在Service层也必须用统一指定的方法名前缀,这样操作的好处除了统一各个开发者的规范,以及看到方法名就能知道操作的主要功能外,在后期的一些统一处理也会起到简化作用,例如数据库读写分离、日志的处理等(这些后期有机会再写了)。
springboot 中设置事务处理非常简单,只要写一个配置类就行了,直接上代码。
@Aspect
@Configuration
public class TransactionAdviceConfig {
private static final String AOP_POINTCUT_EXPRESSION = "execution (* com..*Service.*(..))";
@Autowired
private TransactionManager transactionManager;
@Bean
public TransactionInterceptor txAdvice() {
final DefaultTransactionAttribute requiredTx = new DefaultTransactionAttribute();
requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
// requiredTx.setTimeout(5);
final DefaultTransactionAttribute readOnlyTx = new DefaultTransactionAttribute();
readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
readOnlyTx.setReadOnly(true);
final NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
source.addTransactionalMethod("create*", requiredTx);
source.addTransactionalMethod("save*", requiredTx);
source.addTransactionalMethod("update*", requiredTx);
source.addTransactionalMethod("delete*", requiredTx);
source.addTransactionalMethod("exec*", requiredTx);
source.addTransactionalMethod("import*", requiredTx);
source.addTransactionalMethod("upload*", requiredTx);
source.addTransactionalMethod("download*", requiredTx);
source.addTransactionalMethod("enable*", requiredTx);
source.addTransactionalMethod("disable*", requiredTx);
source.addTransactionalMethod("*", readOnlyTx);
return new TransactionInterceptor(this.transactionManager, source);
}
@Bean
public Advisor txAdviceAdvisor() {
final AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression(TransactionAdviceConfig.AOP_POINTCUT_EXPRESSION);
return new DefaultPointcutAdvisor(pointcut, this.txAdvice());
}
}
这里的代码很简单,只有几处需要注意:
- 设置需要进行事务管理的所在方法,这里使用表达式来定义的:“execution (* com…Service.(…))”
- 设置需要物理操作数据库的方法的前缀名(除查询数据之外的操作)。