(三)JPA

2022-09-25 06:02:27

(二)JPA 連線工廠、主鍵生成策略、DDL自動更新

建議在需要使用時,看看之前的文章,先把環境搭起來。

4、EntityManager

EntityManager 是完成持久化操作的核心物件。

EntityManager 物件在一組實體類與底層資料來源之間進行 O/R 對映的管理。它可以用來管理和更新 Entity Bean, 根椐主鍵查詢 Entity Bean, 還可以通過JPQL語句查詢實體。

上面測試程式碼中,已經使用過EntityManager完成持久化操作。

實體類的狀態:

新建狀態: 新建立的物件,尚未擁有永續性主鍵;

持久化狀態:已經擁有永續性主鍵並和持久化建立了上下文環境;

遊離狀態:擁有持久化主鍵,但是沒有與持久化建立上下文環境;

刪除狀態: 擁有持久化主鍵,已經和持久化建立上下文環境,但是從資料庫中刪除。

4.1 persist 增

persist (Object entity):用於將新建立的 Entity 納入到 EntityManager 的管理。該方法執行後,傳入 persist() 方法的 Entity 物件轉換成持久化狀態。

如果傳入 persist() 方法的 Entity 物件已經處於持久化狀態,則 persist() 方法什麼都不做。

如果對刪除狀態的 Entity 進行 persist() 操作,會轉換為持久化狀態。

如果對遊離狀態的實體執行 persist() 操作,可能會在 persist() 方法丟擲 EntityExistException(也有可能是在flush或事務提交後丟擲)。

測試程式碼:

   @Test
    public void testPersist() {
        // 獲取連線
        EntityManager entityManager = JPAEntityFactory.getEntityManager();
        // 開啟事務
        entityManager.getTransaction().begin();
        // 新建狀態範例 
        Course course = new Course();
        course.setCname("Spring程式設計實戰");
        course.setStart(DateUtil.stringToDate("2022-09-19"));
        course.setEnd(DateUtil.stringToDate("2022-12-30"));
        course.setCredit(2);
        course.setNum(88);
        // 對新建狀態 持久化
        entityManager.persist(course);
        // 提交事務
        entityManager.getTransaction().commit();
        // 關閉連線
        JPAEntityFactory.close();
    }
// 紀錄檔資訊
insert into course (cname, credit, end, num, start) values (?, ?, ?, ?, ?)

如果設定了id,就說明這是一個遊離狀態的實體類,執行會出現異常

4.2 merge 增\改

merge() 用於處理 Entity的同步。即資料庫的插入和更新操作。

測試程式碼: 傳入新建狀態的物件

    @Test
    public void testMerge() {
        // 獲取連線
        EntityManager entityManager = JPAEntityFactory.getEntityManager();
        // 開啟事務
        entityManager.getTransaction().begin();
        Course course = new Course();
        course.setCname("Spring程式設計實戰");
        course.setStart(DateUtil.stringToDate("2022-09-19"));
        course.setEnd(DateUtil.stringToDate("2022-12-30"));
        course.setCredit(2);
        course.setNum(88);
        // 對新建狀態 持久化
        entityManager.merge(course);
        // 提交事務
        entityManager.getTransaction().commit();
        // 關閉連線
        JPAEntityFactory.close();
    }

檢視紀錄檔,可以看到,執行的是插入操作。

insert into course (cname, credit, end, num, start) values (?, ?, ?, ?, ?)

測試程式碼: 傳入遊離狀態物件

    @Test
    public void testMerge() {
        // 獲取連線
        EntityManager entityManager = JPAEntityFactory.getEntityManager();
        // 開啟事務
        entityManager.getTransaction().begin();
        Course course = new Course();
        course.setCid(2L);
        course.setCname("Spring程式設計實戰");
        course.setStart(DateUtil.stringToDate("2022-09-19"));
        course.setEnd(DateUtil.stringToDate("2022-12-30"));
        course.setCredit(2);
        course.setNum(88);
        // 對新建狀態 持久化
        entityManager.merge(course);
        // 提交事務
        entityManager.getTransaction().commit();
        // 關閉連線
        JPAEntityFactory.close();
    }

檢視紀錄檔,可以看到,執行的是Update語句

update course set cname=?,credit=?,end=?, num=?, start=? where cid=?

4.3 remove 刪

刪除範例。如果範例是被管理的,即與資料庫實體記錄關聯,則同時會刪除關聯的資料庫記錄。

注意:該方法只能移除持久化物件。

 @Test
    public void testRemove() {
        // 獲取連線
        EntityManager entityManager = JPAEntityFactory.getEntityManager();
        // 開啟事務
        entityManager.getTransaction().begin();
        // 查詢
        Course course = entityManager.find(Course.class, 2);
        // 對新建狀態 持久化
        entityManager.remove(course);
        // 提交事務
        entityManager.getTransaction().commit();
        // 關閉連線
        JPAEntityFactory.close();
    }

檢視紀錄檔,可以看到,執行的是Delete語句

delete from course where cid=?

4.4 find 查

find (Class<T> entityClass,Object primaryKey):返回指定的 OID 對應的實體類物件。

第一個引數為被查詢的實體類型別,第二個引數為待查詢實體的主鍵值。

如果這個實體存在於當前的持久化環境,則返回一個被快取的物件;否則會建立一個新的 Entity, 並載入資料庫中相關資訊;若 OID 不存在於資料庫中,則返回一個 null。

    @Test
    public void testFind() {
        // 獲取連線
        EntityManager entityManager = JPAEntityFactory.getEntityManager();
        // 開啟事務
        entityManager.getTransaction().begin();
        // 查詢主鍵為3L
        Course course = entityManager.find(Course.class, 3L);
        loggerFactory.info("【find查詢結果:】{}", course);
        // 提交事務
        entityManager.getTransaction().commit();
        // 關閉連線
        JPAEntityFactory.close();
    }

檢視紀錄檔資訊:【find查詢結果:】Course(cid=3, cname=Spring程式設計實戰, start=2022-09-19, end=2022-12-30, credit=2, num=88)

4.5 getReference

getReference (Class<T> entityClass,Object primaryKey):與find()方法類似。

不同的是:如果快取中不存在指定的 Entity, EntityManager 會建立一個 Entity 類的代理,但是不會立即載入資料庫中的資訊,只有第一次真正使用此 Entity 的屬性才載入,所以如果此 OID(主鍵) 在資料庫不存在,getReference() 不會返回 null 值, 而是丟擲EntityNotFoundException。

    @Test
    public void testGetReference() {
        // 獲取連線
        EntityManager entityManager = JPAEntityFactory.getEntityManager();
        // 開啟事務
        entityManager.getTransaction().begin();
        Course course = entityManager.getReference(Course.class, 3L);
        loggerFactory.info("【find查詢結果:】{}", course);
        // 提交事務
        entityManager.getTransaction().commit();
        // 關閉連線
        JPAEntityFactory.close();
    }

檢視紀錄檔資訊:【find查詢結果:】Course(cid=3, cname=Spring程式設計實戰, start=2022-09-19, end=2022-12-30, credit=2, num=88)

不存在,則會丟擲異常: