SpringDataJpa大全

SpringDataJPA概念

  1. Spring Data JPA 是 Spring 基于 ORM 框架、JPA规范的基础上封装的一套JPA应用框架,可使开发者用极简的代码即可实现对数据库的访问和操作
  2. Spring Data JPA 提供了包括增删改查等在内的常用功能,且易于扩展,大大提高了开发效率

SpringDataJPA快速入门

1. 项目配置

1.1 在pom.xml中添加相关依赖
1.2 在applicationContext.xml配置相应的配置
1.3 创建实体类和实体类对应的DAO接口
复制代码

2. Spring Data JPA DAO流程分析

底层用的动态代理,完成接口的实现类对象,根据方法名查询,更加简单便捷

3. Dao层接口基础方法

  • 继承JpaRepository后的方法列表
  • 继承JpaSpecificationExecutor的方法列表
  • 基础查询
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class CustomerDaoTest {
    @Autowired
    private CustomerDao customerDao;

    /**
     * 根据id查询
     */
    @Test
    public void testFindOne(){
        Customer c = customerDao.findOne(2l);
        System.out.println(c);
    }

    /**
     * 保存与更新   是否传id主键属性
     */
    @Test
    public void testSave(){
        Customer customer = new Customer();
        customer.setCustName("洪湖");
        customerDao.save(customer);
    }
    @Test
    public void testUpdate(){
        Customer customer = new Customer();
        customer.setCustId(4l);
        customer.setCustName("大洪湖");
        customerDao.save(customer);
    }

    /**
     * 删除用户
     */
    @Test
    public void testDelete(){
        customerDao.delete(4l);
    }

    /**
     * 查询所有用户
     */
    @Test
    public void testFindAll(){
        List<Customer> list = customerDao.findAll();
        for (Customer customer : list) {
            System.out.println(customer);
        }
    }

    /**
     * 查询客户总数量
     */
    @Test
    public void testCount(){
        long count = customerDao.count();
        System.out.println(count);
    }

    /**
     * 判断用户是否存在
     */
    @Test
    public void testExists(){
        boolean exists=customerDao.exists(3l);
        System.out.println("是否存在:"+exists);
    }

    /**
     * 根据id从数据库查询
     *      findOne
     *          em.find();              立即加载
     *      getOne()
     *          em.getReference();      延迟加载    什么时候用  什么时候查询
     */
    @Test
    @Transactional
    public void testGetOne(){
        Customer customer = customerDao.getOne(3l);
        System.out.println(customer);
    }

}
复制代码
  • 基本能完成简单的crud和排序,分页等功能

4.JPQL

query注解
  • Dao层接口配置
/**
 * springDataJPA规范  需要继承两个接口
 * JpaRepository接口   * 基本的增删查改操作
 * JpaSpecificationExecutor接口    * 封装了复杂查询操作
 */
public interface CustomerDao extends JpaRepository<Customer,Long>,JpaSpecificationExecutor<Customer>{
    /**
     * 根据客户名称 查询客户
     * jpql
     *
     */
    @Query(value = "from Customer where custName = ?")
    public Customer findJpql(String custName);

    /**
     * 多条件查询
     * jpql
     */
    @Query(value = "from Customer where custId = ? and custName = ?")
    public Customer findTwoJpql(long custId,String custName);

    /**
     * 更新操作
     * jpql
     */
    @Query(value = "update Customer set custName = ? where custId = ?")
    @Modifying
    public void updateJpql(String custName,long custId);

    /**
     * sql语句  查询
     */
    @Query(value = "select * from cst_customer",nativeQuery = true)
    public List<Object[]> findSql();

    /**
     * sql语句  查询
     */
    @Query(value = "select * from cst_customer WHERE cust_name LIKE ?",nativeQuery = true)
    public List<Object[]> findSqlFindName(String name);
    
     /**
     * 方法名称查询
     */
    public Customer findByCustName(String custName);

    /**
     * 模糊查询
     * @param custName
     * @return
     */
    public List<Customer> findByCustNameLike(String custName);

