日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

如何自定义Hibernate脏检查机制

發(fā)布時(shí)間:2023/12/3 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何自定义Hibernate脏检查机制 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

介紹

在上一篇文章中,我描述了Hibernate自動(dòng)臟檢查機(jī)制。 盡管您應(yīng)該始終喜歡它,但是有時(shí)您可能想添加自己的自定義污垢檢測(cè)策略。

自定義臟檢查策略

Hibernate提供以下定制機(jī)制:

  • 休眠攔截器#findDirty()
  • CustomEntityDirtinessStrategy

手動(dòng)檢查臟物

作為練習(xí),我將構(gòu)建一個(gè)手動(dòng)的臟檢查機(jī)制,以說明自定義更改檢測(cè)策略的難易程度:

自臟檢查實(shí)體

首先,我將定義一個(gè)DirtyAware接口,所有手動(dòng)臟檢查實(shí)體都必須實(shí)現(xiàn):

public interface DirtyAware {Set<String> getDirtyProperties();void clearDirtyProperties(); }

接下來,我將在基類中封裝當(dāng)前的臟檢查邏輯:

public abstract class SelfDirtyCheckingEntity implements DirtyAware {private final Map<String, String> setterToPropertyMap = new HashMap<String, String>();@Transientprivate Set<String> dirtyProperties = new LinkedHashSet<String>();public SelfDirtyCheckingEntity() {try {BeanInfo beanInfo = Introspector.getBeanInfo(getClass());PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();for (PropertyDescriptor descriptor : descriptors) {Method setter = descriptor.getWriteMethod();if (setter != null) {setterToPropertyMap.put(setter.getName(), descriptor.getName());}}} catch (IntrospectionException e) {throw new IllegalStateException(e);}}@Overridepublic Set<String> getDirtyProperties() {return dirtyProperties;}@Overridepublic void clearDirtyProperties() {dirtyProperties.clear();}protected void markDirtyProperty() {String methodName = Thread.currentThread().getStackTrace()[2].getMethodName();dirtyProperties.add(setterToPropertyMap.get(methodName));} }

所有手動(dòng)的臟檢查實(shí)體都必須擴(kuò)展此基類,并通過調(diào)用markDirtyProperty方法顯式標(biāo)記臟屬性。

實(shí)際的自臟檢查實(shí)體如下所示:

@Entity @Table(name = "ORDER_LINE") public class OrderLine extends SelfDirtyCheckingEntity {@Id@GeneratedValue(strategy = GenerationType.AUTO)private Long id;private Long number;private String orderedBy;private Date orderedOn;public Long getId() {return id;}public Long getNumber() {return number;}public void setNumber(Long number) {this.number = number;markDirtyProperty();}public String getOrderedBy() {return orderedBy;}public void setOrderedBy(String orderedBy) {this.orderedBy = orderedBy;markDirtyProperty();}public Date getOrderedOn() {return orderedOn;}public void setOrderedOn(Date orderedOn) {this.orderedOn = orderedOn;markDirtyProperty();} }

每當(dāng)調(diào)用setter時(shí),關(guān)聯(lián)的屬性就會(huì)變臟。 為簡(jiǎn)單起見,當(dāng)我們將屬性還原為其原始值時(shí),此簡(jiǎn)單練習(xí)不涵蓋用例。

臟檢查測(cè)試

為了測(cè)試自臟檢查機(jī)制,我將運(yùn)行以下測(cè)試用例:

@Test public void testDirtyChecking() {doInTransaction(new TransactionCallable<Void>() {@Overridepublic Void execute(Session session) {OrderLine orderLine = new OrderLine();session.persist(orderLine);session.flush();orderLine.setNumber(123L);orderLine.setOrderedBy("Vlad");orderLine.setOrderedOn(new Date());session.flush();orderLine.setOrderedBy("Alex");return null;}}); }

Hibernate攔截器解決方案

Hibernate Interceptor findDirty回調(diào)使我們能夠控制臟屬性發(fā)現(xiàn)過程。 該方法可能返回:

  • null ,將臟檢查委托給Hibernate默認(rèn)策略
  • 一個(gè)int []數(shù)組,其中包含修改后的屬性索引

我們的Hibernate臟檢查攔截器如下所示:

public class DirtyCheckingInterceptor extends EmptyInterceptor {@Overridepublic int[] findDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types) {if(entity instanceof DirtyAware) {DirtyAware dirtyAware = (DirtyAware) entity;Set<String> dirtyProperties = dirtyAware.getDirtyProperties();int[] dirtyPropertiesIndices = new int[dirtyProperties.size()];List<String> propertyNamesList = Arrays.asList(propertyNames);int i = 0;for(String dirtyProperty : dirtyProperties) {LOGGER.info("The {} property is dirty", dirtyProperty);dirtyPropertiesIndices[i++] = propertyNamesList.indexOf(dirtyProperty);}dirtyAware.clearDirtyProperties();return dirtyPropertiesIndices;}return super.findDirty(entity, id, currentState, previousState, propertyNames, types);}}

將此攔截器傳遞到當(dāng)前的SessionFactory配置時(shí),我們將獲得以下輸出:

