未完待续
spring jpa
1. 参考链接
https://www.jianshu.com/p/c23c82a8fcfc
https://docs.spring.io/spring-data/jpa/docs/2.4.11/reference/html/#preface
2. 核心类
Repository, CrudRepository, PagingAndSortingRepository
3. 使用方式
3.1. 声明接口
interface PersonRepository extends Repository<Person, Long> { … }
3.2. 定义方法
interface PersonRepository extends Repository<Person, Long> {
List<Person> findByLastname(String lastname);
}
3.3. 让spring开启代理
- javaconfig方式
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@EnableJpaRepositories
class Config { … }
- xml方式
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/data/jpa
https://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<jpa:repositories base-package="com.acme.repositories"/>
</beans>
注意:不同的存储类型,使用相应的store(如jpa,mongodb), @Enable${store}Repositories
3.4. 使用
class SomeClient {
private final PersonRepository repository;
SomeClient(PersonRepository repository) {
this.repository = repository;
}
void doSomething() {
List<Person> persons = repository.findByLastname("Matthews");
}
}
4. 查询方法定义
代理通过两种方式生成查询语句
- 根据方法名自动生成
- 指定查询语句
4.1. 策略
Enable${store}Repositories的queryLookupStrategy属性指定
- create: 移除方法名的通用前缀,解析方法名获取
- use_declared_query: 通过注解指定
- Create_if_not_found:上面两种方式的混合
5. 自定义接口实现
Repository默认spring是通过代理组装的,寻找的是Impl结尾的接口实现,可通过Enable${store}Repositories的repositoryImplementationPostfix设置
interface CustomizedUserRepository {
void someCustomMethod(User user);
}
class CustomizedUserRepositoryImpl implements CustomizedUserRepository {
public void someCustomMethod(User user) {
// Your custom implementation
}
}
// 会借由CustomizedUserRepositoryImpl实现someCustomMethod方法,且优先级高于CrudRepository
interface UserRepository extends CrudRepository<User, Long>, CustomizedUserRepository {
// Declare query methods here
}
6. 事件驱动
https://www.baeldung.com/spring-data-ddd
当有save进行时,通过ApplicationEventPublisher发布@DomainEvent标记的事件,也可以继承AbstractAggregateRoot
@Entity
class AnAggregateRoot {
// 不能有参数
@DomainEvents
Collection<Object> domainEvents() {
// … return events you want to get published here
}
@AfterDomainEventPublication
void callbackMethod() {
// … potentially clean up domain events list
}
}
7. REST Query Language with Spring Data JPA Specifications
https://www.baeldung.com/rest-api-search-language-spring-data-specifications
和mybatisplus里的lambda类似
8. 主键策略
@GenericGenerator(name = "idGenerator", strategy = "uuid")
@GeneratedValue(generator = "idGenerator")
9. 审计
https://docs.spring.io/spring-data/jpa/docs/2.4.11/reference/html/#auditing
https://www.baeldung.com/database-auditing-jpa
@EnableJpaAuditing
@EntityListeners
@CreatedDate @CreatedBy @LastModifiedDate @LastModifiedBy
9.1. 使用@EnableJpaAuditing注解开启审计
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories
@EnableJpaAuditing
public class PersistenceConfig { ... }
9.2. 在实体上配置监听
@Entity
@EntityListeners(AuditingEntityListener.class)
public class Bar { ... }
9.3. 配置审计字段
@Entity
@EntityListeners(AuditingEntityListener.class)
public class Bar {
//...
@Column(name = "created_date", nullable = false, updatable = false)
@CreatedDate
private long createdDate;
@Column(name = "modified_date")
@LastModifiedDate
private long modifiedDate;
@Column(name = "created_by")
@CreatedBy
private String createdBy;
@Column(name = "modified_by")
@LastModifiedBy
private String modifiedBy;
//...
}
10. 多EntityManager
- 设置持久化单元名称
// 设置repository的属性
@EnableJpaRepositories(
basePackages = {"com.fan.db.repository.common"},
entityManagerFactoryRef = "commonEntityManagerFactory",
transactionManagerRef = "commonTransactionManager"
)
---
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("com.acme.domain");
factory.setDataSource(dataSource());
factory.setPersistenceUnitName("fan");// 持久化单元名称
return factory;
}
- 通过JpaContext获取
class UserRepositoryImpl implements UserRepositoryCustom {
private final EntityManager em;
@Autowired
public UserRepositoryImpl(JpaContext context) {
this.em = context.getEntityManagerByManagedType(User.class);
}
…
}
11. 类型转换
@javax.persistence.Convert(converter = ApiSourceConverter.class)
12. 通用注解
@Version
@Column
@Enumerated
@Basic
@Transient
@NoRepositoryBean
标记该类不会被Spring Data 创建实例,如CrudRepository上就有
14. 实体关系
@OneToMany
@ManyToOne @JoinColumn
hibernate
org.hibernate.annotations.Type
@Type(type = "pg-uuid")
PostUpdateEventListener, PostLoadEventListener, PersistEventListener, MergeEventListener