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

Spring Data JPA 自定义实现动态表名映射,支持@Table("#{javaConfig.property}"配置

  • 实现思路介绍
  • 使用版本说明
  • 自定义命名策略
  • 配置自定义策略
  • JavaConfig定义
  • 使用方式
  • 测试

实现思路介绍

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

  1. 自定义命名策略
  2. 配置自定义策略
  3. JavaConfig定义
  4. @Table使用配置

使用版本说明

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


   org.springframework.boot
   spring-boot-starter-parent
   2.1.3.RELEASE
   



    1.8



	org.springframework.boot
    spring-boot-starter-data-jpa


    org.springframework.boot
    spring-boot-starter-web

自定义命名策略

注意: 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  Java猿人一枚
 * @since 2019-03-26
 */
@Component
public 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
@Data
public 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;

}

测试

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

你可能感兴趣的:(spring,data,jpa)