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);
    }
复制代码

参考掘金大佬博客

相关文章
相关标签/搜索