Spring Data JPA

一. JPA簡介

  1. JPA的全稱是Java Persistence API, 即Java 持久化API,是SUN公司推出的一套基於ORM的規範,內部是由一系列的接口和抽象類構成。java

  2. JPA與hibernate的關係
    JPA規範本質上就是一種ORM規範,注意不是ORM框架——由於JPA並未提供ORM實現,它只是制訂了一些規範,提供了一些編程的API接口,但具體實現則由服務廠商來提供實現。JPA和Hibernate的關係就像JDBC和JDBC驅動的關係,JPA是規範,Hibernate除了做爲ORM框架以外,它也是一種JPA實現。JPA怎麼取代Hibernate呢?JDBC規範能夠驅動底層數據庫嗎?答案是否認的,也就是說,若是使用JPA規範進行數據庫操做,底層須要hibernate做爲其實現類完成數據持久化工做。
    mysql

  3. JPA的優點
    • 標準化
    • 容器級特性的支持
    • 簡單方便
    • 查詢能力
    • 高級特性

二. Spring Data JPA簡介

  1. Spring Data JPA 是 Spring 基於 ORM 框架、JPA 規範的基礎上封裝的一套JPA應用框架,可以使開發者用極簡的代碼便可實現對數據庫的訪問和操做。它提供了包括增刪改查等在內的經常使用功能,且易於擴展!學習並使用 Spring Data JPA 能夠極大提升開發效率!redis

  2. Spring Data JPA 與 JPA和hibernate之間的關係
    JPA是一套規範,內部是有接口和抽象類組成的。hibernate是一套成熟的ORM框架,並且Hibernate實現了JPA規範,因此也能夠稱hibernate爲JPA的一種實現方式,咱們使用JPA的API編程,意味着站在更高的角度上看待問題(面向接口編程)spring

    Spring Data JPA是Spring提供的一套對JPA操做更加高級的封裝,是在JPA規範下的專門用來進行數據持久化的解決方案。sql

  3. Spring Data JPA 與 JPA和hibernate之間的關係
    數據庫

  4. Spring Data JPA 入門程序
    pom.xmlexpress

    springContext.xml編程

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:jpa="http://www.springframework.org/schema/data/jpa"
       xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/data/jpa
        http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
    <!--spring和spring data jpa的配置-->
    <!-- 1.dataSource 配置數據庫鏈接池-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/jpa"/>
        <property name="user" value="root"/>
        <property name="password" value="root"/>
    </bean>
    <!-- 2.配置entityManagerFactory -->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="packagesToScan" value="cn.guet.domain"/>
        <property name="persistenceProvider">
            <bean class="org.hibernate.jpa.HibernatePersistenceProvider"/>
        </property>
        <!--JPA的供應商適配器-->
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="generateDdl" value="false"/>
                <property name="database" value="MYSQL"/>
                <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect"/>
                <property name="showSql" value="true"/>
            </bean>
        </property>
        <property name="jpaDialect">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
        </property>
    </bean>
    <!-- 3.事務管理器-->
    <!-- JPA事務管理器  -->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
    <!-- 整合spring data jpa-->
    <jpa:repositories base-package="cn.guet.dao"
                      transaction-manager-ref="transactionManager"
                      entity-manager-factory-ref="entityManagerFactory"></jpa:repositories>
    <!-- 4.txAdvice-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="save*" propagation="REQUIRED"/>
            <tx:method name="insert*" propagation="REQUIRED"/>
            <tx:method name="update*" propagation="REQUIRED"/>
            <tx:method name="delete*" propagation="REQUIRED"/>
            <tx:method name="get*" read-only="true"/>
            <tx:method name="find*" read-only="true"/>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
    <!-- 5.aop-->
    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(* cn.guet.service.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
    </aop:config>
    <context:component-scan base-package="cn.guet"></context:component-scan>
    <!--組裝其它 配置文件-->
    </beans>

    Dao 接口,繼承 JpaRepository、JpaSpecificationExecutor緩存

    //JpaRepository<操做的實體類型,實體類中主鍵的類型> 
    //JpaSpecificationExecutor<操做的實體類型>
    public interface CustormerDao extends JpaRepository<Customer, Long> , JpaSpecificationExecutor<Customer> {
    }

    測試代碼app

    @RunWith(SpringJUnit4ClassRunner.class) //聲明spring提供的測試單元
    @ContextConfiguration(locations = "classpath:applicationContext.xml") //指定spring容器的配置信息
    public class DaoTest {
    
    @Autowired
    private CustormerDao custormerDao;
    
    /**
     * findOne:根據id查詢
     */
    @Test
    public void testFindOne() {
        Customer customer = custormerDao.findOne((long) 1);
        System.out.println(customer);
    }
    
    /**
     * save:保存或者更新
     * 根據傳遞的對象是否存在主鍵
     * 若是沒有主鍵id屬性,保存
     * 存在主鍵id屬性,根據id查詢數據,並更新
     */
    @Test
    public void testSave() {
        Customer customer = new Customer();
        customer.setCustName("zzy");
        customer.setCustAddress("深圳");
        customer.setCustIndustry("student");
        custormerDao.save(customer);
    }
    
    /**
     * delete:刪除。先查詢,後刪除
     */
    @Test
    public void testDelete() {
        custormerDao.delete((long) 2);
    }
    
    /**
     * findAll:查詢全部
     */
    @Test
    public void testFindAll() {
        List<Customer> list = custormerDao.findAll();
        System.out.println(list);
    }
    }
  5. Spring Data JPA運行邏輯

  6. CrudRepository接口中的方法
    • long count();

    • void delete(ID var1);

    • void delete(T var1);

    • void delete(Iterable<? extends T> var1);

    • void deleteAll();

    • boolean exists(ID var1);

    • Iterable findAll();

  7. JpaRepository 接口中經常使用的方法 須要@Transactional
    • List findAll();

    • List findAll(Sort var1);

    • List findAll(Iterable var1);

    • void flush();

    • void deleteInBatch(Iterable var1);

    • void deleteAllInBatch();

    • T getOne(ID var1);

  8. 方法名稱規則查詢
    對jpql查詢,更加深刻的一層封裝,咱們只須要按照Spring Data JPA提供的方法名稱規則定義方法,不須要再去配置jpql語句,完成查詢。

    • 基本查詢 findBy+屬性名稱
    /**
     * 方法名的約定
     * findBy:查詢 + 對象中的屬性(首字母大寫):查詢的條件
     * findByCustName:根據客戶名稱查詢
     */
    public Customer findByCustName(String custName);
    • 模糊匹配 findBy+屬性名稱+查詢方式(like|isnull)
    /**
     * findBy+屬性名稱+查詢方式(like|isnull)
     */
    public Customer findByCustNameLike(String custName);
    • 多條件查詢 findBy+屬性名稱+查詢方式+多條件鏈接符(and|or) +屬性名稱+查詢方式
    /**
     * findBy+屬性名稱+查詢方式(like|isnull)+多條件鏈接符(and|or) +屬性名稱+查詢方式
     */
    public Customer findByCustNameLikeAndCustIndustry(String custName,String custIndustry);

三. Specification 動態查詢

  1. 方法列表
    • T findOne(Specification var1); 查詢單個對象

    • List findAll(Specification var1); 查詢列表

    • Page findAll(Specification var1, Pageable var2); 查新所有,分頁;Pageable 分頁參數

    • List findAll(Specification var1, Sort var2); 查詢所有,Specification:條件,Sort :排序參數

    • long count(Specification var1); 統計查詢

  2. Specification 查詢條件
    • Predicate toPredicate(Root var1, CriteriaQuery<?> var2, CriteriaBuilder var3);
      Root 封裝對象中的屬性,CriteriaQuery 不用,CriteriaBuilder 查詢的條件構造器,封裝查詢條件。
  3. T findOne(Specification var1):根據條件查詢單個對象

    //根據單個條件查詢單個對象
    @Test
    public void testSpec() {
        Customer customer = custormerDao.findOne(new Specification<Customer>() {
            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
                //獲取比較的屬性
                Path<Object> custName = root.get("custName");
                //構造查詢條件
                //equal 精準匹配,param1:須要比較的屬性,param2:當前須要比較的取值
                Predicate predicate = cb.equal(custName, "yxf");
                //返回查詢條件
                return predicate;
            }
        });
        System.out.println(customer);
    }
    //根據多個條件查詢單個對象
    @Test
    public void testSpec() {
        Customer customer = custormerDao.findOne(new Specification<Customer>() {
            //Root:獲取屬性,cb:構造查詢條件
            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
                Path<Object> custName = root.get("custName"); //客戶名
                Path<Object> custIndustry = root.get("custIndustry");//行業
                //構造兩個查詢條件
                Predicate predicate1 = cb.equal(custName, "yxf");
                Predicate predicate2 = cb.equal(custIndustry, "student");
                //將多個查詢條件組合到一塊兒
                Predicate predicate = cb.and(predicate1, predicate2);
                return predicate;
            }
        });
        System.out.println(customer);
    }
  4. List findAll(Specification var1); 模糊匹配查詢列表

    //根據多個條件查詢列表
    @Test
    public void testSpec() {
        List<Customer> customers = custormerDao.findAll(new Specification<Customer>() {
            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
                Path<Object> custSource = root.get("custSource");
                //gt,lt,ge,like:須要指定參數類型,Path.as(類型的字節碼對象)
                Predicate predicate = cb.like(custSource.as(String.class), "guet");
                return predicate;
            }
        });
        System.out.println(customers);
    }
  5. List findAll(Specification var1, Sort var2); 排序

    //根據多個條件查詢列表,並排序
    @Test
    public void testSpec() {
        //添加排序,須要調用構造方法實例化sort對象
        //param1:正序、倒序;param2:排序的屬性名
        Sort sort = new Sort(Sort.Direction.ASC, "custId");
        List<Customer> customers = custormerDao.findAll(new Specification<Customer>() {
            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
                Path<Object> custSource = root.get("custSource");
                //gt,lt,ge,like:須要指定參數類型,Path.as(類型的字節碼對象)
                Predicate predicate = cb.like(custSource.as(String.class), "guet");
                return predicate;
            }
        }, sort);
        System.out.println(customers);
    }
  6. Page findAll(Specification var1, Pageable var2); 分頁查詢 pageRequest

    //分頁查詢
    @Test
    public void testSpec() {
        //建立PageRequest的過程當中,須要調用構造方法,傳入兩個參數
        //param1:當前查詢的頁數,param2:每頁查詢的數量
        PageRequest pageRequest = new PageRequest(0, 2);
        Page<Customer> page = custormerDao.findAll(null, pageRequest);
        System.out.println("查詢列表" + page.getContent());
        System.out.println("總條數:" + page.getTotalElements());
        System.out.println("總頁數:" + page.getTotalPages());
    }

