当JPA遇上MySQL表名全大写+全小写+驼峰+匈牙利四风格

我一直知道的MySQL在Linux上有字段名表名等的大小写问题,于是为了避免这个问题,选择了下划线和全小写,心说虽然咱用的是JPA,只要使用注解写清楚表名和字段名是大写的,不也没事么。例如这样

实际上证明,想象比搬砖生活丰富的多。亲们,我用JPA实现查表操作的时候,Exception跳出来说表不存在,因为表名是全小写的,我还能怎样┑( ̄Д  ̄)┍。接下来,折腾才刚刚开始……不妨看下日志,内心异常的沉重

2019-09-24 17:31:16.407 ERROR 25864 --- [  XNIO-2 task-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : (conn=348) Table ‘4a.t_assets_mgr‘ doesn‘t exist
2019-09-24 17:31:16.420 ERROR 25864 --- [  XNIO-2 task-1] c.s.xxxx.aop.logging.LoggingAspect       : Exception in com.xxx.yyyy.service.StaticQuadraa.initLevel() with cause = ‘org.hibernate.exception.SQLGrammarException: could not extract ResultSet‘ and exception = ‘could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet‘

org.springframework.dao.InvalidDataAcce***esourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:242)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:225)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:527)
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:153)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:135)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
    at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
    at com.sun.proxy.$Proxy195.getAllByBusinessName(Unknown Source)

通常情况下解决这个问题,如果你的数据库是搭建在windows上面,而且你还是自己写玩的,第一步肯定是改MySQL的cnf,改成不区分大小写,这样总是可以的?不过现在都是在docker环境下,这操作,不行了啊,再装个Oracle又麻烦,怎么办呢?既然MySQL那边解决起来麻烦,我们在Java这想想办法吧。简单的分析一下过程,浏览器点按钮,发起请求到后台,Controller接到请求后通过service找到对应的DTO,DTO又通过Spring Data找到Hibernate从而实现的JPA规范,再转化成SQL语句发送给数据库执行。因此只要能在发送前把表名改成大写就能解决问题了。
那么这个把表名改成大写或者小写,是在哪里执行的呢?还记得,JPA对字段有一个转换,比如a_b会转换成aB。这个当然不是Java内核实现的,这个是Hibernate的JPA实现做的。具体到代码,这个东西在spring中是org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy ,是默认使用的。Hibernate实现的这个,就是转换驼峰规则的功能。我注解里表名写的是大写,但是输出的sql语句里是小写,毫无疑问,这里有转换成小写的代码。目前,spring data jpa基于Hibernate5,而Hibernate5关于数据库命名策略的配置与之前版本略有不同,其采用implicit-strategy和physical-strategy两个配置项分别控制命名策略

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

这两个策略还是有点小小的区别的:

  • implicit-strategy负责模型对象层次的处理,将对象模型处理为逻辑名称
  • physical-strategy负责映射成真实的数据名称的处理,将上述的逻辑名称处理为物理名称。
  • 当没有使用@Table和@Column注解时,implicit-strategy配置项才会被使用,当对象模型中已经指定时,implicit-strategy并不会起作用。
  • physical-strategy一定会被应用,与对象模型中是否显式地指定列名或者已经被隐式决定无关。

这里提供两种解决方法:

  1. 可以在 springboot 项目中配置文件内加上配置行,设置命名为 无修改命名策略:

    spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
  2. 重写命名策略中改表名为小写的方法:
    @Component
    public class MySQLUpperCaseStrategy extends PhysicalNamingStrategyStandardImpl {
    private static final long serialVersionUID = 1383021413247872469L;
    
    @Override
    public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) {
        // 将表名全部转换成大写
        String tableName = name.getText().toUpperCase();
    
        return name.toIdentifier(name.getText());
    }
    }

    之后在我们需要在相关的.yml文件中使用自己实现的策略

    spring.jpa.hibernate.naming:physical-strategy: xx.xx.xx.config.Strategy.MySQLUpperCaseStrategy

    这里我用了方法2,因为在后续的开发中,我们的开发前辈,对这个数据库下毒,一共用了驼峰、匈牙利、下划线,全小写四种命名风格,简直前无古人后无来者,念天地之悠悠,愿其早日作古而烁今,开局蓝buff必被抢,顺风必翻盘,斗地主3456少个7,高铁吃泡面少叉子,股票逢买必跌。
    在这里我用了方法2,可以比较自由的对表名进行映射修改,而不依赖于他们的命名风格,以致,向先人敬礼!!

原文地址:https://blog.51cto.com/yerikyu/2440787

时间: 2024-10-19 06:33:10

