ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2019-09-18 10:54:17  阅读:374  来源: 互联网

标签:JPA 痛点 System entity println Student Mybatis id out


前言

  • 用惯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 findPage(int page, int size, Student entity){
    //分页+属性排序
    Pageable pageable = PageRequest.of(page, size, Sort.by(Order.desc("id")));
    //字符串包含查(即左右模糊查)+ 忽略大小写 + non-null空串支持
    Example example = Example.of(entity, ExampleMatcher.matching().withStringMatcher(StringMatcher.CONTAINING));
    //查
    Page 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生成实体

  • 在DataSource窗口新建一个DataSource
  • 新建一个JPAproject,右键 JPA Tool > Generate entity from table
  • 拷贝这些实体到目标项目
  • 参考:https://blog.csdn.net/guoxin91/article/details/31801919

标签:JPA,痛点,System,entity,println,Student,Mybatis,id,out
来源: https://www.cnblogs.com/noodlerkun/p/11540296.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有