四. Spring Date Reis

  1. 經常使用方法
    • stringRedisTemplate.opsForValue().set("test", "100",60*10,TimeUnit.SECONDS);//向redis裏存入數據和設置緩存時間
    • stringRedisTemplate.opsForValue().get("test")//根據key獲取緩存中的val
    • stringRedisTemplate.boundValueOps("test").increment(-1);//val作-1操做
    • stringRedisTemplate.boundValueOps("test").increment(1);//val +1
    • stringRedisTemplate.getExpire("test")//根據key獲取過時時間
    • stringRedisTemplate.getExpire("test",TimeUnit.SECONDS)//根據key獲取過時時間並換算成指定單位
    • stringRedisTemplate.delete("test");//根據key刪除緩存
    • stringRedisTemplate.hasKey("546545");//檢查key是否存在,返回boolean值
    • stringRedisTemplate.expire("red_123",1000 , TimeUnit.MILLISECONDS);//設置過時時間
    • stringRedisTemplate.opsForSet().add("red_123", "1","2","3");//向指定key中存放set集合
    • stringRedisTemplate.opsForSet().isMember("red_123", "1")//根據key查看集合中是否存在指定數據
    • stringRedisTemplate.opsForSet().members("red_123");//根據key獲取set集合
相關文章
相關標籤/搜索