如何解决jpa 要求column 名称单词必须用下划线

先引出轮子
http://blog.csdn.net/54powerman/article/details/76175482
偶然发现,spring Boot集成jpa编写实体类的时候,默认使用的命名策略是下划线分隔的字段命名。
Spring Boot版本:1.5.4.release
数据表:
id int,userName varchar(50)

那么如下的映射:
@Data@Entity@Table(name="t_users")@NoArgsConstructor@AllArgsConstructor@Accessors(chain=true)public class User { @Id @GeneratedValue private Integer id; private String userName;}

会发现,数据库里增加了一个字段”user_name”,那么是否可以推测spring boot jpa使用的默认策略是ImprovedNamingStrategy?
由于测试用例的表已经存在,之前使用的是DefaultNamingStrategy,即字段名和属性名相同,也是驼峰式。
好吧,我自己关联:
@Data@Entity@Table(name="t_users")@NoArgsConstructor@AllArgsConstructor@Accessors(chain=true)public class User { @Id @GeneratedValue private Integer id; @Column(name="userName") private String userName;}

有问题了,没有效果。
难道Column注解无效?尝试:
@Column(name="yong_hu_ming")private String userName;

这回有效果了,有了一个新字段 “yong_hu_ming”,column注解有效果呀。
难道是userName这个单词,我再做一个字段:
private String passWord;

重复之前的操作,依然是同样的结果。
也就是说,如果Column注解定义的字段名和属性名一样,会被忽略。奇怪的设计。
像Hibernate4一样,配置一下命名策略:
spring.jpa.hibernate.naming.strategy=org.hibernate.cfg.DefaultNamingStrategy

没有效果。
想起一件事,记得Hibernate5的命名策略有过调整,”spring.jpa.hibernate.naming.strategy” 没效果了:
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

这次有效了:
@Column(name="userName")private String userName;

数据表里可以关联到userName字段了。
当然,ImprovedNamingStrategy策略是比较好的方式,只不过,自动映射对于兼容已有的数据表,需要注意一下。如果全新设计,大可放心使用。


http://www.jianshu.com/p/ba87a9ee6001

最近再写一个Restful API的小例子,遇到这样一个问题,在Spring Boot 下使用CrudRepository,总是提示如下错误:
Caused by: java.sql.SQLSyntaxErrorException: Unknown column 'userprofil0_.real_name' in 'field list' at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:536) at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:513) at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:115) at com.mysql.cj.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:1983) at com.mysql.cj.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1826) at com.mysql.cj.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1923) at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:70) ... 76 more

而我的Bean这样写的:
@Entity@Table(name = "eb_user_profile")public class UserProfile { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "UserID") private Long UserID; @Column(name = "UserName") private String UserName; @Column(name = "RealName") private String RealName; public UserProfile() { } public UserProfile(String userName, String realName) { UserName = userName; RealName = realName; } getter... setter...}

于是spring.jpa.show-sql = true
打印SQL如下
Hibernate: select userprofil0_.userid as userid1_0_0_, userprofil0_.real_name as real_nam2_0_0_, userprofil0_.user_name as user_nam3_0_0_ from eb_user_profile userprofil0_ where userprofil0_.userid=?

啊咧咧,注解明明写好了,为何映射的SQL还是带下划线的?
最后发动老夫的望气之术,终于在茫茫网海中找到这样一段文字:
addUnderscores 用于处理 当表名和列名在Java的种规则符合 UserNameTable(表)和 userNameColumn(列),就会被解析为user_name_table 和 user_name_column ,具体return的处理的是propertyToColumnName。 but呢,如果一旦配置了这个规则,(spring +jpa配置如下:spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy)就会忽略了注释中的@Column中的name,其实这个name地方就是为了映射数据库字段,结果配置了这个就不care了。http://blog.csdn.net/dracotianlong/article/details/27834143

因为配置了org.hibernate.cfg.ImprovedNamingStrategy 策略,因此当列名符合驼峰命名法时,注解就无效了。
解决方案:
将@Column
中的值变为小写。
继承ImprovedNamingStrategy
自定义策略。


其实解决的办法很简单,
核心的问题是JPA默认的语言规则是DefaultNamingStrategy
他会在遇到第二个单词时自动加入下划线

而针对不同的业务我们在设计数据库的时候不太可能一定是尊照这种方式,

所以
第一部分在application.properties中这样配置

###JPA###
#数据库语言
hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
#使用spring-boot-starter-data-jpa 配置使运行时输出SQL语句
spring.jpa.show-sql=true
#解决Spring Boot集成JPA的Column注解命名字段会自动生成下划线的问题(命名规则)
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy
#org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
#org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy

第二部分在JPAConfig.java中这样配置

private Properties additionalProperties() {
        Properties properties = new Properties();
        properties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
//        properties.setProperty("hibernate.physical_naming_strategy", "org" +
//                ".springframework.boot.orm.jpa.hibernate" +
//                ".SpringPhysicalNamingStrategy");

        properties.setProperty("spring.jpa.hibernate.naming-strategy", env
                .getProperty("spring.jpa.hibernate.naming-strategy"));
        properties.setProperty("spring.jpa.show-sql",env
                .getProperty("spring.jpa.show-sql"));
        return properties;
    }

问题就迎刃而解。。。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,850评论 19 139
  • =========================================================...
    lavor阅读 8,861评论 0 5
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 32,497评论 18 399
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 47,122评论 6 342
  • 女儿昨天和表姐说好来我家玩一天,我起早去接,省得挨晒。女儿说也要去,我心想平时都要睡到九点多,六点多起得来吗?今早...
    勿忘我瑶阅读 1,342评论 2 2

友情链接更多精彩内容