Envers, entity’lerinizi versiyonlamak için kullanılan Hibernate modülüdür. Hibernate 3.5 ile beraber core modüller arasına girmiştir. Hibernate ve JPA ile beraber kullanabileceğiniz gibi Envers’ı tek başına da kullanabilirsiniz.
Neden?
Projelerimizde bazı durumlarda kayıtlarımızı log’lama gereği duyuyoruz. Bunun sebebi ise önceki kaydın hangi durumda olduğunu bilmek istiyoruz. Bunlar için log tabloları oluşturup hangi durumda(Insert, Update, Delete) değişikliğe uğradığını ve eski halini bu tablolara kaydediyoruz.
Bu sorunu çözmek için Hibernate bizler Envers’ı sunuyor. Loglamak istediğiniz kayıtları belirtmeniz yeterli.
Nasıl?
Maven projemize Envers’ı dependency olarak ekliyoruz. Bunun yanında ben MySql kullanacağım ve veritabanı işlemlerini Hibernate üzerinden yacağım için onları da ekliyorum.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<!-- HIBERNATE --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.4.3.Final</version> </dependency> <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-envers --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-envers</artifactId> <version>5.4.3.Final</version> </dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> artifactId>mysql-connector-java</artifactId> <version>5.1.22</version> </dependency> |
Bazı Envers annotations’ları;
- @Audited: class ve class properities için kullanılabilir. Class için kullandığınızda sahip olduğu bütün field’ları versiyonlayacaktır.
- @NotAudited: eğer bütün field’lara ihtiyacınız yoksa çıkarabilirsiniz.
- @AuditTable: Hibernate default olarak tablo ismini versiyonlanacak entity ismininin sonuna “_AUD” koyarak isimlendirir. Ancak bu annotations ile kendi tablo isminizi verebilirsiniz.
REVTYPE: Yapılan değişikliğin hangi tipte olduğunu belirtir.
- 0 Insert
- 1 Update
- 2 Delete
Uygula
User objemiz üzerinde yapacağımız değişiklikleri gözlemleyelim.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
@Entity @Audited @AuditTable(value = "User_Audited") public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Integer id; private String name; private String surname; private String email; @NotAudited private String phone; public User() { super(); } public User(String name, String surname, String email, String phone) { super(); this.name = name; this.surname = surname; this.email = email; this.phone = phone; } //getter ve setter metodlar } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public class App { public static void main(String[] args) { UserDao dao = new UserDao(); dao.saveOrUpdateUser(user); dao.saveOrUpdateUser(user); user.setName("CEM"); user.setSurname("DIRMAN"); dao.saveOrUpdateUser(user); dao.deleteUser(user); } } |
NOT: Dao katmanı bu konunun dışında olduğu için ve yazıyı gereksiz uzatmaması için buraya eklenmemiştir. Fakat projenin Github adresi üzerinden ulaşabilirsiniz.
Şimdi tablolarımızın durumuna göz atalım. Hibernate ve Envers bizim adımıza aşağıdaki dört tabloyu oluşturdu.
- User Tablosu: Entity’i saklayan tablo fakat en son yaptığımız işlem silme olduğu için tablonun son hali boş olacaktır.
- REVINFO: Kodu incelediğimizde toplamda dört işlem yaptığımızı görüyoruz bunlar sırasıyla; insert-update-update-delete. Sonuç olarak REVINFO tablomuzda bu işlemleri timestamp değerleriyle birlikte görebiliriz.
- User_Audited: User class’ımızı incelediğimizde tablonun default ismini değiştirdiğimizi göreceğiz. Bunun yanında yaptığımız değişiklikler ve REVTYPE(değişiklik tipi) görebiliyoruz.
- Son kayıda dikkat edersek REVTYPE = 2 yani kayıdın silindiğini belirtiyor.
- Kayıtlara dikkat edersek User’ın ‘phone‘ bilgisinin versiyonlamayacağını belirtmiştik ve Envers bunu değeri versiyonlamadı.
Projeye buradan ulaşabilirsiniz.
Kaynak;