INFO [main]: c.v.h.m.l.f.InterceptorDirtyCheckingTest - The number property is dirty INFO [main]: c.v.h.m.l.f.InterceptorDirtyCheckingTest - The orderedBy property is dirty INFO [main]: c.v.h.m.l.f.InterceptorDirtyCheckingTest - The orderedOn property is dirty DEBUG [main]: o.h.e.i.AbstractFlushingEventListener - Flushed: 0 insertions, 1 updates, 0 deletions to 1 objects DEBUG [main]: n.t.d.l.SLF4JQueryLoggingListener - Name: Time:1 Num:1 Query:{[update ORDER_LINE set number=?, orderedBy=?, orderedOn=? where id=?][123,Vlad,2014-08-20 07:35:05.649,1]} INFO [main]: c.v.h.m.l.f.InterceptorDirtyCheckingTest - The orderedBy property is dirty DEBUG [main]: o.h.e.i.AbstractFlushingEventListener - Flushed: 0 insertions, 1 updates, 0 deletions to 1 objects DEBUG [main]: n.t.d.l.SLF4JQueryLoggingListener - Name: Time:0 Num:1 Query:{[update ORDER_LINE set number=?, orderedBy=?, orderedOn=? where id=?][123,Alex,2014-08-20 07:35:05.649,1]}

手動(dòng)臟檢查機(jī)制已檢測(cè)到傳入更改,并將其傳播到刷新事件偵聽器。

鮮為人知的CustomEntityDirtinessStrategy

CustomEntityDirtinessStrategy是Hibernate API的新增功能,它使我們能夠提供特定于應(yīng)用程序的臟檢查機(jī)制。 該接口可以實(shí)現(xiàn)如下:

public static class EntityDirtinessStrategy implements CustomEntityDirtinessStrategy {@Overridepublic boolean canDirtyCheck(Object entity, EntityPersister persister, Session session) {return entity instanceof DirtyAware;}@Overridepublic boolean isDirty(Object entity, EntityPersister persister, Session session) {return !cast(entity).getDirtyProperties().isEmpty();}@Overridepublic void resetDirty(Object entity, EntityPersister persister, Session session) {cast(entity).clearDirtyProperties();}@Overridepublic void findDirty(Object entity, EntityPersister persister, Session session, DirtyCheckContext dirtyCheckContext) {final DirtyAware dirtyAware = cast(entity);dirtyCheckContext.doDirtyChecking(new AttributeChecker() {@Overridepublic boolean isDirty(AttributeInformation attributeInformation) {String propertyName = attributeInformation.getName();boolean dirty = dirtyAware.getDirtyProperties().contains( propertyName );if (dirty) {LOGGER.info("The {} property is dirty", propertyName);}return dirty;}});}private DirtyAware cast(Object entity) {return DirtyAware.class.cast(entity);}}

要注冊(cè)CustomEntityDirtinessStrategy實(shí)現(xiàn),我們必須設(shè)置以下Hibernate屬性:

properties.setProperty("hibernate.entity_dirtiness_strategy", EntityDirtinessStrategy.class.getName());

運(yùn)行我們的測(cè)試將產(chǎn)生以下輸出:

INFO [main]: c.v.h.m.l.f.CustomEntityDirtinessStrategyTest - The number property is dirty INFO [main]: c.v.h.m.l.f.CustomEntityDirtinessStrategyTest - The orderedBy property is dirty INFO [main]: c.v.h.m.l.f.CustomEntityDirtinessStrategyTest - The orderedOn property is dirty DEBUG [main]: o.h.e.i.AbstractFlushingEventListener - Flushed: 0 insertions, 1 updates, 0 deletions to 1 objects DEBUG [main]: n.t.d.l.SLF4JQueryLoggingListener - Name: Time:1 Num:1 Query:{[update ORDER_LINE set number=?, orderedBy=?, orderedOn=? where id=?][123,Vlad,2014-08-20 12:51:30.068,1]} INFO [main]: c.v.h.m.l.f.CustomEntityDirtinessStrategyTest - The orderedBy property is dirty DEBUG [main]: o.h.e.i.AbstractFlushingEventListener - Flushed: 0 insertions, 1 updates, 0 deletions to 1 objects DEBUG [main]: n.t.d.l.SLF4JQueryLoggingListener - Name: Time:0 Num:1 Query:{[update ORDER_LINE set number=?, orderedBy=?, orderedOn=? where id=?][123,Alex,2014-08-20 12:51:30.068,1]}

結(jié)論

盡管默認(rèn)的字段級(jí)檢查或字節(jié)碼檢測(cè)替代方法足以滿足大多數(shù)應(yīng)用程序的需求,但有時(shí)您還是需要獲得對(duì)變更檢測(cè)過程的控制權(quán)。 在長(zhǎng)期項(xiàng)目中,定制某些內(nèi)置機(jī)制以滿足特殊的服務(wù)質(zhì)量要求并不少見。 框架采用決定還應(yīng)該考慮框架的可擴(kuò)展性和定制支持。

  • 代碼可在GitHub上獲得 。

翻譯自: https://www.javacodegeeks.com/2014/09/how-to-customize-hibernate-dirty-checking-mechanism.html

總結(jié)

以上是生活随笔為你收集整理的如何自定义Hibernate脏检查机制的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。