jpa的使用

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

什么是jpa

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

  • ORM是什么

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

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

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

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

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

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

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

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

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

案例說明

對(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ù)庫信息  -->
              <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ù)庫表:
                              create:程序運(yùn)行時(shí)創(chuàng)建數(shù)據(jù)庫表(如果有表剪撬,先刪除再創(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ù)庫表-->
      <!--            <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是 持久化單元名稱悠反,名稱可以隨便寫残黑,后面我們?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ī)范,它沒有對(duì)數(shù)據(jù)庫的操作的實(shí)現(xiàn)笼恰。所以我們還要選擇是那種方法實(shí)現(xiàn)jpa操作踊沸。這里是選用了hibernate方式。

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

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

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

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

   - create:程序運(yùn)行時(shí)創(chuàng)建數(shù)據(jù)庫表(如果有表谬返,先刪除再創(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ù)庫中的表酿炸。name就是數(shù)據(jù)庫中的表名
    • 實(shí)例類中屬性和表中的字段映射:
      1. @Id:主鍵瘫絮。
      2. @GeneratedValue(strategy = GenerationType.IDENTITY):定義的主鍵生成策略,其中有:
        • GenerationType.IDENTITY:自增填硕。底層數(shù)據(jù)庫必須支持自增才可以使用麦萤。像mysql。
        • GenerationType.SEQUENCE:序列。底層數(shù)據(jù)庫必須支持序列才可以使用频鉴,像orac就支持栓辜,mysql不支持
        • GenerationType.TABLE:jpa提供的一種機(jī)制,它通過一張表的形式完成自增操作垛孔。(會(huì)在數(shù)據(jù)庫中創(chuàng)建一張表)藕甩,通過這張表來維護(hù)自增
        • GenerationType.AUTO:程序自動(dòng)的選擇主鍵策略。根據(jù)自己的表或運(yùn)行環(huán)境選擇上面三種策略周荐。
      3. @Column(name = "id"):表中的字段映射狭莱,name,數(shù)據(jù)庫中對(duì)應(yīng)的字段名概作。
  • api操作

    • 增加操作

          @Test
          public void test() {
              //1.加載配置文件創(chuàng)建工廠(實(shí)體管理類工廠)對(duì)象,傳入的是持久化數(shù)據(jù)單元腋妙,也就是配置文件里我們配置的數(shù)據(jù)單元。
              EntityManagerFactory jpa = Persistence.createEntityManagerFactory("myJpa");
      
              //2.通過工廠獲取實(shí)體管理器
              EntityManager manager = jpa.createEntityManager();
      
              //獲取事務(wù)對(duì)象
              EntityTransaction tx = manager.getTransaction();
              tx.begin();//開啟事務(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è)概念讯榕,上面頻繁通過工廠獲取實(shí)體管理器骤素,是一個(gè)比較耗資源和耗時(shí)的操作。所以我們可以把它放到一個(gè)靜態(tài)代碼塊中愚屁,封裝成一個(gè)工具類來獲取济竹,解決耗資源和耗時(shí)問題

    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ù),所以不用開啟事務(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ù)庫查詢
             * 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ù)庫查詢
    • getReference():查詢的對(duì)象是一個(gè)代理類對(duì)象鸵赫。sql發(fā)送的時(shí)機(jī)是什么時(shí)候調(diào)用,就什么時(shí)候發(fā)送躏升。(延遲加載)

    我們一般是使用getReference()辩棒,延遲加載方式來使用。

  • 刪除客戶的操作

      @Test
        public void testRemove() {
            EntityManager entityManager = JpaUtils.getEntityManager();
            //開啟事務(wù)
            EntityTransaction tx = entityManager.getTransaction();
            tx.begin();//開啟事務(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í)體類中有寫屬性沒值钻弄,那么更新操作后數(shù)據(jù)庫那些字段也會(huì)沒值。

  • 查詢所有的操作

    @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í)體類和類中的屬性

    它們兩的語法相識(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();
    }
    
  • 分頁查詢

    EntityManager entityManager = JpaUtils.getEntityManager();
            String jpql = "from User";
            //1.根據(jù)jpql創(chuàng)建query對(duì)象
            Query query = entityManager.createQuery(jpql);
            //2.對(duì)參數(shù)負(fù)賦值--分頁參數(shù)
            query.setFirstResult(4);//起始索引,從0開始查育八,不包含0
            query.setMaxResults(2);//每頁查詢的條數(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開始
             * 第二個(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這樣寫,后面的數(shù)字是你設(shè)置占位符里的值的時(shí)候根據(jù)這數(shù)字去設(shè)置值按声。像query.setParameter(1, "ni%");

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末劲妙,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子儒喊,更是在濱河造成了極大的恐慌镣奋,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,590評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件怀愧,死亡現(xiàn)場離奇詭異侨颈,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)芯义,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門哈垢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人扛拨,你說我怎么就攤上這事耘分。” “怎么了绑警?”我有些...
    開封第一講書人閱讀 169,301評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵求泰,是天一觀的道長。 經(jīng)常有香客問我计盒,道長渴频,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,078評(píng)論 1 300
  • 正文 為了忘掉前任北启,我火速辦了婚禮卜朗,結(jié)果婚禮上拔第,老公的妹妹穿的比我還像新娘。我一直安慰自己场钉,他們只是感情好蚊俺,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著逛万,像睡著了一般泳猬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上泣港,一...
    開封第一講書人閱讀 52,682評(píng)論 1 312
  • 那天暂殖,我揣著相機(jī)與錄音,去河邊找鬼当纱。 笑死呛每,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的坡氯。 我是一名探鬼主播晨横,決...
    沈念sama閱讀 41,155評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼箫柳!你這毒婦竟也來了手形?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,098評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤悯恍,失蹤者是張志新(化名)和其女友劉穎库糠,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體涮毫,經(jīng)...
    沈念sama閱讀 46,638評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瞬欧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了罢防。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片艘虎。...
    茶點(diǎn)故事閱讀 40,852評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖咒吐,靈堂內(nèi)的尸體忽然破棺而出野建,到底是詐尸還是另有隱情,我是刑警寧澤恬叹,帶...
    沈念sama閱讀 36,520評(píng)論 5 351
  • 正文 年R本政府宣布候生,位于F島的核電站,受9級(jí)特大地震影響妄呕,放射性物質(zhì)發(fā)生泄漏陶舞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評(píng)論 3 335
  • 文/蒙蒙 一绪励、第九天 我趴在偏房一處隱蔽的房頂上張望肿孵。 院中可真熱鬧,春花似錦疏魏、人聲如沸停做。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蛉腌。三九已至,卻和暖如春只厘,著一層夾襖步出監(jiān)牢的瞬間烙丛,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評(píng)論 1 274
  • 我被黑心中介騙來泰國打工羔味, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留河咽,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,279評(píng)論 3 379
  • 正文 我出身青樓赋元,卻偏偏與公主長得像忘蟹,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子搁凸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • 作者:鐘昕靈媚值,叩丁狼教育高級(jí)講師。原創(chuàng)文章护糖,轉(zhuǎn)載請(qǐng)注明出處褥芒。 JPA簡介 JPA是Java Persistence...
    叩丁狼教育閱讀 4,223評(píng)論 1 5
  • 轉(zhuǎn)自:jpa-內(nèi)心求法 JPA概要摘要:JPA定義了Java ORM及實(shí)體操作API的標(biāo)準(zhǔn)。本文摘錄了JPA的一些...
    誰在烽煙彼岸閱讀 1,173評(píng)論 0 4
  • [TOC] ORM思想 ORM全稱Object Relational Mapping嫡良,即對(duì)象關(guān)系映射锰扶,是一種程序設(shè)...
    風(fēng)少俠閱讀 7,541評(píng)論 0 0
  • 一 介紹 Java Persistence API:用于對(duì)象持久化的 APIJava EE 5.0 平臺(tái)標(biāo)準(zhǔn)的OR...
    guideEmotion閱讀 1,269評(píng)論 0 1
  • 金牛派閱讀 132評(píng)論 0 0