2023年4月17日 星期一

Hibernate 有註記 @Audit 的 Entity,如何處理版本

在不考慮直接寫 query 的情況下,Hibernate entity 可以用 Hibernate ORM Hibernate Envers 底下的 code 來處理

抓取特定版本的eneity

Hibernate Envers 已經提供好 code 來抓取 entity 版本了

例如要抓取特定版本的eneity:

import org.hibernate.envers.*;
import org.hibernate.envers.query.*;

@Service
public class MyServiceImpl implements MyService{
	@Autowired
	private EntityManagerFactory entityManagerFactory;


	public List<Number> getAllRevision(String id){
		EntityManager em = entityManagerFactory.createEntityManager();

		EntityTransaction etx = em.getTransaction();
		etx.begin();
		AuditReader reader = AuditReaderFactory.get(em);
		List<Number> revs = reader.getRevisions(MyEntity.class, id);
		
		em.close();
		return revs;
	}
}

AuditReaderFactory.get(); 可以是 org.hibernate.Session 或是 javax.persistence.EntityManager ,推薦使用 EntityManager。

這段 code 中,之所以不 @Autowired EntityManager ,而是 @Autowired EntityManagerFactory,是因為自動注入的 EntityManager他的 connection 是關閉的

所以才選擇用 factory 建立新的 EntityManager。

抓取Entity所有歷史版本

要抓取所有歷史版本可以這樣寫

AuditReader reader = AuditReaderFactory.get(em);
AuditQuery query = reader.createQuery()
	.forRevisionsOfEntity(MyEntity.class, true, false)
	.add(AuditEntity.id().eq(entityID));
List<?> result = query.getResultList();

forRevisionsOfEntity 的後面兩個參數分別是

  • 是否只抓 entity
  • 是否抓取「刪除」紀錄

如果第二個參數為 true;則 result 會是 List<MyEntity>類型。

如果不是,那他會是 List<Object[]>。 Array 的 length 為 3,分別是

  1. Entity
  2. org.hibernate.envers.DefaultRevisionEntity
  3. org.hibernate.envers.RevisionType
可以從 DefaultRevisionEntity 那取得版本號與日期;RevisionType則是記錄該版本的動作類型。

注意事項

  1. 上述範例我都沒有撰寫 try / catch ,實際上建議還是要寫。
  2. 不知為何,我用 java 1.8 compile 的時候,都會說 DefaultRevisionEntity 不存在(我用的 hibernate 版本是 5.4.25.Final )

參考資料

Envers - Hibernate ORM. Hibernate. https://hibernate.org/orm/envers/
良葛格, (N.d). 使用 EntityManager. Openhome. https://openhome.cc/Gossip/EJB3Gossip/EntityManager.html
Example usage for org.hibernate.envers AuditReaderFactory get. Java2s. http://www.java2s.com/example/java-api/org/hibernate/envers/auditreaderfactory/get-1-2.html

沒有留言:

張貼留言