参考链接:https://www.baeldung.com/spring-data-jpa-projections
1. 前置
@Entity
public class Address {
@Id
private Long id;
@OneToOne
private Person person;
private String state;
private String city;
private String street;
private String zipCode;
// getters and setters
}
@Entity
public class Person {
@Id
private Long id;
private String firstName;
private String lastName;
@OneToOne(mappedBy = "person")
private Address address;
// getters and setters
}
2. 映射
出于业务需要,对于jpa我们经常需要定制返回实体,大体方式如下
2.1. 接口方式映射
默认情况下,hibernate查询的结果是一个map对象,这种方式的原理是hibernate会创建接口的代理,根据接口方法名去实际的map里取值,这也是为什么接口定义的都是get方法而不是set方法。
- 封闭式
public interface AddressView {
String getZipCode();
}
public interface AddressRepository extends Repository<Address, Long> {
List<AddressView> getAddressByState(String state);
}
- 开放式
public interface PersonView {
// ...
@Value("#{target.firstName + ' ' + target.lastName}")
String getFullName();
}
public interface PersonRepository extends Repository<Person, Long> {
PersonView findByLastName(String lastName);
}
2.2. 类方式
如果不是数据库映射的实体类,需要提供全字段的构造方法,参数较多的时候就比较难看了。
public class PersonDto {
private String firstName;
private String lastName;
public PersonDto(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
// getters, equals and hashCode
}
public interface PersonRepository extends Repository<Person, Long> {
// ...
PersonDto findByFirstName(String firstName);
}
2.3. 动态映射
将要映射的类作为参数
public interface PersonRepository extends Repository<Person, Long> {
// ...
<T> T findByLastName(String lastName, Class<T> type);
}
3. 复杂属性
https://javabydeveloper.com/mapping-composite-value-types/
@Embeddable
@Embedded
@EmbeddedId
@AttributeOverride(name=“streetAddress”, column=@Column(name=“STREET_ADDRESS”))