(1)、spring.jpa.hibernate.ddl-auto 配置
该配置的主要作用是:自动创建、更新、验证数据库表结构,该参数的几种配置如下:
- create: 每次加载 hibernate 时都会删除上一次生成的表,然后根据 modle 类再重新生成新表,哪怕两次没有任何改变也要这样执行。这也是导致数据库表数据丢失的一个重要原因。
- create-drop :每次加载 hibernate 时根据 modle 类生成表,但是SessionFactory 一关闭,表就会自动删除。
- update :最常用的属性,第一次加载hibernate 时,根据modle 类会自动建立表的架构(前提是先建立好数据库),以后加载hibernate 时根据 modle 类自动更新表结构,即使表结构改变了,但表中的行仍然存在,不会删除以前的行。要注意的是:当部署到服务器后,表结构不会马上建立起来。要等应用第一次运行起来才会。
- validate:每次加载hibernate 时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。
Mode | Reads**import.sql** | Alters Database**Structure** | Comments |
update | No | Yes | |
create | Yes | Yes | Empties the database before creating it |
create-drop | Yes | Yes | Drops the database when the SessionFactory is closed |
validate | No | No |
(2)、spring.jpa.properties.hibernate.dialect 配置
hibernate.dialect 属性的属性值为 Hibernate 所支持的 SQL 方言,如下表:
数据库 | Hibernate方言类 |
DB2 | org.hibernate.dialect.DB2Dialect |
DB2 AS/400 | org.hibernate.dialect.DB2400Dialect |
DB2 OS390 | org.hibernate.dialect.DB2390Dialect |
PostgreSQL | org.hibernate.dialect.PostgreSQLDialect |
MySQL | org.hibernate.dialect.MySQLDialect |
MySQL with InnoDB | org.hibernate.dialect.MySQLInnoDBDialect |
MySQL with MyISAM | org.hibernate.dialect.MySQLMyISAMDialect |
Oracle(any version) | org.hibernate.dialect.OracleDialect |
Oracle 9i/10g | org.hibernate.dialect.Oracle9Dialect |
Sybase | org.hibernate.dialect.SybaseDialect |
Sybase Anywhere | org.hibernate.dialect.SybaseAnywhereDialect |
Microsoft SQL Server | org.hibernate.dialect.SQLServerDialect |
SAP DB | org.hibernate.dialect.SAPDBDialect |
Informix | org.hibernate.dialect.InformixDialect |
HypersonicSQL | org.hibernate.dialect.HSQLDialect |
Ingres | org.hibernate.dialect.IngresDialect |
Progress | org.hibernate.dialect.ProgressDialect |
Mckoi SQL | org.hibernate.dialect.MckoiDialect |
Interbase | org.hibernate.dialect.InterbaseDialect |
Pointbase | org.hibernate.dialect.PointbaseDialect |
FrontBase | org.hibernate.dialect.FrontbaseDialect |
Firebird | org.hibernate.dialect.FirebirdDialect |
2、命名策略配置
其中Naming是一个内部类,Hibernate字段映射策略就是在这里配置的。
根据上面的代码可知,Naming采用下面两个属性:
spring.jpa.hibernate.naming.implicit-strategy= # Hibernate 5 implicit naming strategy fully qualified name.
spring.jpa.hibernate.naming.physical-strategy= # Hibernate 5 physical naming strategy fully qualified name.
现在分别介绍这两个属性分别怎么使用
(1)、physical-strategy的使用:
spring.jpa.hibernate.naming.physical-strategy 它有两个值分别可以配置:
org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
效果分别如下:
org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl效果等同于:
hibernate4中的DefaultNamingStrategy这个直接映射,不会做过多的处理(前提没有设置@Table,@Column等属性的时候)。如果有@Column则以@Column为准【对于关联关系的依旧会命名为user_id这种样子,看下图】
org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy效果等同于:
hibernate4中的ImprovedNamingStrategy 表名,字段为小写,当有大写字母的时候会转换为分隔符号“_”。
(2)、implicit-strategy的使用:
spring.jpa.hibernate.naming.implicit-strategy 它有如下的值可以配置:
org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImp
org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl
org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl
下表说明各个策略的差异:
strategy | primaryTable | joinTable | collectTable |
ImplicitNamingStrategyJpaCompliantImpl | Entity类名 | Entity物理名称 + 引用Entity的物理名称 | Entity类名 + 属性名称 |
ImplicitNamingStrategyLegacyHbmImpl | - | Entity物理名称 + 属性名称 | - |
ImplicitNamingStrategyLegacyJpaImpl | - | - | Entity物理名称 + 属性名称 |
SpringImplicitNamingStrategy | - | Entity的物理名称 + 属性名称 | - |
(3)、自定义命名策略的使用:
A、首先,介绍下命名策略的步骤:
第一步:如果我们没有使用@Table或@Column指定了表或字段的名称,则由SpringImplicitNamingStrategy为我们隐式处理,表名隐式处理为类名,列名隐式处理为字段名。如果指定了表名列名,SpringImplicitNamingStrategy不起作用。
第二步:将上面处理过的逻辑名称解析成物理名称。无论在实体中是否显示指定表名列名,SpringPhysicalNamingStrategy都会被调用。
所以如果我们想要自定义命名策略,可以根据自己的需求选择继承二者,并在配置文件中通过spring.jpa.hibernate.naming.implicit-strategy 或 spring.jpa.hibernate.naming.physical-strategy 进行指定自己的策略(例如为表名添加指定前缀)。
B、其次自定义命名策略,通过继承PhysicalNamingStrategyStandardImpl 或实现PhysicalNamingStrategy 接口:
package com.yozheng.springboot.demo.common; import org.hibernate.boot.model.naming.Identifier; import org.hibernate.boot.model.naming.PhysicalNamingStrategy; import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; /** * 自定义数据库映射名称策略 */ @Component public class DataBaseNamingStrategy implements PhysicalNamingStrategy { @Value("${database.prefix}") private String prefix; //读取application.properties配置的前缀 protected String addUnderscores(String name) { if (name == null) { return null; } StringBuffer stringBuffer = new StringBuffer(name.replace('.', '_')); for (int i = 1; i < stringBuffer.length() - 1; i++) { if (Character.isLowerCase(stringBuffer.charAt(i-1)) && Character.isUpperCase(stringBuffer.charAt(i)) && Character.isLowerCase(stringBuffer.charAt(i+1))) { stringBuffer.insert(i++, '_'); } } return stringBuffer.toString().toLowerCase(); } @Override public Identifier toPhysicalCatalogName(Identifier identifier, JdbcEnvironment jdbcEnvironment) { return identifier; } @Override public Identifier toPhysicalSchemaName(Identifier identifier, JdbcEnvironment jdbcEnvironment) { return identifier; } @Override public Identifier toPhysicalTableName(Identifier identifier, JdbcEnvironment jdbcEnvironment) { return Identifier.toIdentifier(prefix + addUnderscores(identifier.getText())); } @Override public Identifier toPhysicalSequenceName(Identifier identifier, JdbcEnvironment jdbcEnvironment) { return identifier; } @Override public Identifier toPhysicalColumnName(Identifier identifier, JdbcEnvironment jdbcEnvironment) { return Identifier.toIdentifier(addUnderscores(identifier.getText())); } }
只需要实现上面:toPhysicalTableName(这个是映射表名), toPhysicalColumnName(映射字段名称)
c、 在application.properties文件配置信息
#配置自定义命名策略
spring.jpa.hibernate.naming.physical-strategy=com.example.demo.DataBaseNamingStrategy
#数据库表名前缀
database.prefix=tb_
运行测试效果: