jpa的使用

本文章只是自己在學(xué)習(xí)中記的筆記(可能有點(diǎn)亂),只提供參考。如有錯(cuò)誤請(qǐng)指出

什么是jpa

JPA (Java Persistence API)Java持久化API。是一套Sun公司Java官方制定的ORM方案,是規(guī)范,是標(biāo)準(zhǔn) ,sun公司自己并沒(méi)有實(shí)現(xiàn)

  • ORM是什么

    ? 對(duì)象關(guān)系映射,ORM是一個(gè)實(shí)現(xiàn)使用對(duì)象操作數(shù)據(jù)庫(kù)的設(shè)計(jì)思想,主要目的是操作實(shí)體類就相當(dāng)于操作數(shù)據(jù)庫(kù)。不再重點(diǎn)關(guān)注sql語(yǔ)句。

  • JPA的實(shí)現(xiàn)者

    JPA只是是一套標(biāo)準(zhǔn)。它只是一套實(shí)現(xiàn)ORM理論的接口。沒(méi)有實(shí)現(xiàn)的代碼。那么我們必須要有具體的實(shí)現(xiàn)者才可以完成ORM操作功能的實(shí)現(xiàn)!

    市場(chǎng)上的主流的JPA框架(實(shí)現(xiàn)者)有:

    • Hibernate (JBoos)
    • EclipseTop(Eclipse社區(qū))
    • OpenJPA (Apache基金會(huì))

Hibernate實(shí)現(xiàn)

hibernate是一個(gè)開(kāi)放源碼的對(duì)象關(guān)系映射框架

  1. 它對(duì)jdbc進(jìn)行了非常輕量級(jí)的對(duì)象封裝。

  2. 它將實(shí)體類與數(shù)據(jù)庫(kù)表建立映射關(guān)系,是一個(gè)全自動(dòng)的orm框架。

案例說(shuō)明

對(duì)用戶的增刪改查操作

  • 項(xiàng)目搭建

    導(dǎo)入對(duì)應(yīng)的maven坐標(biāo)

    <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-entitymanager -->
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-entitymanager</artifactId>
                <version>5.4.10.Final</version>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-c3p0 -->
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-c3p0</artifactId>
                <version>5.4.10.Final</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.19</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/log4j/log4j -->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.17</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.12</version>
                <scope>provided</scope>
            </dependency>
    
  • 配置相關(guān)的jpa配置文件

    1. 配置文件在類路徑下的一個(gè)叫META-INF的文件下。

    2. 它的文件命名也有要求。叫persistence.xml

      <?xml version="1.0" encoding="UTF-8"?>
      <persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
          <!--  持久化單元,name 持久化單元名稱  transaction-type事務(wù)管理的方式
                  RESOURCE_LOCAL: 本地事務(wù)管理
                  JPA:分布式事務(wù)管理
          -->
          <persistence-unit name="myJpa" transaction-type="RESOURCE_LOCAL">
              <!--  jpa的實(shí)現(xiàn)方式  -->
              <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
              <!-- <class>com.wlm.pojo.Customer</class>-->
              <!--  數(shù)據(jù)庫(kù)信息  -->
              <properties>
                  <property name="javax.persistence.jdbc.user" value="root"/>
                  <property name="javax.persistence.jdbc.password" value="123"/>
                  <property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
                  <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/website?serverTimezone=UTC&amp;useUnicod=true&amp;characterEncoding=utf-8"/>
      
                  <!--    可配置,配置jpa實(shí)現(xiàn)放的配置信息,也就是hibernate
                         顯示sql
                         自動(dòng)創(chuàng)建數(shù)據(jù)庫(kù)表:
                              create:程序運(yùn)行時(shí)創(chuàng)建數(shù)據(jù)庫(kù)表(如果有表,先刪除再創(chuàng)建)
                              ipdate:程序運(yùn)行時(shí)再創(chuàng)建表(如果有表不會(huì)創(chuàng)建)
                              none:不會(huì)創(chuàng)建表
                 -->
                  <property name="hibernate.show_sql" value="true"/><!--  顯示sql-->
                  <property name="hibernate.hbm2ddl.auto" value="update"/><!--自動(dòng)創(chuàng)建數(shù)據(jù)庫(kù)表-->
      <!--            <property name = "hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />&lt;!&ndash;方言&ndash;&gt;-->
              </properties>
          </persistence-unit>
      </persistence>
      
      • <persistence-unit name="myJpa" transaction-type="RESOURCE_LOCAL">配置持久化數(shù)據(jù)單元。

        1. name是 持久化單元名稱,名稱可以隨便寫(xiě),后面我們?cè)诔绦蛑芯褪歉哌@名稱獲取對(duì)象。
        2. transaction-type事務(wù)管理的方式,它有2個(gè)選項(xiàng):
        • RESOURCE_LOCAL: 本地事務(wù)管理。
        • JPA: 分布式事務(wù)管理。
      • <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>jpa的實(shí)現(xiàn)方式。因?yàn)閖pa是接口,是規(guī)范,它沒(méi)有對(duì)數(shù)據(jù)庫(kù)的操作的實(shí)現(xiàn)。所以我們還要選擇是那種方法實(shí)現(xiàn)jpa操作。這里是選用了hibernate方式。

      • <properties>里配置的是數(shù)據(jù)庫(kù)信息。

        注意:其中數(shù)據(jù)庫(kù)的信息字段,都要以javax.persistence.jdbc.開(kāi)頭。

   再后面2個(gè)屬性,可配可不配,它是配置jpa實(shí)現(xiàn)放的配置信息,也就是hibernate。

   重點(diǎn)說(shuō)下`hibernate.hbm2ddl.auto`,自動(dòng)創(chuàng)建數(shù)據(jù)庫(kù)表。它有3個(gè)可選對(duì)象。

   - create:程序運(yùn)行時(shí)創(chuàng)建數(shù)據(jù)庫(kù)表(如果有表,先刪除再創(chuàng)建)
   - update:程序運(yùn)行時(shí)再創(chuàng)建表(如果有表不會(huì)創(chuàng)建)
   - none:不會(huì)創(chuàng)建表。
  • 創(chuàng)建實(shí)體類

    @AllArgsConstructor
    @NoArgsConstructor
    @Setter
    @Getter
    @ToString
    //--------上面是lombok的注解--------
    @Entity
    @Table(name="User")
    public class User {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "id")
        private Integer id;
        private String name;
        private String pwd;
        @Column(name = "create_time")
        private Date createTime;
    
    }
    

    注意:上面我用到了lombok。還有,所有的非lombok注解都是javax.persistence.*里的

    上面的注解是配置映射關(guān)系。映射關(guān)系的配置有兩個(gè)方向:

    • 實(shí)體類和表的映射:
      1. @Entity:聲明此類是一個(gè)實(shí)體類。
      2. @Table(name="User"):對(duì)應(yīng)的是數(shù)據(jù)庫(kù)中的表。name就是數(shù)據(jù)庫(kù)中的表名
    • 實(shí)例類中屬性和表中的字段映射:
      1. @Id:主鍵。
      2. @GeneratedValue(strategy = GenerationType.IDENTITY):定義的主鍵生成策略,其中有:
        • GenerationType.IDENTITY:自增。底層數(shù)據(jù)庫(kù)必須支持自增才可以使用。像mysql。
        • GenerationType.SEQUENCE:序列。底層數(shù)據(jù)庫(kù)必須支持序列才可以使用,像orac就支持,mysql不支持
        • GenerationType.TABLE:jpa提供的一種機(jī)制,它通過(guò)一張表的形式完成自增操作。(會(huì)在數(shù)據(jù)庫(kù)中創(chuàng)建一張表),通過(guò)這張表來(lái)維護(hù)自增
        • GenerationType.AUTO:程序自動(dòng)的選擇主鍵策略。根據(jù)自己的表或運(yùn)行環(huán)境選擇上面三種策略。
      3. @Column(name = "id"):表中的字段映射,name,數(shù)據(jù)庫(kù)中對(duì)應(yīng)的字段名。
  • api操作

    • 增加操作

          @Test
          public void test() {
              //1.加載配置文件創(chuàng)建工廠(實(shí)體管理類工廠)對(duì)象,傳入的是持久化數(shù)據(jù)單元,也就是配置文件里我們配置的數(shù)據(jù)單元。
              EntityManagerFactory jpa = Persistence.createEntityManagerFactory("myJpa");
      
              //2.通過(guò)工廠獲取實(shí)體管理器
              EntityManager manager = jpa.createEntityManager();
      
              //獲取事務(wù)對(duì)象
              EntityTransaction tx = manager.getTransaction();
              tx.begin();//開(kāi)啟事務(wù)
              //完成增刪改查
              User User = new User();
              user.setName("nihao");
              user.setPwd("123");
              user.setCreateTime(new Date());
      
              //保存
              manager.persist(user);//保存操作
      
              //提交事務(wù)
              tx.commit();
      
              //關(guān)閉資源
              manager.close();
              jpa.close();
          }
      
  • 根據(jù)id查詢用戶

    引入一個(gè)概念,上面頻繁通過(guò)工廠獲取實(shí)體管理器,是一個(gè)比較耗資源和耗時(shí)的操作。所以我們可以把它放到一個(gè)靜態(tài)代碼塊中,封裝成一個(gè)工具類來(lái)獲取,解決耗資源和耗時(shí)問(wèn)題

    public class JpaUtils {
        private static EntityManagerFactory factory;
    
        static {
            factory = Persistence.createEntityManagerFactory("myJpa");
        }
    
        /*獲取實(shí)體類管理器對(duì)象*/
        public static EntityManager getEntityManager(){
            return factory.createEntityManager();
        }
    
    }
    

    那么我們根據(jù)id查詢代碼實(shí)現(xiàn):

     @Test
        public void test2() {
            //獲取EntityManager對(duì)象
            EntityManager entityManager = JpaUtils.getEntityManager();
            //查詢不需要事務(wù),所以不用開(kāi)啟事務(wù)。
            //根據(jù)id查詢操作
            /*
             * 要傳入2個(gè)參數(shù)
             * class:查詢數(shù)據(jù)的結(jié)果需要包裝的實(shí)體類型的字節(jié)碼
             * id:查詢的主鍵的信息
             * */
    //        User user = entityManager.find(User.class, 1);//查詢的第一種方法find();
            User user = entityManager.getReference(User.class, 1);//第二種方法。參數(shù)代表的類型都一樣。
            /*
             * 這2種方法的區(qū)別有什么不一樣?
             * find():查詢的對(duì)象就是當(dāng)前Userr本身。再調(diào)用的時(shí)候,sql發(fā)送的時(shí)機(jī)是立刻去數(shù)據(jù)庫(kù)查詢
             * getReference():查詢的對(duì)象是一個(gè)代理類對(duì)象。sql發(fā)送的時(shí)機(jī)是什么時(shí)候調(diào)用,就什么時(shí)候發(fā)送。
             * 一般是使用getReference(),延遲加載方式。
             * */
            System.out.println(user);
            //釋放EntityManager資源
            entityManager.close();
    
        }
    

    其中entityManager.findentityManager.getReference的作用和結(jié)果都是一樣的。為啥要定義兩個(gè)方法?

    • find():查詢的對(duì)象就是當(dāng)前User本身。再調(diào)用的時(shí)候,sql發(fā)送的時(shí)機(jī)是立刻去數(shù)據(jù)庫(kù)查詢
    • getReference():查詢的對(duì)象是一個(gè)代理類對(duì)象。sql發(fā)送的時(shí)機(jī)是什么時(shí)候調(diào)用,就什么時(shí)候發(fā)送。(延遲加載)

    我們一般是使用getReference(),延遲加載方式來(lái)使用。

  • 刪除客戶的操作

      @Test
        public void testRemove() {
            EntityManager entityManager = JpaUtils.getEntityManager();
            //開(kāi)啟事務(wù)
            EntityTransaction tx = entityManager.getTransaction();
            tx.begin();//開(kāi)啟事務(wù)的操作
            //刪除操作
            // 操作步驟
            /*
             * 1,先根據(jù)id查詢到用戶
             * 2,傳入查詢到的用戶進(jìn)行刪除
             * */
            User User = entityManager.getReference(User.class, 2);
            entityManager.remove(User);
            tx.commit();
            entityManager.close();
        }
    
  • 更新操作

     @Test
        public void testUpdate() {
            EntityManager entityManager = JpaUtils.getEntityManager();
    
            EntityTransaction tx = entityManager.getTransaction();
            tx.begin();
    
            User User = entityManager.getReference(User.class, 2);
            User.setName("我我我我");
    
            //更新操作
            entityManager.merge(User);
            tx.commit();
            entityManager.close();
        }
    

    如果實(shí)體類中有寫(xiě)屬性沒(méi)值,那么更新操作后數(shù)據(jù)庫(kù)那些字段也會(huì)沒(méi)值。

  • 查詢所有的操作

    @Test
        public void testFindAll() {
            EntityManager entityManager = JpaUtils.getEntityManager();
    
            //查詢?nèi)縥qpl
            /*
             * jqpl:form User
             * sql:select * from User
             * */
            String jpql = "from User";
            Query query = entityManager.createQuery(jpql);
            //發(fā)送查詢,并封裝結(jié)果集
            List<User> list = query.getResultList();
            for (User o : list) {
                System.out.println(o);
            }
    
            entityManager.close();
        }
    

    這里引入了一個(gè)jpql

    sql:是查詢表和表中的字段。

    jpql:是查詢的實(shí)體類和類中的屬性

    它們兩的語(yǔ)法相識(shí)。

    比如:

    jqpl:form User
    sql:select * from User
    
  • 倒序查詢?nèi)坑脩?,根?jù)id倒序

      EntityManager entityManager = JpaUtils.getEntityManager();
    
            String jpql = "from User order by id desc";
            Query query = entityManager.createQuery(jpql);
    
            List<User> resultList = query.getResultList();
    
            for (User User : resultList) {
                System.out.println(User);
            }
            entityManager.close();
    
  • 使用jpql查詢用戶的總數(shù)

    @Test
    public void testCount() {
        EntityManager entityManager = JpaUtils.getEntityManager();
        String jpql = "select count(id) from User ";
        Query query = entityManager.createQuery(jpql);
        Object singleResult = query.getSingleResult();//獲取一個(gè)結(jié)果的。
    
        System.out.println(singleResult);
        entityManager.close();
    }
    
  • 分頁(yè)查詢

    EntityManager entityManager = JpaUtils.getEntityManager();
            String jpql = "from User";
            //1.根據(jù)jpql創(chuàng)建query對(duì)象
            Query query = entityManager.createQuery(jpql);
            //2.對(duì)參數(shù)負(fù)賦值--分頁(yè)參數(shù)
            query.setFirstResult(4);//起始索引,從0開(kāi)始查,不包含0
            query.setMaxResults(2);//每頁(yè)查詢的條數(shù)
    
            List<User> resultList = query.getResultList();
    
            for (User User : resultList) {
                System.out.println(User);
            }
    
            entityManager.close();
    
  • 條件查詢

     @Test
        public void testLike() {
            EntityManager entityManager = JpaUtils.getEntityManager();
            String jpql = "from User where name like ?1";
            //1.根據(jù)jpql創(chuàng)建query對(duì)象
            Query query = entityManager.createQuery(jpql);
            /*
             * 第一個(gè)參數(shù)是占位符的位置,默認(rèn)是1開(kāi)始
             * 第二個(gè)是 取值
             * */
            query.setParameter(1, "ni%");
            List<User> resultList = query.getResultList();
    
            for (User User : resultList) {
                System.out.println(User);
            }
    
            entityManager.close();
        }
    

    String jpql = "from User where name like ?1"中,占位符后是hpa的樣式規(guī)定,有多個(gè)占位符,比如name like ?1 or pwd = ?2這樣寫(xiě),后面的數(shù)字是你設(shè)置占位符里的值的時(shí)候根據(jù)這數(shù)字去設(shè)置值。像query.setParameter(1, "ni%");

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 作者:鐘昕靈,叩丁狼教育高級(jí)講師。原創(chuàng)文章,轉(zhuǎn)載請(qǐng)注明出處。 JPA簡(jiǎn)介 JPA是Java Persistence...
    叩丁狼教育閱讀 4,720評(píng)論 1 5
  • [TOC] ORM思想 ORM全稱Object Relational Mapping,即對(duì)象關(guān)系映射,是一種程序設(shè)...
    風(fēng)少俠閱讀 7,814評(píng)論 0 0
  • 一 介紹 Java Persistence API:用于對(duì)象持久化的 APIJava EE 5.0 平臺(tái)標(biāo)準(zhǔn)的OR...
    guideEmotion閱讀 1,387評(píng)論 0 1
  • 金牛派閱讀 151評(píng)論 0 0
  • 再過(guò)五個(gè)月我將不再是二十歲了,我二十歲的光陰已經(jīng)過(guò)去了二百多天,這些日子很平靜、沒(méi)有什么波瀾,偶爾有些勉強(qiáng)算...
    何飛花閱讀 285評(píng)論 1 1

友情鏈接更多精彩內(nèi)容