hibernate的envers模塊提供了一整套機制能夠用來記錄數據的變動。這裏簡單介紹一下。html
@SpringBootApplication @EnableJpaRepositories(repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean.class) @EnableJpaAuditing(auditorAwareRef = "auditorAwareImpl") public class EnversDemoApplication { public static void main(String[] args) { SpringApplication.run(EnversDemoApplication.class, args); } }
這裏配置@EnableJpaRepositories(repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean.class)表示開啓envers模塊。java
@Entity @Audited public class Book extends AuditableEntity{ @javax.persistence.Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String title; private String author; private String description; private long price; private boolean valid; // getter and setter }
使用@Audited標註一下這個實體類須要審計。ide
public interface BookDao extends RevisionRepository<Book, Long, Integer>,JpaRepository<Book, Long> { }
經過繼承RevisionRepository獲取查找revisions的查詢方法,主要以下:post
@NoRepositoryBean public interface RevisionRepository<T, ID extends Serializable, N extends Number & Comparable<N>> { Revision<N, T> findLastChangeRevision(ID var1); Revisions<N, T> findRevisions(ID var1); Page<Revision<N, T>> findRevisions(ID var1, Pageable var2); Revision<N, T> findRevision(ID var1, N var2); }
這裏的N是指變動版本號的類型,通常Integer夠用,若是以爲不夠用能夠改成Long類型。這裏的T就是實體類。ID就是實體類的主鍵類型。ui
通過以上配置以後,就能夠正常記錄變動的每一個版本了,能夠經過以下方法來查詢,好比:this
Revisions<Integer,Book> revision = bookDao.findRevisions(id); List<Revision<Integer,Book>> data = revision.getContent();
這裏的id爲實體的idhibernate
hibernate默認以實體類後綴_AUD來記錄每一個變動的版本,好比code
-- ---------------------------- -- Table structure for book_aud -- ---------------------------- DROP TABLE IF EXISTS "public"."book_aud"; CREATE TABLE "public"."book_aud" ( "id" int8 NOT NULL, "rev" int4 NOT NULL, "revtype" int2, "author" varchar(255) COLLATE "default", "description" varchar(255) COLLATE "default", "price" int8, "title" varchar(255) COLLATE "default", "valid" bool ) WITH (OIDS=FALSE); ALTER TABLE "public"."book_aud" OWNER TO "postgres"; -- ---------------------------- -- Primary key structure for table book_aud -- ---------------------------- ALTER TABLE "public"."book_aud" ADD PRIMARY KEY ("id", "rev") NOT DEFERRABLE INITIALLY IMMEDIATE; -- ---------------------------- -- Foreign keys structure for table book_aud -- ---------------------------- ALTER TABLE "public"."book_aud" ADD CONSTRAINT "fk2u9iq76nh69r6f989ae7xft9" FOREIGN KEY ("rev") REFERENCES "public"."revinfo" ("rev") ON UPDATE NO ACTION ON DELETE NO ACTION NOT DEFERRABLE INITIALLY IMMEDIATE;
若是想改表後綴的話,能夠經過org.hibernate.envers.audit_table_suffix的屬性進行配置。裏頭的rev字段表示revision的版本號,通常全局遞增。revtype字段表示操做類型,0表示新增,1表示更新,2表示刪除。orm
另外還有一個表是revinfo,記錄每一個變動的版本號和時間:htm
-- ---------------------------- -- Table structure for revinfo -- ---------------------------- DROP TABLE IF EXISTS "public"."revinfo"; CREATE TABLE "public"."revinfo" ( "rev" int4 NOT NULL, "revtstmp" int8 ) WITH (OIDS=FALSE); ALTER TABLE "public"."revinfo" OWNER TO "postgres"; -- ---------------------------- -- Primary key structure for table revinfo -- ---------------------------- ALTER TABLE "public"."revinfo" ADD PRIMARY KEY ("rev") NOT DEFERRABLE INITIALLY IMMEDIATE;
若是默認的envers的實現不知足你的要求的話,使用@RevisionEntity註解,替換@Audited,而後自定義listener,好比
@Entity @RevisionEntity( ExampleListener.class ) public class ExampleRevEntity extends DefaultRevisionEntity { private String username; public String getUsername() { return username; } public void setUsername( String username ) { this.username = username; } } public class ExampleListener implements RevisionListener { public void newRevision( Object revisionEntity ) { ExampleRevEntity exampleRevEntity = ( ExampleRevEntity ) revisionEntity; Identity identity = (Identity) Component.getInstance( "org.jboss.seam.security.identity" ); exampleRevEntity.setUsername( identity.getUsername() ); } }
具體的這裏就不細講了,具體能夠參考hibernate。