    /**
     * 精确查询
     * @param custName
     * @param custLevel
     * @return
     */
    public Customer findByCustNameLikeAndCustLevel(String custName,String custLevel);
}
复制代码
  • 测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class JpqlTest {
    @Autowired
    private CustomerDao customerDao;

    /**
     * JPQL精准查询
     */
    @Test
    public void testFindJPQL(){
        Customer customer = customerDao.findJpql("深圳计划");
        System.out.println(customer);
    }

    /**
     * JPQL多条件查询
     */
    @Test
    public void  testFindTwoJPQL(){
        Customer c = customerDao.findTwoJpql(2l, "深圳计划");
        System.out.println(c);
    }

    /**
     * JPQL更新操作
     * 需要添加事务  不然会回滚
     */
    @Test
    @Transactional
    @Rollback(value = false)
    public void  testUpdateJPQL(){
        customerDao.updateJpql("大深圳计划",2l);
    }

    /**
     * sql语句查询
     */
    @Test
    public void testSql(){
        List<Object[]> list = customerDao.findSql();
        for (Object[] objects : list) {
            System.out.println(Arrays.toString(objects));
        }
    }

    /**
     * sql语句模糊查询
     */
    @Test
    public void testSqlFindName(){
        List<Object[]> list = customerDao.findSqlFindName("%计划");
        for (Object[] objects : list) {
            System.out.println(Arrays.toString(objects));
        }
    }
      /**
     * 方法名称查询
     */
    @Test
    public void findByCustName(){
        Customer c = customerDao.findByCustName("福州计划");
        System.out.println(c);
    }

    /**
     * 模糊查询
     */
    @Test
    public void findByCustNameLike(){
        List<Customer> list = customerDao.findByCustNameLike("%计划");
        for (Customer customer : list) {
            System.out.println(customer);
        }
    }

    /**
     * sql多条件查询
     */
    @Test
    public void findByCustNameLikeAndCustLevel(){
        Customer c = customerDao.findByCustNameLikeAndCustLevel("%计划", "1");
        System.out.println(c);
    }
}
复制代码
Specifications动态查询
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class SpecTest {
    @Autowired
    private CustomerDao customerDao;

    /**
     * 根据条件查询单个对象
     */
    @Test
    public void testSpec(){
        /**
         * 匿名内部类
         * 自定义查询条件
         *      root 需要查询对象的属性
         *      CriteriaBuilder 构造查询条件的【模糊匹配,精准匹配等】
         *
         */
        Specification<Customer> spec=new Specification<Customer>() {
            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                //获取比较的属性
                Path<Object> custName = root.get("custName");
                //构造查询  【进行精准匹配】
                //1.比较的属性  2.比较的值
                Predicate p = cb.equal(custName, "福州计划");
                return p;
            }
        };
        Customer customer = customerDao.findOne(spec);
        System.out.println(customer);
    }

    /**
     *  多条件查询
     */
    @Test
    public void testSpec1(){
        /**
         * root 获取属性
         * cb  构造查询
         */
        Specification<Customer> spec=new Specification<Customer>() {
            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                Path<Object> custName = root.get("custName");
                Path<Object> custLevel = root.get("custLevel");
                //精准匹配
                Predicate p1 = criteriaBuilder.equal(custName, "大深圳计划");
                Predicate p2 = criteriaBuilder.equal(custLevel, "1");
                Predicate p = criteriaBuilder.and(p1, p2);
                return p;
            }
        };
        Customer c = customerDao.findOne(spec);
        System.out.println(c);
    }

    /**
     *  模糊查询
     */
    @Test
    public void testSpec2(){
        /**
         * root 获取属性
         * cb  构造查询
         */
        Specification<Customer> spec=new Specification<Customer>() {
            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                Path<Object> custName = root.get("custName");
                Predicate p = criteriaBuilder.like(custName.as(String.class), "%计划");
                return p;
            }
        };
        //排序对象   1.排序方式【倒序或者正序】 排序属性名
        Sort sort = new Sort(Sort.Direction.DESC,"custId");
        List<Customer> list = customerDao.findAll(spec, sort);
        for (Customer c : list) {
            System.out.println(c);
        }
    }

    /**
     * 分页查询
     */
    @Test
    public void testSpec3(){
        Specification spec=null;
        //1.当前页码  2.每页显示条数
        Pageable pageable =new PageRequest(0,2);
        Page<Customer> p = customerDao.findAll(spec, pageable);
        System.out.println(p.getContent());//获得数据集合列表
        System.out.println(p.getTotalElements());//总条数
        System.out.println(p.getTotalPages()); //总页数
    }

}
复制代码

5.多表关系

一对多映射
  • LinkMan实体类
    /**
     * 配置联系人到客户多对一关系
     * 声明关系
     *          @ManyToOne  一对多
     *              targetEntity:对方对象的字节码
     *    配置外键
     *          @JoinColumn  配置外键
     *              name 外键字段名称
     *              referencedColumnName 参见主表的字段名称
     */
    @ManyToOne(targetEntity = Customer.class)
    @JoinColumn(name = "lkm_cust_id",referencedColumnName = "cust_id")
    private Customer customer;
