本文主要翻译自Spring Boot 官方参考文档
JPA
JPA 是Java Persistence API的简称,JPA是一种将对象映射到关系型数据库的标准技术。spring-boot-starter-data-jpa很好地实现了这种技术。主要包括以下三个关键的依赖:
- Hibernate - 一种最流行的JPA实现
- Spring Data JPA - 可以利用它实现基于JPA的仓库
- Spring ORMs - 来自于Spring Framework的核心ORM支持
Entity Classes - 实体类
以前JPA实体类都是在persistence.xml文件上进行说明的。随着Spring Boot**实体扫描**的使用,这个文件将不是必须的了。默认情况下,所有在主配置类(被@EnableAutoConfiguration 或 @SpringBootApplication注解)下的包都会被搜索。
任何被@Entity, @Embeddable, @MappedSuperclass都会被扫描。一个典型的实体类如下:
package com.example.myapp.domain;
import java.io.Serializable;
import javax.persistence.*;
@Entity
public class City implements Serializable {
@Id
@GeneratedValue
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private String state;
// ... additional members, often include @OneToMany mappings
protected City() {
// no-args constructor required by JPA spec
// this one is protected since it shouldn't be used directly
}
public City(String name, String state) {
this.name = name;
this.country = country;
}
public String getName() {
return this.name;
}
public String getState() {
return this.state;
}
// ... etc
}
可以使用@EntityScan注解自定义实体扫描位置
Spring Data JPA Repositories
Spring Data JPA Repositories 是用来获取数据的接口。JPA查询会根据方法名称自动创建。例如,一个CityRepository
能够声明一个findAllByState(String state)
方法来查找给定州的所有城市,而这个方法的实现是自动生成的。
对于更加复杂的查询,可以通过Spring Data的Query注解来注解相应的方法实现。
Spring Data repositories 通常继承自Repository
或者CrudRepository
接口。如果使用了自动配置,repositories会被从主配置 类所在的包依次向下搜索。
典型的Spring Data repository如下:
package com.example.myapp.domain;
import org.springframework.data.domain.*;
import org.springframework.data.repository.*;
public interface CityRepository extends Repository<City, Long> {
Page<City> findAll(Pageable pageable);
City findByNameAndCountryAllIgnoringCase(String name, String country);
}
创建或者删除JPA数据库
默认情况下,只有在使用嵌入式数据库(H2, HSQL或者Derby)的情况下,JPA数据库会自动创建。 可以通过Spring.jpa.*属性显示地配置JPA。例如,可以在application.properties文件设置spring.jpa.hibernate.ddl-auto=create-drop
实现数据库的自动创建和删除。
配置Hibernate命名策略
Spring Boot提供了一致的命名策略并且忽略你正在使用的Hibernate生成的命名策略。如果你使用的是Hibernate4, 你能通过spring.jpa.hibernate.naming.strategy
实现自定义命名策略;但是Hibernate 5定义了Physical和Implicit命名策略。
Spring Boot默认通过SpringPhysicalNamingStrategy
进行配置。这种实现提供了和Hibernate4相同的表结构:所有的点号和驼峰形式都被下划线所取代。默认情况下,所有表的名称以小写字母的形式生成,但是也可以覆盖。
具体来说,一个TelephoneNumber实体将会映射到telephone_phone表中。
如果想使用Hibernate5的默认实现 ,可以像下面这样设置:
`spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNumingStrategyStandardImpl
具体请参考HibernateJpaAutoConfiguration
和 JpaBaseConfiguration
.
使用自定义的实体管理工厂
可以通过增加一个名为entityManagerFactory
的bean来完全控制EntityManagerFactory
的配置。如果存在上述的bean,Spring Boot的自动配置将会关闭自己的实体管理器。
使用两个EntityManager
即使默认的EntityManagerFactory
工作的很好,也有可能需要定义一个新的EntityManager。因为第二个bean会屏蔽掉默认的bean,为了更方便地实现上述目的,可以使用Spring Boot提供的EntityManagerBuilder,也可以使用直接来源于Spring ORM的LocalContainerEntityManagerFactoryBean
.示例如下:
// add two data sources configured as above
@Bean
public LocalContainerEntityManagerFactoryBean customerEntityManagerFactory(
EntityManagerFactoryBuilder builder) {
return builder
.dataSource(customerDataSource())
.packages(Customer.class)
.persistenceUnit("customers")
.build();
}
@Bean
public LocalContainerEntityManagerFactoryBean orderEntityManagerFactory(
EntityManagerFactoryBuilder builder) {
return builder
.dataSource(orderDataSource())
.packages(Order.class)
.persistenceUnit("orders")
.build();
}
上述配置几乎能单独工作。为了完成所有的工作,你还需要为这两个EntityManager
配置TransactionManagers
。在Spring Boot中如果将其中一个标记成@Primary
,被标记的EntityManager
会默认被JpaTransactionManager
使用。另外一个则必须被显式地注入到新的实例中。也可以使用JTA事务管理覆盖两者。
如果你正在使用Spring Data, 则需要一致地配置@EnableJpaRepositories
,例如
@Configuration
@EnableJpaRepositories(basePackageClasses = Customer.class,
entityManagerFactoryRef = "customerEntityManagerFactory")
public class CustomerConfiguration {
...
}
@Configuration
@EnableJpaRepositories(basePackageClasses = Order.class,
entityManagerFactoryRef = "orderEntityManagerFactory")
public class OrderConfiguration {
...
}