spring-data-jpa
简介
JPA(Java Persistence API) 意即 Java 持久化 API,是 Sun 官方在 JDK5.0 后提出的 Java 持久化规范。JPA 的出现主要是为了简化持久层开发以及整合 ORM 技术。JPA 包括以下 3 方面的技术:
- ORM 映射元数据:支持 XML 和注解两种元数据的形式,元数据描述对象和表之间的映射关系
- API:操作实体对象来执行 CRUD 操作
- 查询语言:通过面向对象而非面向数据库的查询语言(JPQL)查询数据,避免程序的 SQL 语句紧密耦合
Spring Data JPA 极大的简化 JPA 的写法,可以在几乎不用写实现的情况下,实现对数据的访问和操作。除了 CRUD 外,还包括如分页、排序等一些常用的功能。它的核心概念包括:
- Repository:最顶层的接口,是一个空的接口,目的是为了统一所有 Repository 的类型,且能让组件扫描的时候自动识别。
- CrudRepository :是Repository的子接口,提供CRUD的功能
- PagingAndSortingRepository:是CrudRepository的子接口,添加分页和排序的功能
- JpaRepository:是PagingAndSortingRepository的子接口,增加了一些实用的功能,比如:批量操作等。
- JpaSpecificationExecutor:用来做负责查询的接口
- Specification:是Spring Data JPA提供的一个查询规范,要做复杂的查询,只需围绕这个规范来设置查询条件即可
Y9 主要使用了 Spring Boot + Spring Data Jpa 来做数据的 CRUD 等操作。具体 JpaRepository 提供的方法可查看:https://docs.spring.io/spring-data/jpa/docs/2.7.18/reference/html/#jpa.query-methods.query-creation
功能引用
Y9提供了两种JPA数据源配置模块
risenet-y9boot-starter-jpa-public
risenet-y9boot-starter-jpa-tenant
druid 是阿里巴巴开源平台上一个数据库连接池实现,它结合了 C3P0、DBCP、PROXOOL 等 DB 池的优点,同时加入了日志监控,可以很好的监控 DB 池连接和 SQL 的执行情况,可以说是针对监控而生的 DB 连接池,据说是目前最好的连接池。Y9 将数据连接池由 druid 来接管。其 druid 数据源属性配置参考如下所示:
(1)application.properties 配置:
需要排除DataSourceAutoConfiguration和HibernateJpaAutoConfiguration
spring.autoconfigure.exclude[0]=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
spring.autoconfigure.exclude[1]=org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
spring.data.jpa.repositories.bootstrap-mode=default
spring.data.jpa.repositories.enabled=false
spring.datasource.druid.filter.stat.log-slow-sql=true
spring.datasource.druid.filter.stat.mergeSql=true
spring.datasource.druid.filter.stat.slow-sql-millis=3000
spring.datasource.druid.filter.wall.config.drop-table-allow=false
spring.datasource.druid.filter.wall.enabled=true
spring.datasource.druid.stat-view-servlet.enabled=false
spring.datasource.druid.stat-view-servlet.url-pattern=/druid/*
spring.datasource.druid.stat-view-servlet.login-username=admin
spring.datasource.druid.stat-view-servlet.login-password=admin
spring.datasource.druid.stat-view-servlet.reset-enable=false
spring.datasource.druid.stat-view-servlet.allow=127.0.0.1
spring.datasource.druid.web-stat-filter.enabled=false
spring.datasource.druid.web-stat-filter.url-pattern=/*
spring.datasource.druid.web-stat-filter.exclusions=*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*,/static/*
spring.jpa.generate-ddl=true
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.open-in-view=false
spring.jpa.properties.hibernate.hbm2ddl.auto=none
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
spring.jpa.properties.hibernate.jdbc.batch_size=100
spring.jpa.properties.hibernate.show_sql=true
spring:
autoconfigure:
exclude:
- org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
- org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
data:
jpa:
repositories:
bootstrap-mode: default
enabled: false
datasource:
druid:
filter:
stat:
log-slow-sql: true
mergeSql: true
slow-sql-millis: 3000
wall:
config:
drop-table-allow: false
enabled: true
stat-view-servlet:
enabled: false
url-pattern: /druid/*
login-username: admin
login-password: admin
reset-enable: false
allow: 127.0.0.1
web-stat-filter:
enabled: false
url-pattern: /*
exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*,/static/*'
jpa:
generate-ddl: true
database-platform: org.hibernate.dialect.MySQL8Dialect
hibernate:
naming:
implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
open-in-view: false
properties:
hibernate:
hbm2ddl:
auto: none
dialect: org.hibernate.dialect.MySQL8Dialect
jdbc:
batch_size: 100
show_sql: true
公共数据源的配置
引用与配置
(1)修改 pom.xml
将本公司的私服仓库地址添加到 pom.xml 文件中。
<repositories>
<repository>
<id>y9-internet-repo</id>
<url>https://svn.youshengyun.com:9900/nexus/repository/maven-public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
<!-- <updatePolicy>always</updatePolicy> -->
<!-- always,daily(default),interval:XXX,never -->
</snapshots>
</repository>
</repositories>
(2)将risenet-y9boot-starter-jpa-public 添加到 pom.xml 的依赖列表里.
<dependency>
<groupId>net.risesoft</groupId>
<artifactId>risenet-y9boot-starter-jpa-public</artifactId>
<version>[最新版本]</version>
</dependency>
(3)添加数据源属性配置,修改属性文件 application.properties
spring.datasource.druid.y9-public.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.druid.y9-public.url=jdbc:mysql://218.60.41.112:3306/y9_public?serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&useUnicode=true&characterEncoding=utf-8&rewriteBatchedStatements=true&useCompression=true&useSSL=false
spring.datasource.druid.y9-public.username=root
spring.datasource.druid.y9-public.password=Y9i-83204585
spring.datasource.druid.y9-public.initialSize=1
spring.datasource.druid.y9-public.maxActive=20
spring.datasource.druid.y9-public.maxPoolPreparedStatementPerConnectionSize=100
spring.datasource.druid.y9-public.maxWait=60000
spring.datasource.druid.y9-public.minEvictableIdleTimeMillis=300000
spring.datasource.druid.y9-public.minIdle=1
spring.datasource.druid.y9-public.poolPreparedStatements=true
spring.datasource.druid.y9-public.testOnBorrow=false
spring.datasource.druid.y9-public.testOnReturn=false
spring.datasource.druid.y9-public.testWhileIdle=true
spring.datasource.druid.y9-public.timeBetweenEvictionRunsMillis=60000
spring.datasource.druid.y9-public.useGlobalDataSourceStat=true
spring.datasource.druid.y9-public.validationQuery=SELECT 1 FROM DUAL
#设置实体类扫描位置
y9.feature.jpa.packagesToScanEntityPublic=net.risesoft.y9public.entity
y9.feature.jpa.packagesToScanRepositoryPublic=net.risesoft.y9public.repository
spring:
datasource:
druid:
y9-public:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/y9_public?serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&useUnicode=true&characterEncoding=utf-8&rewriteBatchedStatements=true&useCompression=true&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: 111111
initialSize: 1
maxActive: 20
maxPoolPreparedStatementPerConnectionSize: 100
maxWait: 60000
minEvictableIdleTimeMillis: 300000
minIdle: 1
poolPreparedStatements: true
testOnBorrow: false
testOnReturn: false
testWhileIdle: true
timeBetweenEvictionRunsMillis: 60000
useGlobalDataSourceStat: true
validationQuery: SELECT 1 FROM DUAL
y9:
feature:
jpa:
packagesToScanEntityPublic: net.risesoft.y9public.entity
packagesToScanRepositoryPublic: net.risesoft.y9public.repository
使用说明
(1)创建数据源:y9PublicDS。
(2)创建 Entity 持久化操作的主要对象工厂 EntityManagerFactory:rsPublicEntityManagerFactory
(3)提供事务 PlatformTransactionManager:rsPublicTransactionManager
使用示例:
@Transactional(value = "rsPublicTransactionManager", readOnly = true)
public interface AppFolderRepository extends JpaRepository<AppFolder, String>, JpaSpecificationExecutor<AppFolder> {
}
(4)创建 JDBC 查询 JdbcTemplate Bean:jdbcTemplate4Public
使用示例:
@Autowired
@Qualifier("jdbcTemplate4Public")
private JdbcTemplate jdbcTemplate4Public;
@RequestMapping("/test")
public void test(HttpServletResponse response) {
try {
String sql = "select id from rs_common_tenant";
List<String> tenantIDList = jdbcTemplate4Public.queryForList(sql, String.class);
for (String tenantID : tenantIDList) {
System.out.println(tenantID);
}
} catch (IOException e) {
}
}
租户数据源的配置
使用与配置
(1)修改 pom.xml
将本公司的私服仓库地址添加到 pom.xml 文件中。
<repositories>
<repository>
<id>y9-internet-repo</id>
<url>https://svn.youshengyun.com:9900/nexus/repository/maven-public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
<!-- <updatePolicy>always</updatePolicy> -->
<!-- always,daily(default),interval:XXX,never -->
</snapshots>
</repository>
</repositories>
(2)将 risenet-y9boot-starter-jpa-tenant 添加到 pom.xml 的依赖列表里.
<dependency>
<groupId>net.risesoft</groupId>
<artifactId>risenet-y9boot-starter-jpa-tenant</artifactId>
<version>[最新版本]</version>
</dependency>
(3)多租户数据源的defaultDataSource通过属性spring.datasource.druid.tenantDefault指定,默认为spring.datasource.druid.y9Public,当然可以指定本应用自己的,比如spring.datasource.druid.flowable,修改属性文件application.properties如下:
spring.datasource.druid.tenantDefault=spring.datasource.druid.flowable
spring.datasource.druid.flowable.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.druid.flowable.url=jdbc:mysql://localhost:3306/y9_flowable?serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&useUnicode=true&characterEncoding=utf-8&rewriteBatchedStatements=true&useCompression=true&useSSL=false
spring.datasource.druid.flowable.username=root
spring.datasource.druid.flowable.password=111111
spring.datasource.druid.flowable.initialSize=1
spring.datasource.druid.flowable.maxActive=20
spring.datasource.druid.flowable.maxPoolPreparedStatementPerConnectionSize=100
spring.datasource.druid.flowable.maxWait=60000
spring.datasource.druid.flowable.minEvictableIdleTimeMillis=300000
spring.datasource.druid.flowable.minIdle=1
spring.datasource.druid.flowable.poolPreparedStatements=true
spring.datasource.druid.flowable.testOnBorrow=false
spring.datasource.druid.flowable.testOnReturn=false
spring.datasource.druid.flowable.testWhileIdle=true
spring.datasource.druid.flowable.timeBetweenEvictionRunsMillis=60000
spring.datasource.druid.flowable.useGlobalDataSourceStat=true
spring.datasource.druid.flowable.validationQuery=SELECT 1 FROM DUAL
#实体类扫描位置
y9.feature.jpa.packagesToScanEntityTenant=net.risesoft.entity
y9.feature.jpa.packagesToScanRepositoryTenant=net.risesoft.repository
spring:
datasource:
druid:
tenantDefault: spring.datasource.druid.example
example:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/y9_flowable?serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&useUnicode=true&characterEncoding=utf-8&rewriteBatchedStatements=true&useCompression=true&useSSL=false
password: 111111
username: root
initialSize: 1
maxActive: 20
maxPoolPreparedStatementPerConnectionSize: 100
maxWait: 60000
minEvictableIdleTimeMillis: 300000
minIdle: 1
poolPreparedStatements: true
testOnBorrow: false
testOnReturn: false
testWhileIdle: true
timeBetweenEvictionRunsMillis: 60000
useGlobalDataSourceStat: true
validationQuery: SELECT 1 FROM DUAL
y9:
feature:
jpa:
packagesToScanEntityTenant: net.risesoft.entity
packagesToScanRepositoryTenant: net.risesoft.repository
使用说明
(1)创建数据源:y9PublicDS和defaultDataSource。
(2)创建 Entity 持久化操作的主要对象工厂 EntityManagerFactory:rsTenantEntityManagerFactory, entityManagerFactory
(3)提供事务 PlatformTransactionManager:rsTenantTransactionManager、transactionManager
使用示例:
@Transactional(value = "rsTenantTransactionManager", readOnly = true)
public interface AppItemRepository extends JpaRepository<AppItem, String>, JpaSpecificationExecutor<AppItem> {
}
(4)创建 JDBC 查询 JdbcTemplate Bean:jdbcTemplate4Tenant
使用示例:
@Autowired
@Qualifier("jdbcTemplate4Tenant")
private JdbcTemplate jdbcTemplate4Tenant;
@RequestMapping("/test")
public void test(HttpServletResponse response) {
try {
String sql = "select id from RC8_ORG_POSITION";
List<String> positionIDs = jdbcTemplate4Tenant.queryForList(sql, String.class);
for (String positionID : positionIDs) {
System.out.println(positionID);
}
} catch (IOException e) {
}
}
数据库多租户数据源管理
提供数据源切换工具,可通过数据库轮询和 Kafka 监听两个方式监听数据源的变化,此外还提供 Liquibase 管理数据表结构的变化。
注:租户数据源的 Liquibase 管理管理需要配合数字底座的系统管理,先在数字底座生成系统才可使用。
引用与配置
(1)修改 pom.xml
<dependency>
<groupId>net.risesoft</groupId>
<artifactId>risenet-y9boot-starter-multi-tenant</artifactId>
<version>[最新版本]</version>
</dependency>
(2)修改属性文件,其中
y9.feature.multi-tenant.event-source提供两个方式 kafka 和 db
y9.feature.multi-tenant.event-source=db
y9:
feature:
multi-tenant:
event-source: db
liquibase管理分公共库和租户库的初始化:
y9.feature.liquibase.public-enabled=true
y9.feature.liquibase.tenant-enabled=true
y9:
feature:
liquibase:
public-enabled: true
tenant-enabled: true
约定目录结构如下:
其中租户的 main.xml 示例如下:
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.9.xsd">
<include file="liquibase/tenant/init.xml"/>
<includeAll path="liquibase/tenant/release/"/>
</databaseChangeLog>
具体初始化和更新等操作可参考:liquibase官网
注:开启 liquibase 需要把把自动更新关闭,spring.jpa.properties.hibernate.hbm2ddl.auto=none
示例代码
码云地址:https://gitee.com/risesoft-y9/y9-core
该示例代码路径地址:https://gitee.com/risesoft-y9/y9-core/tree/main/y9-digitalbase-example/risenet-y9demo-data-jpa