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);
    }
複製代碼

參考掘金大佬博客

相關文章
相關標籤/搜索