• sort:Mybatis转用JPA的几大痛点使用总结


    前言

    • 用惯Mybatis后,转JPA发现DAO操作格外优雅清爽
    • 但是依旧有几个痛点,毕竟Mybatis的特点就是灵活(前提是用的熟。。)
    • 痛点(说不上痛点其实,用的没有Mybatis熟练罢了。。)
      • 综合条件分页查询(Example和Pageable使用)
      • 复杂SQL查询(Mybatis优势大)
      • Entity部分属性更新
      • 反向Entity类生成(Mybatis有逆向工具,JPA也有了)
    • MybatisPlus用起来应该也是优雅的,有时间去官网看看..
    • 版本说明
      • springboot2.1.7
      • MySQL5.7
      • JDK1.8

    综合条件分页查询

    分页查询

    • 学生实体类
      @Entity
      @Table(name = "tb_student")
      public class Student extends SerializableBean{
      private static final long serialVersionUID = -4418101957648659928L;
      	@Id
      	@GeneratedValue(strategy = GenerationType.IDENTITY) //mysql自增主键
      	private Integer id;
      	
      	@Column(length = 20)
      	private String name;
      	
      	//...
      }
      
    • 学生Repository接口
      public interface StudentRepository extends JpaRepository<Student, Integer> {
      }
      
    • @SpringBootTest JUnit
      @Test
      public void test_findPage() {
      	//模拟前端传参
      	int page = 3, size = 10; //查第1页,每页10条
      	//分页查询,注:JPA页码从0开始,所以 PageRequest.of(page-1, size)
      	Page<Student> pager = stuRepo.findAll(PageRequest.of(page-1, size));
      	//结果
      	System.out.println(pager.getNumber()+1); //当前页码 2
      	System.out.println(pager.getSize()); //每页记录 10
      	System.out.println(pager.getTotalPages()); //总页数 3
      	System.out.println(pager.getTotalElements()); //总记录数
      	System.out.println(pager.getNumberOfElements()); //本页记录数 5
      	System.out.println(pager.getContent()); //本页结果集 5
      }
      

    综合条件查询

    • 方法 List<S> findAll(Example<S> example);
    • Example 抽象了实体查询条件
    • ExampleMatcher 抽象了查询条件的附加效果,比如模糊匹配、忽略大小写等
    • 实例:
      @Test
      public void test_findByExample() {
      	//模拟前台输入 name
      	Student entity = new Student();
      	entity.setName("name");
      	entity.setClassId(1);
      	
      	//简单的非null属性,精确查询
      	Example<Student> example = Example.of(entity);
      	//字符串属性模糊查 + 非null空串 支持
      	Example<Student> example2 = Example.of(entity, ExampleMatcher.matching().withStringMatcher(StringMatcher.CONTAINING));
      	
      	//查询
      	List<Student> list = stuRepo.findAll(example);
      	System.out.println(list.size());
      }
      

    多条件综合查询与分页结合

    • 方法:<S extends T> Page<S> findAll(Example<S> example, Pageable pageable);
    • 实例:
      public Page<Student> findPage(int page, int size, Student entity){
      	//分页+属性排序
      	Pageable pageable = PageRequest.of(page, size, Sort.by(Order.desc("id"))); 
      	//字符串包含查(即左右模糊查)+ 忽略大小写 + non-null空串支持
      	Example<Student> example = Example.of(entity, ExampleMatcher.matching().withStringMatcher(StringMatcher.CONTAINING));
      	//查
      	Page<Student> pager = stuRepo.findAll(example, pageable);
      	
      	return pager;
      }
      

    复杂SQL查询

    方式1:外键关联(@ManyToOne 等)

    适用于依旧使用传统外键的场景,但是现在很多场景都不推荐使用外键

    方式2:@Query注解(JPQL 和 Native)

    额。。挺麻烦的(主要还没用熟,有机会在整理)

    方法3:复杂查询用Mybatis

    • 将只做复杂查询工作交给Mybatis,扬长避短
    • 不要在一个service方法中同时使用JPA和Mybatis
    • Mapper和Repository井水不犯河水

    部分属性更新

    • 错误示范
      @Test
      public void testSaveFlush() {
      	int id = 47;
      	//原实体对象
      	Student entity0 = stuRepo.findById(id).get();
      	System.out.println(entity0); //{"classId":9,"createTime":null,"id":47,"name":"aaa"}
      	//错误更新
      	Student enity = new Student();
      	enity.setName("bbb");
      	enity.setId(id);
      	Student stu_upd = stuRepo.saveAndFlush(enity);
      	System.out.println(stu_upd); //{"classId":null,"createTime":null,"id":47,"name":"bbb"}
      	//name之外的属性全部被更新成了null
      }
      
    • 正确方式1-service方法中先查赋值再更新
      @Test
      public void testSaveFlush() {
      	int id = 47;
      	//模拟前端传参
      	Student vo = new Student();
      	vo.setName("bbb");
      	vo.setId(id);
      	//原实体对象
      	Student entity0 = stuRepo.findById(id).get();
      	System.out.println(entity0); //{"classId":9,"createTime":"2019-09-12T23:28:23","id":47,"name":"aaa"}
      	//赋值
      	MyBeanUtils.copyProperties(vo, entity0); //改写的bean属性复制方法,dest有值的属性不覆盖
      	//更新
      	Student entity_upd = stuRepo.saveAndFlush(entity0);
      	System.out.println(entity_upd); //{"classId":9,"createTime":"2019-09-12T23:28:23","id":47,"name":"bbb"}
      }
      
    • 正确方式2-使用springmvc的@ModelAttribute(推荐
      • Service层方法
        public Student merge(Student entity) {
        	
        	return stuRepo.saveAndFlush(entity);
        }
        
      • Controller层
        //for 实体对象部分修改
        @ModelAttribute
        public void modelAttributeGetStudent(@RequestParam(value="id", required = false) Integer id, Model model) {
        	if(id!=null) {
        	    //注意:"student" 需是 handler方法的入参类型(Student)小写
        		model.addAttribute("student", stuRepo.findById(id).get()); 
        	}
        }
        //学生修改/新增
        @PutMapping
        public BaseResult merge(Student stu) {
        	Student entity = stuService.merge(stu);
        	
        	return BaseResult.successData(entity);
        }
        

    逆向生成Entity方式

    • 使用JPA一般直接运行生成表结构
    • Entity类的注解对表结构细节不好把控
    • 很多场景都是传统的先有表设计再有业务开发

    eclipse使用JAP Tool生成实体

  • 相关阅读:
    ps+div+css打造蓝色后台login页面实现,ps切片,浏览器兼容
    mysql 常用命令与问题
    struts2 笔记
    hibernate在eclipse的逆向工程生成hbm.xml和bean类
    struts2 checkbox 传值的用法
    css 背景渐变,圆角,阴影用法与兼容
    Firefox 插件 JSview下载
    Spark插件开发完全入门手册,多级组织架构初步(原创) CVT
    Java 动态代理机制分析及扩展,第 2 部分(转) CVT
    Windows 2012服务器建立域控(AD DS)详解(转) CVT
  • 原文地址:https://www.cnblogs.com/noodlerkun/p/11540296.html
Copyright © 2020-2023  润新知