龙空技术网

Spring Data JPA自定义实现动态表名映射

llspaces 356

前言:

现时你们对“hibernate动态建表”可能比较注重,姐妹们都需要了解一些“hibernate动态建表”的相关知识。那么小编在网络上搜集了一些有关“hibernate动态建表””的相关文章,希望大家能喜欢,同学们一起来了解一下吧!

Spring Data JPA自定义实现动态表名映射

开始本文介绍之前先来看下jpa的架构,感兴趣的同学也可以自己去官网看下具体介绍:

本文目的:扩展jpa实现支持@Table("#{javaConfig.property}"方式动态表名配置

一.实现思路介绍

本文意在实现jpa中 @Table(name="tb_user") 注解name属性支持#{javaConfig.property}方式赋值的功能,达到表名可以在配置文件配置或者自定义动态设置的效果,使jpa表名配置更为灵活,实现思路如下:

1. 自定义命名策略

2. 配置自定义策略

3. JavaConfig定义

4. @Table使用配置

5. 自测

先来说明下使用版本, 采用maven管理项目,直接看下pom.xml 文件依赖版本

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.3.RELEASE</version> <relativePath/></parent><properties> <java.version>1.8</java.version></properties><!-- 其中spring-data-jpa版本2.1.5.RELEASE,hibernate对应版本5.3.7.FINAL--><dependency>	<groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId></dependency>

二、 自定义命名策略

注意: hibernate5.1之前动态表名借助实现NamingStrategy接口,

但是5.1之后该接口已废弃

本文借助继承SpringPhysicalNamingStrategy重写toPhysicalTableName方法实现,其中org.springframework.expression包下已经提供了解析#{}表达式的功能,调用即可,代码可参考如下:

import org.hibernate.boot.model.naming.Identifier;import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;import org.springframework.beans.BeansException;import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.context.expression.BeanFactoryAccessor;import org.springframework.context.expression.BeanFactoryResolver;import org.springframework.expression.Expression;import org.springframework.expression.ParserContext;import org.springframework.expression.spel.standard.SpelExpressionParser;import org.springframework.expression.spel.support.StandardEvaluationContext;import org.springframework.stereotype.Component;/** * 自定义命名策略(实现支持解析#{javaConfig.property}获取表名功能 ) * * @author llspace * @since 2019-06-27 */@Componentpublic class MySpringPhysicalNamingStrategy extends SpringPhysicalNamingStrategy implements ApplicationContextAware { private final StandardEvaluationContext context = new StandardEvaluationContext(); private final SpelExpressionParser parser = new SpelExpressionParser(); @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.context.addPropertyAccessor(new BeanFactoryAccessor()); this.context.setBeanResolver(new BeanFactoryResolver(applicationContext)); this.context.setRootObject(applicationContext); } @Override public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment jdbcEnvironment) { String nameStr = name.getText(); if(nameStr.contains(ParserContext.TEMPLATE_EXPRESSION.getExpressionPrefix())){ //参考SimpleElasticsearchPersistentEntity 实现思想,将tableName参数的值支持表达式获取 Expression expression = this.parser.parseExpression(nameStr, ParserContext.TEMPLATE_EXPRESSION); return Identifier.toIdentifier((String)expression.getValue(this.context, String.class)); }else { //默认方式不变 return super.toPhysicalTableName(name, jdbcEnvironment); } }}

三、配置自定义策略

spring: jpa: show-sql: true hibernate: naming: physical-strategy: 包名.MySpringPhysicalNamingStrategy myTableName: tb_user

四. JavaConfig定义

@Data为lombok提供的注解,简化实体类代码

@Component@Datapublic class AppConfig { @Value("${myTableName}") private String tableName; }

五.使用方式

@Data@Entity@Table(name = "#{appConfig.tableName}")public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name;}

六. 测试

本文就介绍到这了,有兴趣的同学可以自己测试下效果!

标签: #hibernate动态建表