定制企业网站建设制作,wordpress怎么写html,做网站私活,电销系统线路介绍 在上一篇文章中#xff0c;我描述了Hibernate自动脏检查机制。 尽管您应该始终喜欢它#xff0c;但是有时您可能想添加自己的自定义污垢检测策略。 自定义脏检查策略 Hibernate提供以下定制机制#xff1a; 休眠拦截器#findDirty#xff08;#xff09; CustomEnt… 介绍 在上一篇文章中我描述了Hibernate自动脏检查机制。 尽管您应该始终喜欢它但是有时您可能想添加自己的自定义污垢检测策略。 自定义脏检查策略 Hibernate提供以下定制机制 休眠拦截器#findDirty CustomEntityDirtinessStrategy 手动检查脏物 作为练习我将构建一个手动的脏检查机制以说明自定义更改检测策略的难易程度 自脏检查实体 首先我将定义一个DirtyAware接口所有手动脏检查实体都必须实现 public interface DirtyAware {SetString getDirtyProperties();void clearDirtyProperties();
} 接下来我将在基类中封装当前的脏检查逻辑 public abstract class SelfDirtyCheckingEntity implements DirtyAware {private final MapString, String setterToPropertyMap new HashMapString, String();Transientprivate SetString dirtyProperties new LinkedHashSetString();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 SetString getDirtyProperties() {return dirtyProperties;}Overridepublic void clearDirtyProperties() {dirtyProperties.clear();}protected void markDirtyProperty() {String methodName Thread.currentThread().getStackTrace()[2].getMethodName();dirtyProperties.add(setterToPropertyMap.get(methodName));}
} 所有手动的脏检查实体都必须扩展此基类并通过调用markDirtyProperty方法显式标记脏属性。 实际的自脏检查实体如下所示 Entity
Table(name ORDER_LINE)
public class OrderLine extends SelfDirtyCheckingEntity {IdGeneratedValue(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();}
} 每当调用setter时关联的属性就会变脏。 为简单起见当我们将属性还原为其原始值时此简单练习不涵盖用例。 脏检查测试 为了测试自脏检查机制我将运行以下测试用例 Test
public void testDirtyChecking() {doInTransaction(new TransactionCallableVoid() {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回调使我们能够控制脏属性发现过程。 该方法可能返回 null 将脏检查委托给Hibernate默认策略 一个int []数组其中包含修改后的属性索引 我们的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;SetString dirtyProperties dirtyAware.getDirtyProperties();int[] dirtyPropertiesIndices new int[dirtyProperties.size()];ListString 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);}} 将此拦截器传递到当前的SessionFactory配置时我们将获得以下输出 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]} 手动脏检查机制已检测到传入更改并将其传播到刷新事件侦听器。 鲜为人知的CustomEntityDirtinessStrategy CustomEntityDirtinessStrategy是Hibernate API的新增功能它使我们能够提供特定于应用程序的脏检查机制。 该接口可以实现如下 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);}} 要注册CustomEntityDirtinessStrategy实现我们必须设置以下Hibernate属性 properties.setProperty(hibernate.entity_dirtiness_strategy, EntityDirtinessStrategy.class.getName()); 运行我们的测试将产生以下输出 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]}结论 尽管默认的字段级检查或字节码检测替代方法足以满足大多数应用程序的需求但有时您还是需要获得对变更检测过程的控制权。 在长期项目中定制某些内置机制以满足特殊的服务质量要求并不少见。 框架采用决定还应该考虑框架的可扩展性和定制支持。 代码可在GitHub上获得 。 翻译自: https://www.javacodegeeks.com/2014/09/how-to-customize-hibernate-dirty-checking-mechanism.html