• Springdata-Jpa学习笔记


    Respository接口

    Respository是Springdata JPA中的顶层接口,提供了两种查询方法:

    1)基于方法名称命名规则

    2)基于@Qeury注解查询

    1. 方法名称命名规则查询

    规则:findBy(关键字)+属性名称(属性名称首字母大写)+查询条件(首字母大写)

    模糊查询:

    @Test
    public void test(){
        
        List<StudentEntity> res = this.stu.findByXmLike("刘%");
        for(StudentEntity tmp : res){
            System.out.println(tmp);
        }
    }
    

    方法命名规则:

    • And --- 等价于 SQL 中的 and 关键字,比如 findByUsernameAndPassword(String user, Striang pwd);
    • Or --- 等价于 SQL 中的 or 关键字,比如 findByUsernameOrAddress(String user, String addr);
    • Between --- 等价于 SQL 中的 between 关键字,比如 findBySalaryBetween(int max, int min);
    • LessThan --- 等价于 SQL 中的 "<",比如 findBySalaryLessThan(int max);
    • GreaterThan --- 等价于 SQL 中的">",比如 findBySalaryGreaterThan(int min);
    • GreaterThanEqual
    • IsNull --- 等价于 SQL 中的 "is null",比如 findByUsernameIsNull();
    • IsNotNull --- 等价于 SQL 中的 "is not null",比如 findByUsernameIsNotNull();
    • NotNull --- 与 IsNotNull 等价;
    • Like --- 等价于 SQL 中的 "like",比如 findByUsernameLike(String user);
    • NotLike --- 等价于 SQL 中的 "not like",比如 findByUsernameNotLike(String user);
    • OrderBy --- 等价于 SQL 中的 "order by",比如 findByUsernameOrderBySalaryAsc(String user);
    • Not --- 等价于 SQL 中的 "! =",比如 findByUsernameNot(String user);
    • In --- 等价于 SQL 中的 "in",比如 findByUsernameIn(Collection userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;
    • NotIn --- 等价于 SQL 中的 "not in",比如 findByUsernameNotIn(Collection userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;

    缺点:查询条件过于复杂时,方法名会很长

    2. 基于@Query注解的查询

    2.1 通过JPQL语句查询

    JPQL:通过Hibernate的HQL演变过来的。和HQL语法极其相似。

    不需要实现方法;

    JPQL中语句的变量使用类名和类中成员。

    //使用@Query注解查询, 抽象方法, 参数列表的顺序就是sql语句中的顺序
        @Query(value="from StudentEntity where xm like ?1")
        List<StudentEntity> queryByXm(String name);
    
    //多值查询
    	@Query(value="from StudentEntity where xm is ?1 and yxh is ?2")
    	List<StduentEntity> queryByXmAndYxh(String name, Integer yxh);
    
    //或是这样的Like查询写法
    @Query(value="from StudentEntity where xm like %:name%")
        List<StudentEntity> queryByXm(@Param("name") String name);
    

    @Param("name") 给参数在JPQL语句中赋值

    2.2 通过SQL语句查询

    @Query语句中使用数据库中的表名和表中数据

    nativeQuery = true 使用SQL语句

    //可标可不标参数顺序, 多值查询时不标明顺序按次序填充
    @Query(value = "select * from S where xm = ?1", nativeQuery = true)
        List<StudentEntity> queryBySQL(String name);
    

    3. 分页

    PagingAndSortingRepository

    3.1. 分页处理
    @Test
        public void testPaging(){
            int page, size;
            //page 为当前页的索引,起始为0
            //size 为页面大小
            page = 1;
            size = 5;
            Pageable p = new PageRequest(page,size);
            Page<StudentEntity> res =  this.stu.findAll(p);
            for(StudentEntity s: res){
                System.out.println(s);
            }
        }
    
    3.2 排序处理
    /*
        对单列做排序
         */
        @Test
        public void testSort(){
            // Sort: 该对象封装了排序规则以及指定的排序字段(对象的属性来表示)
            // direction: 排序规则
            // properties: 指定做排序的属性, 给表对应类的属性
            Sort sort = new Sort(Sort.Direction.DESC, "xh");
            List<StudentEntity> res = this.stu.findAll(sort);
            for(StudentEntity s: res){
                System.out.println(s);
            }
        }
    
    /*
    多列排序
    */
    @Test
        public void testSort2(){
            //Sort sort = new Sort();
            Sort.Order o1 = new Sort.Order(Sort.Direction.DESC, "yxh");
            Sort.Order o2 = new Sort.Order(Sort.Direction.ASC, "csrq");
            Sort sort = new Sort(o1,o2);
            List<StudentEntity>  res = this.stu.findAll(sort);
            for(StudentEntity s: res){
                System.out.println(s);
            }
        }
    

    4. JpaSpecificationExecutor接口

    不能单独使用,必须和JpaRepository同时继承,否则无法生成代理对象。

    完成复杂的多条件查询,并且支持分页与排序

    //1.创建接口
    public interface StudentRepository extends JpaRepository<StudentEntity,Integer>, JpaSpecificationExecutor<StudentEntity>
    
    5.1 单条件查询

    根据criteriaBuilder的方法调用确定查询方法,如:相等判断,模糊查询等

    root.get()方法返回的值可以用 .as(String.class)转成 字符串类 (或其他指定类)

    /*
        JpaSpecificationExecutor
        单条件查询
         */
        @Test
        public void testSpecification(){
            Specification<StudentEntity> spec= new Specification<StudentEntity>() {
                /*
                @return Predicate:定义了查询条件
                @param Root<StduentEntity> root:根对象,封装了查询条件的对象
                @param criteriaQuery :定义了基本的查询,一般不常用
                @param criteriaBuilder : 创建一个查询条件
                 */
                @Override
                public Predicate toPredicate(Root<StudentEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                    Predicate pre = criteriaBuilder.equal(root.get("xm"), "刘%");
                    return pre;
                }
            };
    
            List<StudentEntity> res = this.stu.findAll(spec);
            for(StudentEntity s: res){
                System.out.println(s);
            }
        }
    
    5.2 多条件查询

    多条件查询有多种方式

    /*
        JpaSpecificationExecutor
        需求:使用姓名和学院查询数据
        多条件查询方式一
         */
        @Test
        public void testSpecification2(){
            Specification<StudentEntity> spec= new Specification<StudentEntity>() {
                /*
                @return Predicate:定义了查询条件
                @param Root<StduentEntity> root:根对象,封装了查询条件的对象
                @param criteriaQuery :定义了基本的查询,一般不常用
                @param criteriaBuilder : 创建一个查询条件
                 */
                @Override
                public Predicate toPredicate(Root<StudentEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                    List<Predicate> plist = new ArrayList<>();
                    plist.add(criteriaBuilder.like(root.get("xm"), "刘%"));
                    plist.add(criteriaBuilder.equal(root.get("yxh"),2));
                    //此时条件之间没有关联
                    Predicate [] arr = new Predicate[plist.size()];
                    return criteriaBuilder.or(plist.toArray(arr));     //规定关系之间的关系并返回查询规则
                    //如果再想或关系,就将cb返回的Predicate对象再放入cb.or方法中
                }
            };
    
            List<StudentEntity> res = this.stu.findAll(spec);
            for(StudentEntity s: res){
                System.out.println(s);
            }
        }
    
    /*
        JpaSpecificationExecutor
        需求:使用姓名和学院查询数据
        多条件查询方式二
         */
        @Test
        public void testSpecification2(){
            Specification<StudentEntity> spec= new Specification<StudentEntity>() {
                /*
                @return Predicate:定义了查询条件
                @param Root<StduentEntity> root:根对象,封装了查询条件的对象
                @param criteriaQuery :定义了基本的查询,一般不常用
                @param criteriaBuilder : 创建一个查询条件
                 */
                @Override
                public Predicate toPredicate(Root<StudentEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
                    return cb.or(cb.like(root.get("xm"),"刘%"), cb.equal(root.get("yxh"),2));
                }
            };
    
            List<StudentEntity> res = this.stu.findAll(spec);
            for(StudentEntity s: res){
                System.out.println(s);
            }
        }
    
    
    5.3 多条件查询+分页
    	/*
        查询院系号为1或性别为女的同学 结果分页
         */
        @Test
        public void test4(){
            Specification<StudentEntity> spec = new Specification<StudentEntity>() {
                @Override
                public Predicate toPredicate(Root<StudentEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
                    return cb.and(cb.equal(root.get("yxh"),1),cb.equal(root.get("xb"),0));
                }
            };
    
            Pageable pg = new PageRequest(0,2);
            Page<StudentEntity> res = this.stu.findAll(spec, pg);
            System.out.println(res.getTotalElements());
            System.out.println(res.getTotalPages());
            for(StudentEntity s :res){
                System.out.println(s);
            }
        }
    
    5.4 条件查询+排序
    /*
        查询院系号为1或性别为女的同学,结果按学号做倒序排序
         */
        @Test
        public void test5(){
            Specification<StudentEntity> spec = new Specification<StudentEntity>() {
                @Override
                public Predicate toPredicate(Root<StudentEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
                    return cb.and(cb.equal(root.get("yxh"),1),cb.equal(root.get("xb"),0));
                }
            };
    
            Sort sort = new Sort(Sort.Direction.DESC,"xh");
            List<StudentEntity> res = this.stu.findAll(sort);
            for(StudentEntity s :res){
                System.out.println(s);
            }
        }
    
    5.5 条件查询+分页+排序

    将排序整合到分页对象中

    new PageRequest(0,3,sort);
    
    /*
        查询院系号为1或性别为女的同学,做分页处理,结果按学号做倒序排序
         */
        @Test
        public void test6(){
            //排序定义
            Sort sort = new Sort(Sort.Direction.DESC,"xh");
            //分页定义,Pageable对象中存在
            Pageable pg = new PageRequest(0,3,sort);
    
            Specification<StudentEntity> spec = new Specification<StudentEntity>() {
                @Override
                public Predicate toPredicate(Root<StudentEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
                    return cb.and(cb.equal(root.get("yxh"),1),cb.equal(root.get("xb"),0));
                }
            };
            Page<StudentEntity> res = this.stu.findAll(pg);
            System.out.println("总条目数: "+res.getTotalElements());
            System.out.println("页数: "+res.getTotalPages());
            for(StudentEntity s : res){
                System.out.println(s);
            }
        }
    

    5. 实体类

    5.1 主键定义
    //自增方式创建主键
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Id
        @Column(name="xh")
        private int xh;
    

    @Temporal方法

    //JPA将时间映射到日期
        @Temporal(TemporalType.DATE)
        @Column(name = "csrq")
        private Date csrq;
    

    6. 关联关系

    6.1 一对一关系

    例:角色与用户一对一

    //测试一对一关系 学生类
        @OneToOne(cascade = CascadeType.PERSIST)		//表示级联关系,增加学生时,对应用户也会加入数据库
        @JoinColumn(name="id")				//表示外键,使用对应表的主键(数据库内的名称)
        private Account account;
    
    	//用户类
    	@OneToOne(mappedBy = "account")			//看谁引用了这个account
    	private StudentEntity student;
    

    操作一对一关系

    //增添数据
    @Test
        public void test7(){
            //创建用户对象
            Account acc = new Account();
            acc.setUsername("玩家");
    
            //创建学生对象
            StudentEntity student = new StudentEntity();
            student.setXm("李修文");
            student.setYxh(3);
            student.setSjhm("13120716616");
            student.setPassword("0");
            //student.setCsrq(new Date("1998-7-24"));
            student.setJg("上海");
            student.setXb(1);
    
            //关联
            student.setAccount(acc);
            acc.setStudent(student);
    
            //保存学生,相应地acc中也会出现“玩家”条目
            this.stu.save(student);
        }
    
    	/*
        根据学号查询学生,并查询其账户
         */
        @Test
        public void test8(){
            StudentEntity student = this.stu.findByXh(1112);
            System.out.println("学生信息:"+student);
            Account acc = student.getAccount();
            System.out.println(acc);
        }
    
    6.2 一对多关系
    //用户类
    @Id
        @Column(name="user_id")
        private int userId;
    
        @Column(name="user_name")
        private String name;
    
        @OneToMany
        @JoinColumn(name="role_id")
        private Role role;
    
    //角色类
    	@Id
        @Column(name="role_id")
        private Integer roleId;
    
        @Column(name="role_name")
        private String roleName;
    
        @OneToMany(mappedBy = "role")
        private Set<User> users = new HashSet<User>();
    
    
    6.3 多对多关系

    将会生成一个中间表

    //学生类
    
    /*
    @JoinTable: 配置中间表信息
    joinColumns: 建立当前表在中间表的外键字段
    */
    @ManyToMany(cascade = CasadeType.PERSIST, fetch = FetchType.EAGER)		//级联操作,添加不存在的数据时同时导入课程类,  放弃延迟加载改为立即加载
    @JoinTable(name="t_stu_class",joinColumns=@JoinColumn(name="stu_xh"), inverseJoinColumns = @JoinColumn(name="class_id"))
    private Set<Class> classes = new HashSet<Class>();
    
    
    //课程类
    @ManyToMany(mappedBy = "classes")		//映射引用课程类的对象
    private Set<Student> students = new HashSet<Student>();
    

    *无论是一对多还是多对多,级联操作开启在具体使用的那个类的注解上

    在查询时,如果没有用立即加载的话,输出学生对应的所有课程会报错(因为延迟加载,session在检索出学生后就关闭了)

  • 相关阅读:
    win7 下加载MSCOMCTL.OCX
    getGLES1ExtensionString: Could not find GLES 1.x config!
    IUnknown(TVarData(Params[0]).VPointer) as Range
    win8 VB6打开提示MSCOMCTL.ocx未注册
    服务端接口处理流任务要如何返回?
    flink之kafka生产和消费实战-将生产数据存放到mongodb中
    初识doris的那些基本概念
    bash常见用法
    sonar p3c规则配置
    sonar之gitlab ci 在gradle项目的实践(汉化、branch、 commit提交评论)
  • 原文地址:https://www.cnblogs.com/xiuwenli/p/11027776.html
Copyright © 2020-2023  润新知