1.使用开始
配置maven
1 <dependency> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-data-jpa</artifactId> 4 </dependency>
配置properties
# database spring.datasource.url=jdbc:mysql://127.0.0.1:3306/stuadmin?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8 spring.datasource.username=root spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.type = com.alibaba.druid.pool.DruidDataSource spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=none spring.jpa.database-platform=org.hibernate.dialect.MySQL55Dialect
创建实体
2.一对一关系
- Teacher 教师
@Entity //表示实体 @Table(name = "t_teacher") // 表示数据库表名 // 数据库json序列化异常 @JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"}) public class Teacher { @Id //表示id主键 @GeneratedValue(strategy = GenerationType.IDENTITY) //自增长 @Column(name = "id", precision = 8) // 列名 总长度 private Long id; @Column(name = "name", length = 20) // length只作用于varchar类型 private String name; @Column(name = "subject", columnDefinition = "varchar(25) not null COMMENT '教授课程'") // columnDefinition 相当于添加一些细微属性操作 会拼接到数据 private String subject; }
- WorkCard 工作证
@Entity @Table(name = "t_work_card") @JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"}) public class WorkCard { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") private Long id; @Column(name = "number", unique = true) private Long number; @Column(name = "overtime", columnDefinition = "datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '过期时间'") private Date overtime; // 级联 懒加载 @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) //当前表id参照teacher表teacher_id字段 无外键(逻辑外键) @JoinColumn(name = "teacher_id", referencedColumnName = "id",foreignKey = @ForeignKey(name = "none",value = ConstraintMode.NO_CONSTRAINT)) private Teacher teacher; }
- 定义接口repository
public interface WorkCardRepository extends JpaRepository<WorkCard, Long> { }
- 使用
@Autowired WorkCardRepository workCardRepository; @GetMapping("/getteacherandworkcard") @ResponseBody public WorkCard queryWorkcardAndTeacher() { // 级联查询 WorkCard one = workCardRepository.getOne(1L); return one; }
多对一
- Classz 教室
@Entity @Table(name = "t_class") @JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"}) public class Classz { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") private Long id; @Column(name = "name", columnDefinition = "varchar(25) not null COMMENT '班级名称'") private String name; //一对多 当前教室为1 学生为多 //当前属性映射到classz中 //懒加载 @OneToMany(mappedBy = "classz", cascade = CascadeType.ALL, fetch = FetchType.LAZY) private List<Student> studentList; }
- Student 学生
@Entity @Table(name = "t_student") @JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"}) public class Student { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") private Long id; @Column(name = "name", columnDefinition = "varchar(25) not null COMMENT '姓名'") private String name; @Column(name = "age") private Integer age; @Column(name = "gender", columnDefinition = "varchar(2) not null default '男' COMMENT '性别'") private String gender; @Column(name = "distance", columnDefinition = "decimal(5,2) COMMENT '离校距离'") private BigDecimal distance; @ManyToOne(fetch = FetchType.LAZY) // 多对一 // class_id字段映射 Class @JoinColumn(name = "class_id", foreignKey = @ForeignKey(name = "none",value = ConstraintMode.NO_CONSTRAINT)) @JsonIgnore private Classz classz; }
- 定义repository
public interface ClasszRepository extends JpaRepository<Classz, Long> { }
- 使用
@GetMapping("/getclassz") @ResponseBody public Classz queryClassz() { //查修班级 Classz one = classzRepository.getOne(3L); return one; }
多对多
- 教室
@Entity @Table(name = "t_class") @JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"}) public class Classz { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") private Long id; @Column(name = "name", columnDefinition = "varchar(25) not null COMMENT '班级名称'") private String name; @ManyToMany(mappedBy = "classzList", cascade = CascadeType.ALL, fetch = FetchType.LAZY) @JsonIgnore private List<Teacher> teachers; }
- 老师
@Entity @Table(name = "t_teacher") @JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"}) public class Teacher { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", precision = 8) private Long id; @Column(name = "name", length = 20) private String name; @Column(name = "subject", columnDefinition = "varchar(25) not null COMMENT '教授课程'") private String subject; @ManyToMany(cascade=CascadeType.ALL, fetch = FetchType.LAZY) //Teacher是关系的维护端 //将会生成中间关联表 @JoinTable(name = "t_teacher_class_ref", joinColumns = @JoinColumn(name="teacher_id", foreignKey = @ForeignKey(name = "none",value = ConstraintMode.NO_CONSTRAINT)), inverseJoinColumns = @JoinColumn(name = "class_id", foreignKey = @ForeignKey(name = "none",value = ConstraintMode.NO_CONSTRAINT)), uniqueConstraints = {@UniqueConstraint(columnNames={"class_id", "teacher_id"})}) // class_id teacher_id 联合索引 private List<Classz> classzList;//教室 }
- 定义repository
- 使用
@GetMapping("/getteachers") @ResponseBody public Teacher queryTeachers() { // 级联查询 Teacher one = teacherRepository.getOne(1L); return one; }
自定义方法名
public interface UserRepository extends JpaRepository<User, Long> { List<User> findByAge(Integer age); List<User> findAllByAgeBetween(Integer start, Integer end); List<User> findUsersByAgeAndGenderLessThan(Integer age, Integer gender); @Query(nativeQuery = true, value = "select * from t_user where username = :username") List<User> findUsersByName(@Param("username") String username); }
native sql
@Query(nativeQuery = true, value = "select * from t_user where username = :username") List<User> findUsersByName(@Param("username") String username);
jpql
@Query("select s from Student s join s.classz c where c.name = :classname and s.name like :sname%")
List<Student> getStudentByName(@Param("classname") String classname, @Param("sname") String sname);
分页
public interface StudentPagingAndSortRepository extends PagingAndSortingRepository<Student, Long> { } @GetMapping("/get/studensbypage") @ResponseBody public List<Student> getStudentsByPage(@Param("page") Integer page, @Param("size") Integer size) { Pageable pageRequest = PageRequest.of(page, size); Page<Student> findStudentsByPage = studentPagingAndSortRepository.findAll(pageRequest); return findStudentsByPage.getContent(); } 或者使用JpaSpecificationExecutor 动态查询 和 pagerequest联合使用 Pageable pageable = PageRequest.of(page,size); Specification<Student> specification = new Specification<Student>() { @Override public Predicate toPredicate(Root<Student> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) { List<Predicate> predicates = new ArrayList<Predicate>(); //age Predicate age = criteriaBuilder.between(root.<Integer>get("age"), agegt, agelt); predicates.add(age); //dis Predicate distance = criteriaBuilder.equal(root.<Double>get("distance"), BigDecimal.valueOf(dis)); predicates.add(distance); //gender Predicate gender = criteriaBuilder.equal(root.<String>get("gender"), gend); predicates.add(gender); Predicate endset = criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()])); return endset; } }; // 查询 Page<Student> students = studentSpecificationRepository.findAll(specification, pageable); return students.getContent(); }
级联关系 - CascadeType
https://www.jianshu.com/p/e8caafce5445
- CascadeType.REMOVE
- CascadeType.MERGE
- CascadeType.DETACH
- CascadeType.REFRESH
- CascadeType.ALL
@EntityGhpra解决n+1问题
1.用EntityGhpra解决n+1
@Entity @Table(name = "t_class")
@NamedEntityGraph(name = "Classz.Graph", attributeNodes = {@NamedAttributeNode("studentList")}) //注意这句,先用@NamedEntityGraph指名要加载的studentList属性 @JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"}) public class Classz { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") private Long id; @Column(name = "name", columnDefinition = "varchar(25) not null COMMENT '班级名称'") private String name; //一对多 当前教室为1 学生为多 //当前属性映射到classz中 //懒加载 @OneToMany(mappedBy = "classz", cascade = CascadeType.ALL, fetch = FetchType.LAZY) private List<Student> studentList; }
- 2.调用方法时,指名要进行加载优化的对象
public interface ClasszRepository extends JpaRepository<Classz, Long> {
// 解决懒加载n+1问题
@EntityGraph(value = "Classz.Graph", type = EntityGraph.EntityGraphType.FETCH)
public List<Classz> findAll(); }
自定义repository
https://blog.csdn.net/chengqiuming/article/details/82531227
jpa与hibernate的关系
- JPA
JPA全称: Java Persistence API,JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。 JPA的出现有两个原因:
1. 其一,简化现有Java EE和Java SE应用的对象持久化的开发工作;
2. 其二,Sun希望整合对ORM技术,实现持久化领域的统一。
Sun之所以提出JPA规范,其目的是以官方身份来统一各种ORM框架的规范,包括著名的Hibernate、TopLink等,不过JPA规范给开发者带来了福音:
开发者面向JPA规范的接口,但底层的JPA实现可以任意切换:
觉得Hibernate好的,可以选择Hibernate JPA实现;觉得TopLink好的,可以选择TopLink JPA实现……
这样开发者可以避免为使用Hibernate学习一套ORM框架,为使用TopLink又要再学习一套ORM框架
JPA提供的技术:
- (1)ORM映射元数据
JPA支持XML和JDK 5.0注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持
久化到数据库表中;
- (2)JPA 的API
用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发者从繁琐的JDBC和SQL代码中解
脱出来。
- (3)查询语言
通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合
- Hibernate
JPA是需要Provider来实现其功能的,Hibernate就是JPA Provider中很强的一个。
Java 8日期和时间支持
SQL片段映射
不可变的实体类型
实体过滤器
SQL片段匹配
手动冲洗模式
二级缓存查询
软删除
这些高级功能都是hibernate所拥有的。