Springdata jpa 入门

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

此时定义classrepository 和 teacherrepository 都行

public interface TeacherRepository extends JpaRepository<Teacher, Long> {
}
  • 使用
@GetMapping("/getteachers")
@ResponseBody
public Teacher queryTeachers() {

    // 级联查询
    Teacher one = teacherRepository.getOne(1L);

    return one;
}
自定义方法名

在repository中可以定义许多方法 例如findby get等, 调用方式和之前一样

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

相当于自己写sql

    @Query(nativeQuery = true, value = "select * from t_user where username = :username")
    List<User> findUsersByName(@Param("username") String username);
jpql

对象级别的sql

    @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);
分页

继承pageAndSortRepository接口即可

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
Cascade remove operation,级联删除操作。
删除当前实体时,与它有映射关系的实体也会跟着被删除。
  • CascadeType.MERGE
Cascade merge operation,级联更新(合并)操作。
当Student中的数据改变,会相应地更新Course中的数据。 
  • CascadeType.DETACH
Cascade detach operation,级联脱管/游离操作。
如果你要删除一个实体,但是它有外键无法删除,你就需要这个级联权限了。它会撤销所有相关的外键关联。
  • CascadeType.REFRESH
Cascade refresh operation,级联刷新操作。
假设场景 有一个订单,订单里面关联了许多商品,这个订单可以被很多人操作,那么这个时候A对此订单和关联的商品进行了修改, 与此同时,B也进行了相同的操作,但是B先一步比A保存了数据,那么当A保存数据的时候,就需要先刷新订单信息及关联的商品信息后,再将订单及商品保存。 
  • CascadeType.ALL
Cascade all operations,清晰明确,拥有以上所有级联操作权限。
@EntityGhpra解决n+1问题

n+1问题:一个教室对应多个学生时,jpa默认会先查询所有的教室,接着再通过每个用户的id去一条条查询每个教室的学生,这样会导致数据库执行多次sql语句,降低数据库性能;

  • 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的关系
  1. 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语句紧密耦合

  1. Hibernate

  JPA是需要Provider来实现其功能的,Hibernate就是JPA Provider中很强的一个。

Java 8日期和时间支持

SQL片段映射

不可变的实体类型

实体过滤器

SQL片段匹配

手动冲洗模式

二级缓存查询

软删除

 这些高级功能都是hibernate所拥有的。

猜你喜欢

转载自www.cnblogs.com/poetrycloud/p/11967115.html
今日推荐