当JPA遇上MySQL表名全大写+全小写+驼峰+匈牙利四风格的相关文章

解决windows 下mysql 表名自动转成小写的问题

由于web用的是mvc,数据库用的是mysql.为了方便开发,在windows7下面也安装了个mysql,今天在创建表的时候,遇到了个棘手的问题.所有的表名都转成了小写,这不是我要的,作为处女座,是不能容忍这样的事情存在的.经过一番折腾后,终于解决了,方法如下. 第一步:先在navicat的tools里面选择console,然后输入: show variables like 'lower_case_table_names';注意分号 如果输出的lower_case_table_names的val

linux系统下MySQL表名区分大小写问题

问题如下: 比如上图中的PERSON表,查询SQL语句中如果表名是小写,就会报错说person表不存在. 因为Linux环境下的MySQL数据库的表名默认是区分大小写的,可以查看Linux上的MySQL的配置文件/etc/my.cnf: [[email protected]_219_131_centos tomcat7]# cat /etc/my.cnf [mysqld] datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock user=m

mysql表名等大小写敏感问题、字段类型timestamp、批量修改表名、oracle查询历史操作记录等

mysql表名等大小写敏感问题:http://blog.csdn.net/postnull/article/details/72455768: 1 MySQL在Linux下数据库名.表名.列名.别名大小写规则是这样的: 2 1.数据库名与表名是严格区分大小写的: 3 2.表的别名是严格区分大小写的: 4 3.列名与列的别名在所有的情况下均是忽略大小写的: 5 4.字段内容默认情况下是大小写不敏感的. ================================================

Linux下 设置Mysql表名不区分大小写

情景:公司近期在将数据库从Oracle转为Mysql,由于之前在Oracle中表名是不区分大小写,因此到Mysql中就出现了找不到表的问题,经上网查询,发现在linux下Mysql的表名是区分大小写的,但是有参数可以使其不区分大小写.具体操作如下: 一.linux中mysql大小写详情: 1.数据库名严格区分大小写 2.表名严格区分大小写的 3.表的别名严格区分大小写 4.变量名严格区分大小写 5.列名在所有的情况下均忽略大小写 6.列的别名在所有的情况下均忽略大小写 二.设置Mysql表名不区

linux下mysql表名大小写问题

近日,新mysql实例导入sql数据时,发现比老的mysql多了100+张表,最终发现是mysql表名大小写所致:很简单的问题却耽误很长时间,在此记录一下,以防再犯同样的错误: 1.Linux下mysql安装完后是默认:区分表名的大小写,不区分列名的大小写:2.用root帐号登录后,在/etc/my.cnf中的[mysqld]后添加添加lower_case_table_names=1,重启MYSQL服务,这时已设置成功:不区分表名的大小写:lower_case_table_names参数详解:l

设置Linux下Mysql表名不区分大小写

1.Linux下mysql安装完后是默认:区分表名的大小写,不区分列名的大小写:2.用root帐号登录后,在/etc/my.cnf中的[mysqld]后添加添加lower_case_table_names=1,重启MYSQL服务,这时已设置成功:不区分表名的大小写:lower_case_table_names参数详解:lower_case_table_names=0其中0:区分大小写,1:不区分大小写 MySQL在Linux下数据库名.表名.列名.别名大小写规则是这样的:1.数据库名与表名是严格

MySQL表名和数据库关键字相同解决办法

今天改他们的代码的时候,遇到了MySQL表名和数据库关键字的问题. 由于表名是关键字,导致增删改查都报错. Hibernate: select leave0_.id as id22_, leave0_.stuNumber as stuNumber22_, leave0_.stuName as stuName22_, leave0_.academy as academy22_, leave0_.classes as classes22_, leave0_.leaveDays as leaveDay

php大力力 [021节]mysql表名在mac下不能大写

2015-08-27 php大力力021.mysql表名在mac下不能大写 刚才数据库里面,phpMyAdmin狂出错. Some errors have been detected on the server! Please look at the bottom of this window. Notice in ./libraries/structure.lib.php#1868 Undefined index: Rows Backtrace ./libraries/structure.li

mysql表名区分大小写问题

mysql表名区分大小写问题 查看mysql数据库大小写敏感参数 1.1. show variables like 'lower%';'' 参数说明 lower_case_table_names: 此参数不可以动态修改,必须重启数据库 lower_case_table_names = 1 表名存储在磁盘是小写的,但是比较的时候是不区分大小写 lower_case_table_names = 0 表名存储为给定的大小和比较是区分大小写的 1.2 . 特别注意 需要注意的是,当 lower_case