Hibernate 5.1.x 命名策略(向后兼容 Hibernate 4.x)
Posted
技术标签:
【中文标题】Hibernate 5.1.x 命名策略(向后兼容 Hibernate 4.x)【英文标题】:Hibernate 5.1.x naming Strategy (backward compatible with Hibernate 4.x) 【发布时间】:2016-08-31 22:54:10 【问题描述】:我正在使用 Spring Boot 1.3.3.RELEASE。默认情况下,Spring Boot 使用 Hibernate 版本 4.x。我正在尝试使用新的 Hibernate,即 5.1.0 FINAL(截至目前)。
我正在使用 Gradle 来覆盖 Hibernate 版本,我添加了以下行
ext['hibernate.version']="5.1.0.Final"
按照SpringBoot 1.3.0 support hibernate 5?的步骤进行
我使用以下命名策略
spring.jpa.properties.hibernate.naming.implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl
spring.jpa.properties.hibernate.naming.physical_strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
我有一个实体类
@Entity
public class AppUser
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotNull
@Length(max = 100)
private String username;
@NotNull
@Length(max = 100)
private String firstName;
@NotNull
@Length(max = 100)
private String lastName;
@Length(max = 100)
private String middleName;
@NotNull
@Length(max=100)
private String email;
@NotNull
@Length(max = 100)
private String password;
@NotNull
private boolean enabled;
在 Hibernate 4.x 上,它执行查询
create table app_user (
id bigint not null auto_increment,
email varchar(100) not null,
enabled bit not null,
first_name varchar(100) not null,
last_name varchar(100) not null,
middle_name varchar(100),
password varchar(100) not null,
username varchar(100) not null,
primary key (id)
)
在 5.x 上它执行了查询
create table AppUser (
id bigint not null auto_increment,
email varchar(100) not null,
enabled bit not null,
firstName varchar(100) not null,
lastName varchar(100) not null,
middleName varchar(100),
password varchar(100) not null,
username varchar(100) not null,
primary key (id)
)
如何设置命名策略,使 Hibernate 在表名和列名上使用 5.x 下划线(如 4.x)
【问题讨论】:
你确定你用ext['hibernate.version']="5.1.0.Final"
把hibernate版本改成5.1.0了吗?我认为您参考的链接中的解决方案适用于 maven,但不适用于 gradle。
是的。当 Classpath 包含 hibernate 5.1.0.Final Jars
【参考方案1】:
首先,你不需要
org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
因为它什么都不做,并且被 Hibernate 作为默认值使用。
Hibernate 5 没有您想要的策略。所有策略都符合 JPA(生成像 AppUser
这样的名称)。所以你需要自己实现。
例如物理命名策略
public class UnderscorePhysicalStartegy extends PhysicalNamingStrategyStandardImpl
@Override
public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context)
return context.getIdentifierHelper()
.toIdentifier(NamingStrategyUtils.classToName(name.getText()));
它使用NamingStrategyUtils。
请记住,如果您指定明确的名称
@Entity
@Table(name = "AppUser")
public class AppUser
无论如何你都会有一个表名app_user
。如果您不希望出现这种行为,请使用隐式命名策略。
我做了一些关于命名策略的研究工作。您可以参考Hibernate5NamingStrategy,它会根据您的需要生成带有下划线的表和列名称以及约束名称(唯一、外键)。
此类用于生成名称:HibernateNamingStrategy。
如何使用Hibernate5NamingStrategy
可以使用StrategyOptions配置命名策略。
例如,使用不带前缀的策略(如f_
):
StrategyOptions options = StrategyOptions.builder().withoutPrefixes().build();
Hibernate5NamingStrategy strategy = new Hibernate5NamingStrategy(options);
其他示例:Hibernate 5 Implicit Naming Strategy
除此之外,ImprovedNamingStrategy for Hibernate 5 可以用来模拟 Hibernate 4 ImprovedNamingStrategy
的行为。
【讨论】:
如果没有f_
前缀,有什么办法吗?默认设置太烦人了。
@Airhead 我更新了我的答案。我不知道哪个默认行为更好用。
我最终创建了自己的类,它扩展了上述类并以这种方式配置选项,以便能够从persistence.xml 中使用它,而不是不推荐使用的配置对象。
@Airhead 这很有趣。它需要将这种方式添加到文档中。【参考方案2】:
我将我的分析提供给任何人使用:
如果您在实体类中提供 @Table 和 @Column 注释,并且名称带有下划线,即 user_id 即 @Column( name="user_id"),将列名作为user_id;如果您将其作为 userid 提供,那么如果您不使用策略或隐式策略(特别是 spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl
),它将更改为 user_id。因此,如果您想要一个实体属性名称更改为带有下划线和小写字母的策略,即从 userId 到 user_id,您应该使用隐式或不使用策略(实际上使用隐式策略)。
如果您不希望您的命名策略在列名或类名中添加下划线,那么您需要使用的策略类似于:spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
。您在注释 @Table 和 @Column 的 名称属性中提供的内容将保持原样。
如果您不想提供注释并希望手动处理表名和列名,则应扩展类 org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl 并覆盖所需的方法。如果您仍然在此处的某些情况下使用注释,请记住覆盖的方法将应用于这些注释中编写的名称。 spring.jpa.hibernate.naming.physical-strategy=example.CustomStrategy
【讨论】:
以上是关于Hibernate 5.1.x 命名策略(向后兼容 Hibernate 4.x)的主要内容,如果未能解决你的问题,请参考以下文章