文章目录
- 系列文章目录
- JPA配置
- Bootstrap Mode
- 命名策略
- 数据库初始化
- 使用JPA初始化数据库
- 使用Hibernate初始化数据库
- 使用SQL脚本初始化
- 使用Spring Batch初始化数据库
- 数据库初始化依赖
- 检测数据库初始化器
- 检测依赖于数据库初始化的Bean
JPA配置
Spring Data JPA已经提供了一些独立于供应商的配置选项(例如SQL日志),Spring Boot将这些选项以及一些针对Hibernate
的选项作为外部配置属性公开。其中一些是根据上下文自动检测的,因此你不应该设置它们。
属性 | 描述 | 备注 |
| 要操作的目标数据库,默认自动检测 | 可选配置 |
| 要操作的目标数据库的名称,默认情况下是自动检测的 | 可以使用" |
|
| 默认 |
| 启动时是否初始化数据库 | 默认 |
| 是否启用SQL语句日志记录 | 默认 |
| 资源映射(等价于 | |
|
| 默认 |
| 要在JPA提供程序上设置的其他本地属性 | 例如: |
| 是否启用 | 默认 |
|
| 三种模式: |
| DDL模式 |
|
| 全限定名的隐式命名策略 | 例如:org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy |
| 物理命名策略的完全限定名 | |
| 是否使用Hibernate更新的 | 默认 |
Bootstrap Mode
默认情况下,Spring Data JPA Repository是默认的Spring bean。它们是单例作用域,并且是提前初始化的。在启动期间,它们已经与JPA EntityManager
交互,以进行验证和元数据分析。Spring框架支持在后台线程中初始化JPA EntityManagerFactory
,因为在Spring应用程序中,这个过程通常会占用大量的启动时间。为了有效地利用后台初始化,我们需要确保JPA Repository的初始化时间越晚越好。
在Spring Data JPA 中,可以使用spring.data.jpa.repositories.bootstrap-mode
配置BootstrapMode
:
DEFAULT
(默认) — 默认模式,除非显示的使用@Lazy
注解延迟加载,否则Repository在容器启动过程中初始化。LAZY
— 懒加载模式,启动过程中JPA Respository组件bean并没有真正被初始化。这些JPA Respository组件bean仅在首次调用前才会被初始化,以及进行相应的验证和元数据分析。DEFERRED
—延迟加载模式,本质上和LAZY
操作模式相同,但是触发一个ContextRefreshedEvent
事件来通知Respository
初始化,这样Respository
在应用程序完全启动之前就被验证了。
模式选择建议:
1.如果你不使用异步JPA引导,则坚持使用默认引导模式。
2.如果你想异步引导JPA,DEFERRED
是一个合理的默认值,因为它将确保Spring Data
JPA引导只等待EntityManagerFactory
设置,如果EntityManagerFactory
设置本身需要比初始化所有其他应用程序组件更长的时间。尽管如此,它确保存储库在应用程序发出启动信号之前得到了正确的初始化和验证。
3.对于测试场景和本地开发,LAZY
是一个不错的选择。
命名策略
Hibernate使用两种不同的命名策略将对象模型中的名称映射到相应的数据库名称。物理策略
和隐式策略
实现的完全限定类名,可以通过分别设置spring.jpa.hibernate.naming.physical-strategy
和spring.jpa.hibernate.naming.implicit-strategy
属性来配置。如果ImplicitNamingStrategy
或PhysicalNamingStrategy
bean在应用程序上下文中可用,Hibernate将自动配置使用它们。
默认情况下,Spring Boot使用CamelCaseToUnderscoresNamingStrategy
配置物理命名策略。使用这种策略,所有的点都被下划线取代
,驼峰大小写也被下划线取代
。另外,默认情况下,所有表名都是小写的。例如,TelephoneNumber
实体被映射到telephone_number
表。如果你的模式需要混合大小写标识符,定义一个自定义CamelCaseToUnderscoresNamingStrategy
bean,如下面的示例所示:
@Configuration(proxyBeanMethods = false)
public class MyHibernateConfiguration {
@Bean
public CamelCaseToUnderscoresNamingStrategy caseSensitivePhysicalNamingStrategy() {
return new CamelCaseToUnderscoresNamingStrategy() {
@Override
protected boolean isCaseInsensitive(JdbcEnvironment jdbcEnvironment) {
return false;
}
};
}
}
数据库初始化
一个SQL
数据库可以用不同的方式初始化,这取决于你的技术栈是什么。
使用JPA初始化数据库
JPA具有用于DDL生成的特性,可以将这些特性设置为在启动时针对数据库运行。这是通过两个外部属性控制的:
spring.jpa.generate-ddl (boolean)
: 开启和关闭该特性,并且与厂商无关。spring.jpa.hibernate.ddl-auto (enum)
:是以更细粒度的方式控制行为的Hibernate特性。
ddl-auto
枚举:none
(默认):禁用DDL
处理validate
:验证schema,不对数据库做任何操作update
: 更新schemacreate
: 创建schema,并销毁之前数据create-drop
: 会话创建时创建schema,会话关闭时销毁schema
使用Hibernate初始化数据库
你可以显式地设置spring.jpa.hibernate.ddl-auto
,标准的Hibernate属性值为none
、validate
、update
、create
和create-drop
。 根据Spring Boot是否认为数据库是嵌入式的,它会为你选择一个默认值。如果没有检测到schema管理器,或者在所有其他情况下都没有检测到schema
管理器,则默认为create-drop
。通过查看Connection类型和JDBC url来检测嵌入式数据库(Hsqldb
、h2
和Derby
是候选项)。从内存数据库切换到“真正的”数据库时要小心,不要假设新平台中存在表和数据。你要么必须显式地设置ddl-auto
,要么使用其他机制之一来初始化数据库。
你可以通过启用
org.hibernate.SQL
日志记录器来输出模式创建。如果你启用调试模式,这将自动完成。
另外,在classpath
根目录命名为import.sql
的文件,Hibernate在启动时执行此文件(如果将ddl-auto
属性设置为create
或create-drop
)。这个是Hibernate的特性。
新建实体类:
@Entity
public class Blog {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private String content;
//get set
}
配置:
spring:
datasource:
#数据库驱动完整类名
driver-class-name: com.mysql.jdbc.Driver
#数据库连接url
url: jdbc:mysql://127.0.0.1:3306/spring-boot-data-learn
#数据库用户名
username: root
#数据库密码
password: 123456
jpa:
hibernate:
ddl-auto: create
logging:
level:
org.hibernate.SQL: debug
启动程序:
HHH000400: Using dialect: org.hibernate.dialect.MySQL57Dialect
org.hibernate.SQL : drop table if exists blog
org.hibernate.SQL : create table blog (id bigint not null auto_increment, content varchar(255), title varchar(255), primary key (id)) engine=InnoDB
使用SQL脚本初始化
Spring Boot可以自动创建 JDBC DataSource Schema
(DDL
脚本)或R2DBC ConnectionFactory
并初始化它(DML
脚本)。 它从标准classpath
的根路径位置:分别加载schema.sql
和 data.sql
。
另外,Spring Boot还自动处理schema-${platform}.sql
和 data-${platform}.sql
(如果存在)文件,platform
的值来自spring.sql.init.platform
变量。这允许你在必要时切换到特定于数据库的脚本。例如,你可以选择将其设置为数据库(hsqldb
、h2
、oracle
、mysql
、postgresql
等)的供应商名称。
默认情况下,只有在使用嵌入式内存数据库时才执行SQL
数据库初始化。 要始终初始化一个SQL
数据库,不管它是什么类型,请将spring.sql.init.mode
设置为always
。类似地,要禁用初始化,可以将spring.sql.init.mode
设置为never
。默认情况下,Spring Boot启用其基于脚本的数据库初始化器的快速失败特性。这意味着,如果脚本导致异常,应用程序将无法启动。你可以通过设置spring.sql.init.continue-on-error
来调整该行为。
默认情况下,在创建JPA EntityManagerFactory bean之前执行基于脚本的数据源初始化。schema.sql
可用于为JPA-managed的实体创建schema
,data.sql
可以填充它。
不建议使用多个数据源初始化技术,如果你希望基于脚本的数据源初始化能够构建在Hibernate执行的schema创建之上,请将spring.jpa.defer-datasource-initialization
设置为true
。这将推迟数据源初始化,直到创建并初始化任何EntityManagerFactory bean之后。
如果你正在使用高级数据库迁移工具,如Flyway
或Liquibase
,你应该单独使用它们来创建和初始化schema
。不建议在Flyway
或Liquibase
一起使用schema.sql
和 data.sql
,并且在未来的版本中将删除支持。
新建resources/schema.sql和data.sql
//schema.sql
create table blog_always (id bigint not null auto_increment, content varchar(255), title varchar(255), primary key (id)) engine=InnoDB;
//data.sql
INSERT INTO blog_always(title,content)
VALUES('hello word',"content");
application.yaml配置
spring:
datasource:
#数据库驱动完整类名
driver-class-name: com.mysql.jdbc.Driver
#数据库连接url
url: jdbc:mysql://127.0.0.1:3306/spring-boot-data-learn
#数据库用户名
username: root
#数据库密码
password: 123456
jpa:
hibernate:
ddl-auto: create
sql:
init:
mode: always
continue-on-error: false
logging:
level:
org.hibernate.SQL: debug
启动程序:
使用Spring Batch初始化数据库
如果你使用Spring Batch,那么它已经预先打包了用于大多数流行数据库平台的SQL
初始化脚本。 Spring Boot可以检测你的数据库类型,并在启动时执行这些脚本。如果使用嵌入式数据库,默认情况下会发生这种情况。你也可以为任何数据库类型启用它,如下所示的示例:
spring:
batch:
jdbc:
initialize-schema: "always"
你还可以通过设置spring.batch.jdbc.initialize-schema=never
显式地关闭初始化。
数据库初始化依赖
数据库初始化是在应用程序启动时作为应用程序上下文刷新的一部分执行的。为了允许在启动期间访问已初始化的数据库,将自动检测充当数据库初始化器的bean和要求对数据库进行初始化的bean。其初始化依赖于已初始化的数据库的bean被配置为依赖于那些初始化数据库的bean。如果在启动期间,应用程序试图访问数据库,而数据库还没有初始化,则可以配置对初始化数据库并要求初始化数据库的bean的额外检测
检测数据库初始化器
Spring Boot将自动检测以下类型的bean来初始化SQL数据库:
- DataSourceScriptDatabaseInitializer
- EntityManagerFactory
- Flyway
- FlywayMigrationInitializer
- R2dbcScriptDatabaseInitializer
- SpringLiquibase
如果你正在为数据库初始化库使用第三方启动器,那么它可能会提供一个检测器,以便自动检测其他类型的bean
。要检测其他bean
,请在META-INF/spring-factories
中注册一个DatabaseInitializerDetector
实现。
检测依赖于数据库初始化的Bean
Spring Boot将自动检测以下类型的依赖于数据库初始化的bean
:
- AbstractEntityManagerFactoryBean (除非
spring.jpa.defer-datasource-initialization
设置为true
) - DSLContext (jOOQ)
- EntityManagerFactory (除非
spring.jpa.defer-datasource-initialization
设置为true
) - JdbcOperations
- NamedParameterJdbcOperations
如果你正在使用第三方starter
数据访问库,它可能会提供一个检测器,以便自动检测其他类型的bean。要检测其他bean,请在META-INF/spring-factories
中注册一个DependsOnDatabaseInitializationDetector
实现。或者,用@DependsOnDatabaseInitialization
注解的bean的类或它的@Bean
方法。