资讯专栏INFORMATION COLUMN

Hibernate 自定义表名映射

weij / 784人阅读

摘要:所以设计的表名映射格式为,如果不加注解,则将实体名按照默认的生成规则进行生成,如果加了注解,则填写的就作为表名映射,不进行任何处理。云智命名策略实体与数据表名的关系配置然后将该项配置修改为我们自己建立的实现类。

问题描述 Hibernate映射介绍

Hibernate中,默认的生成关系是将我们驼峰命名的实体进行拼接下划线同时转小写。

这种情况我们可以接受,默认的设置很规范。

但是这样,我们在实体之上声明了@Table注解,并说我们的表名是Mandatory_Instrument_Apply,但是Hibernate还是将我们的数据表映射为小写加下划线的形式。这种情况看起来就有些不合理了。

业务需求

因为需要兼容老项目,老项目的数据表命名不很很规范,所以需要用最小的成本实现数据库的兼容。

所以设计的表名映射格式为,如果不加@Table注解,则将实体名按照Hibernate默认的生成规则进行生成,如果加了@Table注解,则填写的name就作为表名映射,不进行任何处理。

功能实现 入门

抛出来一个问题,无从下手。

打开浏览器,看看有没有前人的经验,GoogleGoogle去发现找不着啥有价值的信息。但是在StackOverflow上找到一篇引人思索的问题。

Spring boot JPA insert in TABLE with uppercase name with Hibernate - StackOverflow

spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

将这个配置声明为org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl,就能实现大写的转换。

试试再说:

将配置按该问题的回答进行修改:

测试一番:

加了@Table注解的,是我们想要的配置,直接映射。那不加注解的呢?

这个又不是我们想要的了,这个注解应该是直接将注解中的名或实体名映射到数据表,不做任何修改。

发现新大陆

正当一筹莫展之时,再去看一下配置,有了新的领悟。

org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl,这个配置的不就是一个实现类吗?我是不是也可以写一个类然后将我写的类配置上呢?

点进去,发现不过是一个实现了PhysicalNamingStrategySerializable两个接口的类。

看实现的toPhysicalTableName方法,应该就是生成数据表名的方法。直接将name返回,这就和我们之前猜想的一致,这个配置是直接将@Table或实体名映射到数据表。

YunzhiNamingStrategy

建立配置类YunzhiNamingStrategy.java,云智命名策略,分别实现上述PhysicalNamingStrategyStandardImpl实现的两个接口。同时实现接口中声明的方法。

package com.mengyunzhi.demo.config;

import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;

import java.io.Serializable;

/**
 * @author zhangxishuo on 2018/6/15
 * 云智命名策略
 * 实体与数据表名的关系配置
 */
public class YunzhiNamingStrategy implements PhysicalNamingStrategy, Serializable {
    @Override
    public Identifier toPhysicalCatalogName(Identifier identifier, JdbcEnvironment jdbcEnvironment) {
        return null;
    }

    @Override
    public Identifier toPhysicalSchemaName(Identifier identifier, JdbcEnvironment jdbcEnvironment) {
        return null;
    }

    @Override
    public Identifier toPhysicalTableName(Identifier identifier, JdbcEnvironment jdbcEnvironment) {
        return null;
    }

    @Override
    public Identifier toPhysicalSequenceName(Identifier identifier, JdbcEnvironment jdbcEnvironment) {
        return null;
    }

    @Override
    public Identifier toPhysicalColumnName(Identifier identifier, JdbcEnvironment jdbcEnvironment) {
        return null;
    }
}

然后将该项配置修改为我们自己建立的实现类。

兼容原配置项

因为该接口中有多个配置项,如:数据库名、字段名等,我们只想修改实体到数据表的命名策略,所以我们找到了另一个实现PhysicalNamingStrategy命名策略的实现类:SpringPhysicalNamingStrategy

这就是我们第一次演示的策略,无论添不添加@Table注解,都会映射到小写的加下划线的表名。

同时这里的字段映射为小写下划线我们是需要保留的,为了代码的复用,我们用到了面向对象的继承大法。

package com.mengyunzhi.demo.config;

import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy;

/**
 * @author zhangxishuo on 2018/6/15
 * 云智命名策略
 * 实体与数据表名的关系配置
 */
public class YunzhiNamingStrategy extends SpringPhysicalNamingStrategy {
    
}

我们对父类中的toPhysicalTableName方法不满意,Command + N,重写父类方法。

package com.mengyunzhi.demo.config;

import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy;

/**
 * @author zhangxishuo on 2018/6/15
 * 云智命名策略
 * 实体与数据表名的关系配置
 */
public class YunzhiNamingStrategy extends SpringPhysicalNamingStrategy {
    @Override
    public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment jdbcEnvironment) {
        return super.toPhysicalTableName(name, jdbcEnvironment);
    }
}
注解判断

我们可以开始我们的逻辑了。

@Table注解的,就按@Table中的名称中,否则就按Spring默认的父类走。

但是问题出现了,Identifier中给我们的名称就是已经处理好的名称。

Identifier

假如这么写:

@Entity
public class MandatoryInstrumentApply {
}

那我们的Identifier中的text值就是MandatoryInstrumentApply

@Entity
@Table(name = "Mandatory_Instrument_Apply")
public class MandatoryInstrumentApply {
}

那我们的Identifier中的text值就是Mandatory_Instrument_Apply

Hibernate是把应该处理好的名称告诉我们,但是不会告诉我们这个名称是实体的名还是在注解上获取的。

解决方案

package com.mengyunzhi.demo.config;

import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy;

import javax.persistence.Table;

/**
 * @author zhangxishuo on 2018/6/15
 * 云智命名策略
 * 实体与数据表名的关系配置
 */
public class YunzhiNamingStrategy extends SpringPhysicalNamingStrategy {

    // 定义包名
    private static final String packageName = "com.mengyunzhi.demo.entity.";

    /**
     * 重写父类生成表名的方法
     */
    @Override
    public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment jdbcEnvironment) {
        try {
            // 获取实体类
            Class entityClass = Class.forName(packageName + name.getText());
            // 判断类上是否有Table注解
            Boolean hasAnnotation = entityClass.isAnnotationPresent(Table.class);
            // 存在Table注解
            if (hasAnnotation) {
                // 获取Table注解实例
                Table table = (Table) entityClass.getAnnotation(Table.class);
                // 如果注解中的name字段不为空
                if (!table.name().equals("")) {
                    // 不对名称进行处理
                    return name;
                }
            }
            // 表示这是一个类名,按父类操作进行处理
            return super.toPhysicalTableName(name, jdbcEnvironment);
        } catch (ClassNotFoundException e) {
            // 找不到实体类,说明肯定是@Table注解中的名称
            return name;
        }
    }
}
测试

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/71208.html

相关文章

  • 【从零入门系列-2】Spring Boot 之 数据库实体定义实现

    摘要:文章系列从零入门系列之从零入门系列之程序结构设计说明前言本篇文章开始代码实践,系统设计从底向上展开,因此本篇先介绍如何实现数据库表实体类的设计实现。主键由数据库自动生成主要是自动增长型主键由程序控制。 文章系列 【从零入门系列-0】Sprint Boot 之 Hello World 【从零入门系列-1】Sprint Boot 之 程序结构设计说明 前言 本篇文章开始代码实践,系统...

    nemo 评论0 收藏0
  • Hibernate配置及定义注册映射文件

    摘要:一配置属性详解可以在各式各样不同环境下工作而设计的因此存在着大量的配置参数。以简便操作,多数配置参数都有默认的配置值也是我们日常使用的必须品。 Hibernate (开放源代码的对象关系映射框架) Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装, 它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernat...

    coordinate35 评论0 收藏0
  • Hibernate 注解使用

    摘要:声明添加对乐观锁定的支持一些属性关联关系获取方式即是否采用延时加载及时加载,是在查询数据时,也直接一起获取关联对象的数据。在前面的基础上增加课程类并补充学生类学生类负责关联关系 Hibernate 注解使用 在Hibernate中通常配置对象关系映射关系有两种,一种是基于xml的方式,另一种是基于Hibernate Annotation库的注解方式。在Hibernate 3.2版本和J...

    Jinkey 评论0 收藏0
  • Hibernate映射关系

    摘要:前言首先声明,这是一篇转发博客,不属于原创。关系映射有下面几种类型一对一外键关联映射单向一对一外键关联,使用,并设置了级联操作。设置了外键的名称为数据库字段名,如果不设置,则默认为另一类的属性名,外键的值是唯一的。 前言 首先声明,这是一篇转发博客,不属于原创。但是感觉很有用,所以在本人的博客中记录下来。 Hibernate Annotation关系映射有下面几种类型: 一对一...

    gougoujiang 评论0 收藏0
  • 几个数据持久化框架Hibernate、JPA、Mybatis、JOOQ和JDBC Template的

    摘要:不管是还是,表之间的连接查询,被映射为实体类之间的关联关系,这样,如果两个实体类之间没有实现关联关系,你就不能把两个实体或者表起来查询。 因为项目需要选择数据持久化框架,看了一下主要几个流行的和不流行的框架,对于复杂业务系统,最终的结论是,JOOQ是总体上最好的,可惜不是完全免费,最终选择JDBC Template。 Hibernate和Mybatis是使用最多的两个主流框架,而JOO...

    xietao3 评论0 收藏0

发表评论

0条评论

weij

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<