序
hibernate的envers模塊提供了一整套機(jī)制可以用來記錄數(shù)據(jù)的變更仰剿。這里簡單介紹一下全陨。
1.自動(dòng)配置
@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模塊。
2.Audited注解
@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標(biāo)注一下這個(gè)實(shí)體類需要審計(jì)甚颂。
繼承RevisionRepository
public interface BookDao extends RevisionRepository<Book, Long, Integer>,JpaRepository<Book, Long> {
}
通過繼承RevisionRepository獲取查找revisions的查詢方法蜜猾,主要如下:
@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是指變更版本號(hào)的類型,一般Integer夠用振诬,如果覺得不夠用可以改為Long類型蹭睡。這里的T就是實(shí)體類。ID就是實(shí)體類的主鍵類型贷揽。
查詢變更
經(jīng)過以上配置之后棠笑,就可以正常記錄變更的每個(gè)版本了,可以通過如下方法來查詢禽绪,比如:
Revisions<Integer,Book> revision = bookDao.findRevisions(id);
List<Revision<Integer,Book>> data = revision.getContent();
這里的id為實(shí)體的id
revision的表結(jié)構(gòu)
hibernate默認(rèn)以實(shí)體類后綴_AUD來記錄每個(gè)變更的版本蓖救,比如
-- ----------------------------
-- 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的屬性進(jìn)行配置。里頭的rev字段表示revision的版本號(hào)循捺,一般全局遞增斩例。revtype字段表示操作類型,0表示新增从橘,1表示更新念赶,2表示刪除。
另外還有一個(gè)表是revinfo恰力,記錄每個(gè)變更的版本號(hào)和時(shí)間:
-- ----------------------------
-- 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;
自定義revision entity
如果默認(rèn)的envers的實(shí)現(xiàn)不滿足你的要求的話叉谜,使用@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() );
}
}
具體的這里就不細(xì)講了,具體可以參考hibernate香府。