jpa文档笔记

未完待续


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
上一篇:Mybatis工具类MyBatisUtils


下一篇:AngularJS 学习笔记(六)--- 依赖注入和路由