背景
最近用sqlite数据库开发本地应用,后端使用的springboot + jpa。现在遇到sqlite对单条sql中select union 最大限制为500,而jpa底层把所有表中的列作为 一个select union 查询并且超过了数据库的最大限制,为了方便以后的开发,运维,所以需要实现jpa自动创建表的功能,减少开发和运维的工作量。
实现逻辑
创建一个类,实现 BeanPostProcessor
为什么要实现BeanPostProcessor呢,因为spring在创建bean的时候,先创建的BFPP,再创建BPP,然后创建内部Bean,最后再创建工程中使用的Bean,使用BPP就是为了防止有冲突出现。
@Component
@Slf4j
@Order(Integer.MIN_VALUE)
public class ComplementBeanPostProcessor implements BeanPostProcessor {
在jpa的实体类上实现自定义接口
JpaEntryDefinition接口为一个空定义接口,只是为了标识JPA的实体,源码能力强的可以通过@Entity加@Table注解获取对应的实体类
@Data
@Entity
@Table(name = "table_name")
public class TableName implements JpaEntryDefinition{
}
创建@PostConstruct中的方法
@PostConstruct在ComplementBeanPostProcessor初始化的时候会被调用
@PostConstruct
public void init(){
// 初始化数据库表
verifyAndComplementTable();
}
增加列或者创建表
java类型与数据库类型关系映射
public static final Map<String,String> classTypeMappingColumnType = Maps.newHashMap();
static{
classTypeMappingColumnType.put("int","integer");
classTypeMappingColumnType.put("java.lang.Integer","integer");
classTypeMappingColumnType.put("java.lang.String","varchar(255)");
classTypeMappingColumnType.put("long","Long");
classTypeMappingColumnType.put("java.lang.Long","Long");
}
private void verifyAndComplementTable() {
log.info("start----------------->校验并完善数据库表结构");
Set<Class<?>> tableList = ReflectUtils.getChildreClass(JpaEntryDefinition.class);
validJpaEntryDefinition(tableList);
//获取数据库中所有的表
List<String> existTableNme = jdbcTemplate.queryForList("select name from sqlite_master where type='table' order by name ",String.class);
Map<String, String> existTableNmeMap = existTableNme.stream().collect(Collectors.toMap(Function.identity(), Function.identity()));
for(Class clazz : tableList){
Table tableAnno = (Table)clazz.getAnnotation(

最低0.47元/天 解锁文章
923

被折叠的 条评论
为什么被折叠?