复制代码
  • Customer实体类
    //配置客户和联系人之间的关系  一对多
    /**
     * 注解配置多表关系
     *    声明关系
     *          @OneToMany  一对多
     *              targetEntity:对方对象的字节码
     *    配置外键
     *          @JoinColumn  配置外键
     *              name 外键字段名称
     *              referencedColumnName 参见主表的字段名称
     *
     *  @OneToMany(targetEntity = LinkMan.class)
     *  @JoinColumn(name = "lkm_cust_id",referencedColumnName = "cust_id")
     *      放弃外键维护权   使用 mappedBy:对方配置关系的属性名称
     *  cascade 配置级联
     *      CascadeType.All         所有
     *                  MERGE       更新
     *                  PERSIST     保存
     *                  REMOVE      删除
     */
    @OneToMany(mappedBy = "customer",cascade = CascadeType.ALL)
    private Set<LinkMan> linkMens=new HashSet<LinkMan>();
复制代码
  • 测试类
    @Autowired
    private CustomerDao customerDao;
    @Autowired
    private LinkManDao linkManDao;
    
    /**
     * 级联添加  保存一个客户的同时  保存客户的所有的联系人
     */
    @Test
    @Transactional  //设置事务
    @Rollback(value = false)
    public void testCascadeAdd(){
        Customer customer=new Customer();
        customer.setCustName("阿里");
        LinkMan man=new LinkMan();
        man.setLkmName("淼哥");
        man.setCustomer(customer);
        customer.getLinkMens().add(man);
        customerDao.save(customer);
    }
    /**
     * 级联删除
     */
    @Test
    @Transactional  //设置事务
    @Rollback(value = false)//不回滚
    public void testCascadeDelete(){
        Customer c = customerDao.findOne(1l);
        //删除一号客户
        customerDao.delete(c);
    }
    
     /**
     *  一查多
     *      加载方式:延迟加载
     * 对象导航查询 【查询一个对象时,通过此对象查询所有的关联对象】
     */
    @Test
    @Transactional
    public void testQuery1(){
        Customer customer = customerDao.getOne(1l);
        Set<LinkMan> set = customer.getLinkMens();
        for (LinkMan man : set) {
            System.out.println(man);
        }
    }

    /**
     *  多查一
     *    加载方式:立即加载
     */
    @Test
    @Transactional
    public void testQuery2(){
        LinkMan linkMan = linkManDao.findOne(2l);
        Customer customer = linkMan.getCustomer();
        System.out.println(customer);
    }

复制代码
多对多映射
  • User实体类
    /**
     *  用户到角色
     *  配置多对多关系
     *      1.表明表关系的配置
     *      2.配置中间表(包含两个外键)
     *      @ManyToMany
     *           targetEntity 对方实体类字节码
     *      @JoinTable
     *           joinColumns  当前表在中间表的外键
     *                  name: 外键名
     *                  referencedColumnName:参照主表的主键名
     *           inverseJoinColumns  对方表在中间表的外键
     */
    @ManyToMany(targetEntity = Role.class,cascade = CascadeType.ALL)
    @JoinTable(name = "sys_user_role",
        joinColumns = {@JoinColumn(name = "sys_user_id",referencedColumnName = "user_id")},
        inverseJoinColumns = {@JoinColumn(name = "sys_role_id",referencedColumnName = "role_id")}
    )
    private Set<Role> roles=new HashSet<Role>();
复制代码
  • Role实体类
     /**
     *  角色到用户
     *  配置多对多关系
     *      1.表明表关系的配置
     *      2.配置中间表(包含两个外键)
     *      @ManyToMany
     *           targetEntity 对方实体类字节码
     *      @JoinTable
     *           joinColumns  当前表在中间表的外键
     *                  name: 外键名
     *                  referencedColumnName:参照主表的主键名
     *           inverseJoinColumns  对方表在中间表的外键
     *  放弃外键维护权   使用 mappedBy:对方配置关系的属性名称
     *      @ManyToMany(targetEntity = User.class)
     *      @JoinTable(name = "sys_user_role",
     *      joinColumns = {@JoinColumn(name = "sys_role_id",referencedColumnName = "role_id")},
     *      inverseJoinColumns = {@JoinColumn(name = "sys_user_id",referencedColumnName = "user_id")}
    )
     */
    @ManyToMany(mappedBy = "roles")
    private Set<User> users=new HashSet<User>();
复制代码
  • 测试类
/**
     * 级联操作 添加
     */
    @Test
    @Transactional
    @Rollback(false)
    public void testCasCadeAdd(){
        User user = new User();
        user.setUserName("淼哥");
        Role role = new Role();
        role.setRoleName("java软件工程师");
        // 一对一
        user.getRoles().add(role);
        //一对一 主键重复
        //role.getUsers().add(user);
        userDao.save(user);
    }
    /**
     * 级联操作 删除
     */
    @Test
    @Transactional
    @Rollback(false)
    public void testCasCadeDelete(){
        User user = userDao.findOne(1l);
        userDao.delete(user);
    }
复制代码

参考掘金大佬博客

转载于:https://juejin.im/post/5cf9aa6e5188252fbc380857

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值