springdata-jpa
1.映射
1.1自动映射
参考地址:
11-1.idea 从数据库快速生成Spring Data JPA实体类
1.2一对一映射
@OneToOne(targetEntity=TeacherDto.class,cascade=CascadeType.ALL,fetch=FetchType.EAGER)
@JoinColumn(name="teacherId",referencedColumnName = "teacherId",insertable = false,updatable = false)
参考地址:
12-1.Spring Data JPA 关系映射(一对一,一对多,多对多 )
1.3一对多,多对一映射
1.3.1 双向映射
1.3.1.1多对一
import com.fasterxml.jackson.annotation.JsonBackReference;
@ManyToOne (targetEntity=BuildingDto.class,cascade=CascadeType.ALL,fetch=FetchType.EAGER)
@JoinColumn(name="classroomId",referencedColumnName = "classroomId",insertable = false,updatable = false)
@JsonBackReference
注:name 是默认将外实体的主键作为外键,referencedColumnName 则不是,按实际情况而定
参考地址:
1311-1.@JoinColumn解释
1.3.1.2一对多
import com.fasterxml.jackson.annotation.JsonManagedReference;
@OneToMany(targetEntity=EquipmentDto.class,mappedBy = "BuildingDto")
@JsonManagedReference
注:@JsonBackReference和@JsonManagedReference的区别见参考地址1312-1。
参考地址:
1312-1.jackson中的@JsonBackReference和@JsonManagedReference,以及@JsonIgnore
参考地址:
131-1.JPA开发(下)一(多)对多的配置与crud操作
131-1.Spring Data JPA 之 一对一,一对多,多对多 关系映射
1.3.2单向映射
1.3.2.1多对一
@ManyToOne(targetEntity=SchoolDto.class,cascade=CascadeType.ALL,fetch=FetchType.EAGER)
@JoinColumn(name="schoolId",referencedColumnName = "schoolId",insertable = false,updatable = false)
注:注意不要写@JsonBackReference
,这个注解。
1.3.2.2一对多
@OneToMany(targetEntity=AcademicDto.class,cascade=CascadeType.ALL,fetch=FetchType.EAGER)
@JoinColumn(name="schoolId",referencedColumnName = "schoolId",insertable = false,updatable = false)
1.4多对多映射
参考地址:
14-1.SpringDataJpa 多对多表关系,映射对象CRUD
1.5带有条件的映射
// 是用于两个属性相等的情况下
@OneToMany(targetEntity=CourseTableDto.class,cascade=CascadeType.ALL,fetch=FetchType.EAGER)
@JoinColumnsOrFormulas(value = {
@JoinColumnOrFormula(column = @JoinColumn(name ="courseId", referencedColumnName ="courseId",insertable =false, updatable = false)),
@JoinColumnOrFormula(column = @JoinColumn(name ="teacherId", referencedColumnName ="teacherId",insertable =false, updatable = false))
})
参考地址:
15-1.@JoinColumn 匹配关联多个字段
15-2.table单一字段参照另一个table复合主键中的一个column 可使用@JoinFormula
1.6映射相关bug
bug1.Could not determine type for: java.util.List
// 具体bug
Caused by: org.hibernate.MappingException: Could not determine type for: java.util.List, at table: ss_user, for columns: [org.hibernate.mapping.Column(role_list)]
解决方案:注解要么全写在字段上,要么全写在getXX上,千万千万不能混合使用,否则会报这个错误!
参考地址:
bug1-1.实体类注解错误:Could not determine type for: java.util.List
bug2.2.返回JSON出现Infinite recursion
无限循环错误的解决
// 具体bug
ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: com.test.dto.BuildingDto["EquipmentDto"]->org.hibernate.collection.internal.PersistentBag[0] with root cause
java.lang.StackOverflowError: null
解决方案:在关联关系属性的getter方法上分别加上@JsonManagedReference
(一的一方)和 @JsonBackReference
(多的一方)即可
包名为:com.fasterxml.jackson.annotation.JsonBackReference;
com.fasterxml.jackson.annotation.JsonManagedReference;
参考地址:
bug2-1.返回JSON出现Infinite recursion无限循环错误的解决
bug3.should be mapped with insert="false" update="false"
解决方案:
@JoinColumn(name="classroomId",referencedColumnName = "classroomId",insertable = false,updatable = false)
1.7映射注意事项
1.数据表设计时可以没有外键约束,不过在实体类中还是要如上写上@OneToMany和@ManyToOne的注解及其里面的内容
2.常见注解的使用
2.1@Where
用途:针对逻辑删除时使用注解Where
参考地址;
21-1.JPA 使用@Where 注解实现全局过滤
3.分页与排序
参考地址:
4.使用Specification实现复杂查询
4.1查询模板
// 在resposity中继承JpaSpecificationExecutor的接口
public interface BuildingRepository extends JpaRepository<BuildingDto, Integer> , JpaSpecificationExecutor<BuildingDto> {
}
// 在使用的地方如下:
if(!StringUtils.isEmpty(buildingId)){
try {
Specification<BuildingDto> specification=(root, query, criteriaBuilder)->{
List<Predicate> predicateList=new ArrayList<>();
Join<BuildingDto,EquipmentDto> equipmentJoin=root.join("equipmentStatus", JoinType.LEFT);
// Join<BuildingDto,EquipmentDto> equipmentJoin=root.join(root.getModel().getList("equipmentStatus",EquipmentDto.class), JoinType.LEFT);
predicateList.add(criteriaBuilder.equal(root.get("isEnabled"),SystemConstant.IN_USE));
predicateList.add(criteriaBuilder.equal(root.get("buildingId"),buildingId));
predicateList.add(criteriaBuilder.or(criteriaBuilder.equal(equipmentJoin.get("isEnabled"),SystemConstant.IN_USE),criteriaBuilder.isNull(equipmentJoin.get("isEnabled"))));
return criteriaBuilder.and(predicateList.toArray(new Predicate[predicateList.size()]));
};
List<BuildingDto> BuildingDtos=BuildingRepository.findAll(specification);
return ResponseMessage.ok(BuildingDtos);
} catch (Exception e) {
log.warn(e.toString());
}
参考地址:
4-1.SpringDataJpa的Specification查询
4-2.Spring data jpa 多表查询(二:多表动态条件查询)
查询中的bug
bug1.Unable to locate Attribute
// bug具体内容
Unable to locate Attribute with the the given name [***] on this ManagedType [****]
解决方法:定义属性的时候,属性名称为equipmentStatus,那么对应的getter和setter就必须是getEquipmentStatus,setEquipmentStatus