
ars.database.spring.HibernateDatabaseConfiguration Maven / Gradle / Ivy
The newest version!
package ars.database.spring;
import java.util.Set;
import java.util.Map;
import java.util.List;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Collection;
import java.util.LinkedList;
import java.util.Collections;
import java.lang.reflect.Modifier;
import org.hibernate.Hibernate;
import org.hibernate.type.Type;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.mapping.Column;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.LoadEventListener;
import org.hibernate.event.spi.LockEventListener;
import org.hibernate.event.spi.MergeEventListener;
import org.hibernate.event.spi.EvictEventListener;
import org.hibernate.event.spi.FlushEventListener;
import org.hibernate.event.spi.DeleteEventListener;
import org.hibernate.event.spi.PersistEventListener;
import org.hibernate.event.spi.RefreshEventListener;
import org.hibernate.event.spi.PreLoadEventListener;
import org.hibernate.event.spi.PostLoadEventListener;
import org.hibernate.event.spi.AutoFlushEventListener;
import org.hibernate.event.spi.PreUpdateEventListener;
import org.hibernate.event.spi.PreDeleteEventListener;
import org.hibernate.event.spi.PreInsertEventListener;
import org.hibernate.event.spi.ReplicateEventListener;
import org.hibernate.event.spi.DirtyCheckEventListener;
import org.hibernate.event.spi.PostUpdateEventListener;
import org.hibernate.event.spi.PostDeleteEventListener;
import org.hibernate.event.spi.PostInsertEventListener;
import org.hibernate.event.spi.FlushEntityEventListener;
import org.hibernate.event.spi.SaveOrUpdateEventListener;
import org.hibernate.event.spi.InitializeCollectionEventListener;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.springframework.beans.BeansException;
import org.springframework.aop.support.AopUtils;
import org.springframework.aop.framework.Advised;
import org.springframework.context.ApplicationContext;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import ars.util.Beans;
import ars.util.Trees;
import ars.util.Strings;
import ars.util.ObjectAdapter;
import ars.util.Conditions.Or;
import ars.util.Conditions.Match;
import ars.database.model.TreeModel;
import ars.database.hibernate.Hibernates;
import ars.database.hibernate.HibernateSimpleRepository;
import ars.database.repository.Repository;
import ars.database.repository.Repositories;
import ars.database.repository.DataConstraintException;
import ars.database.service.event.DeleteEvent;
import ars.database.service.event.InitEvent;
import ars.database.service.event.ServiceEvent;
import ars.database.service.event.ServiceListener;
import ars.database.spring.DatabaseConfiguration;
import ars.invoke.request.ParameterInvalidException;
/**
* 基于Hibernate数据操作配置
*
* @author wuyongqiang
*/
public class HibernateDatabaseConfiguration extends DatabaseConfiguration implements ObjectAdapter,
ServiceListener {
private static Map, List> VALIDATE_MODEL_PROPERTY_MAPPING = new HashMap, List>(); // 数据模型/属性映射
private static Map, Map, List>> VALIDATE_MODEL_RELATE_MAPPING = new HashMap, Map, List>>(); // 数据模型关联属性映射
private String validate; // 数据验证模型
public String getValidate() {
return validate;
}
public void setValidate(String validate) {
this.validate = validate;
}
/**
* 对象实体属性值有效性验证
*
* @param event 初始化事件对象
*/
protected void validation(InitEvent event) {
Object entity = event.getEntity();
Class> model = event.getService().getModel();
while (true) {
Class> superclass = model.getSuperclass();
if (superclass != Object.class && !Modifier.isAbstract(superclass.getModifiers())
&& VALIDATE_MODEL_PROPERTY_MAPPING.containsKey(superclass)) {
model = superclass;
continue;
}
break;
}
Repository> repository = Repositories.getRepository(model);
List properties = VALIDATE_MODEL_PROPERTY_MAPPING.get(model);
if (properties == null) {
throw new RuntimeException("Unknown model:" + model.getName());
}
List uniques = new LinkedList();
for (Property property : properties) {
String name = property.getName();
Object value = Beans.getValue(entity, name);
Iterator> columnIterator = property.getColumnIterator();
if (columnIterator.hasNext()) {
Column column = (Column) columnIterator.next();
if (!column.isNullable() && Beans.isEmpty(value)) {
throw new ParameterInvalidException(name, "required");
} else if (column.isUnique() && !Beans.isEmpty(value)) {
uniques.add(new Match(name, value));
}
}
if (entity instanceof TreeModel && name.equals("parent") && Trees.isLoop((TreeModel>) entity)) {
throw new ParameterInvalidException(name, "dead cycle");
}
}
if (!uniques.isEmpty()) {
Object id = Beans.getValue(entity, repository.getPrimary());
Object exist = repository.query().ne(repository.getPrimary(), id)
.condition(new Or(uniques.toArray(new Match[0]))).single();
if (exist != null) {
for (Match match : uniques) {
if (Beans.isEqual(Beans.getValue(exist, match.getKey()), match.getValue())) {
throw new ParameterInvalidException(match.getKey(), "exist");
}
}
}
}
}
/**
* 对象实体删除验证
*
* @param event 删除事件对象
*/
protected void validation(DeleteEvent event) {
Object entity = event.getEntity();
Class> model = event.getService().getModel();
Map, List> relates = VALIDATE_MODEL_RELATE_MAPPING.get(model);
if (relates != null && !relates.isEmpty()) {
for (Entry, List> entry : relates.entrySet()) {
Class> foreignKeyClass = entry.getKey();
Repository> repository = Repositories.getRepository(foreignKeyClass);
for (Property property : entry.getValue()) {
if (TreeModel.class.isAssignableFrom(model) && model == foreignKeyClass
&& property.getName().equals("parent")) {
continue;
}
Object relate = repository.query().eq(property.getName(), entity).paging(1, 1).single();
if (relate != null) {
String message = new StringBuilder(event.getSource().format(foreignKeyClass.getName()))
.append('[').append(relate.toString()).append(']').toString();
throw new DataConstraintException(message);
}
}
}
}
}
/**
* 绑定持久化会话工厂实例
*
* @param applicationContext Spring上下文对象
*/
@SuppressWarnings("rawtypes")
protected void bindSessionFactory(ApplicationContext applicationContext) {
Collection sessionFactories = applicationContext.getBeansOfType(SessionFactory.class).values();
Map, SessionFactory> modelSessionFactoryMappings = new HashMap, SessionFactory>();
for (SessionFactory sessionFactory : sessionFactories) {
Collection classMetadatas = sessionFactory.getAllClassMetadata().values();
for (ClassMetadata classMetadata : classMetadatas) {
modelSessionFactoryMappings.put(classMetadata.getMappedClass(), sessionFactory);
}
}
// 绑定数据持久化对象会话工厂实例
Map repositories = applicationContext.getBeansOfType(Repository.class);
for (Entry entry : repositories.entrySet()) {
Repository> repository = entry.getValue();
if (AopUtils.isAopProxy(repository)) {
try {
repository = (Repository>) ((Advised) repository).getTargetSource().getTarget();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
if (!(repository instanceof HibernateSimpleRepository)) {
continue;
}
Class> model = repository.getModel();
SessionFactory sessionFactory = modelSessionFactoryMappings.get(model);
if (sessionFactory == null) {
throw new IllegalStateException("No matching session factory:" + model);
}
((HibernateSimpleRepository>) repository).setSessionFactory(sessionFactory);
}
}
/**
* 绑定数据验证属性
*
* @param applicationContext Spring上下文对象
*/
protected void bindValidateProperty(ApplicationContext applicationContext) {
Collection sessionFactoryBeans = applicationContext.getBeansOfType(
LocalSessionFactoryBean.class).values();
for (LocalSessionFactoryBean bean : sessionFactoryBeans) {
SessionFactory sessionFactory = bean.getObject();
Configuration configuration = bean.getConfiguration();
Iterator persistentIterator = configuration.getClassMappings();
while (persistentIterator.hasNext()) {
PersistentClass persistent = persistentIterator.next();
Class> mappedClass = persistent.getMappedClass();
if (this.validate != null && !Strings.matches(mappedClass.getName(), this.validate)) {
continue;
}
List mappedProperties = VALIDATE_MODEL_PROPERTY_MAPPING.get(mappedClass);
if (mappedProperties == null) {
mappedProperties = new LinkedList();
VALIDATE_MODEL_PROPERTY_MAPPING.put(mappedClass, mappedProperties);
}
Iterator> propertyIterator = persistent.getPropertyIterator();
while (propertyIterator.hasNext()) {
Property property = (Property) propertyIterator.next();
String name = property.getName();
if (TreeModel.class.isAssignableFrom(mappedClass)
&& (name.equals("key") || name.equals("level") || name.equals("leaf")
|| name.equals("parent") || name.equals("children"))) {
continue;
}
mappedProperties.add(property);
Type type = property.getType();
Class> foreignKeyClass = Hibernates.getPropertyTypeClass(sessionFactory, type);
if (this.validate != null && !Strings.matches(foreignKeyClass.getName(), this.validate)) {
continue;
}
if (type.isEntityType() || type.isCollectionType()) {
Map, List> relates = VALIDATE_MODEL_RELATE_MAPPING.get(foreignKeyClass);
if (relates == null) {
relates = new HashMap, List>();
VALIDATE_MODEL_RELATE_MAPPING.put(foreignKeyClass, relates);
}
List properties = relates.get(mappedClass);
if (properties == null) {
properties = new LinkedList();
relates.put(mappedClass, properties);
}
properties.add(property);
}
}
}
persistentIterator = configuration.getClassMappings();
while (persistentIterator.hasNext()) {
PersistentClass persistent = persistentIterator.next();
Class> mappedClass = persistent.getMappedClass();
Map, List> relates = VALIDATE_MODEL_RELATE_MAPPING.get(mappedClass);
if (relates == null) {
continue;
}
Class> superclass = mappedClass.getSuperclass();
while (superclass != Object.class && !Modifier.isAbstract(superclass.getModifiers())) {
Map, List> superrelates = VALIDATE_MODEL_RELATE_MAPPING.get(superclass);
if (superrelates == null) {
break;
}
for (Entry, List> entry : relates.entrySet()) {
Class> key = entry.getKey();
List properties = superrelates.get(key);
if (properties == null) {
properties = new LinkedList();
superrelates.put(key, properties);
}
for (Property property : entry.getValue()) {
if (!properties.contains(property)) {
properties.add(property);
}
}
}
for (Entry, List> entry : superrelates.entrySet()) {
Class> key = entry.getKey();
List properties = relates.get(key);
if (properties == null) {
properties = new LinkedList();
relates.put(key, properties);
}
for (Property property : entry.getValue()) {
if (!properties.contains(property)) {
properties.add(property);
}
}
}
superclass = superclass.getSuperclass();
}
}
}
}
/**
* 注册事件监听器
*
* @param applicationContext Spring上下文对象
*/
protected void registerEventListener(ApplicationContext applicationContext) {
Collection sessionFactories = applicationContext.getBeansOfType(SessionFactory.class).values();
for (SessionFactory sessionFactory : sessionFactories) {
EventListenerRegistry registry = ((SessionFactoryImpl) sessionFactory).getServiceRegistry().getService(
EventListenerRegistry.class);
Map loadEventListeners = applicationContext
.getBeansOfType(LoadEventListener.class);
if (!loadEventListeners.isEmpty()) {
registry.appendListeners(EventType.LOAD, loadEventListeners.values().toArray(new LoadEventListener[0]));
}
Map lockEventListeners = applicationContext
.getBeansOfType(LockEventListener.class);
if (!lockEventListeners.isEmpty()) {
registry.appendListeners(EventType.LOCK, lockEventListeners.values().toArray(new LockEventListener[0]));
}
Map mergeEventListeners = applicationContext
.getBeansOfType(MergeEventListener.class);
if (!mergeEventListeners.isEmpty()) {
registry.appendListeners(EventType.MERGE,
mergeEventListeners.values().toArray(new MergeEventListener[0]));
}
Map evictEventListeners = applicationContext
.getBeansOfType(EvictEventListener.class);
if (!evictEventListeners.isEmpty()) {
registry.appendListeners(EventType.EVICT,
evictEventListeners.values().toArray(new EvictEventListener[0]));
}
Map flushEventListeners = applicationContext
.getBeansOfType(FlushEventListener.class);
if (!flushEventListeners.isEmpty()) {
registry.appendListeners(EventType.FLUSH,
flushEventListeners.values().toArray(new FlushEventListener[0]));
}
Map deleteEventListeners = applicationContext
.getBeansOfType(DeleteEventListener.class);
if (!deleteEventListeners.isEmpty()) {
registry.appendListeners(EventType.DELETE,
deleteEventListeners.values().toArray(new DeleteEventListener[0]));
}
Map persistEventListeners = applicationContext
.getBeansOfType(PersistEventListener.class);
if (!persistEventListeners.isEmpty()) {
registry.appendListeners(EventType.PERSIST,
persistEventListeners.values().toArray(new PersistEventListener[0]));
}
Map refreshEventListeners = applicationContext
.getBeansOfType(RefreshEventListener.class);
if (!refreshEventListeners.isEmpty()) {
registry.appendListeners(EventType.REFRESH,
refreshEventListeners.values().toArray(new RefreshEventListener[0]));
}
Map preLoadEventListeners = applicationContext
.getBeansOfType(PreLoadEventListener.class);
if (!preLoadEventListeners.isEmpty()) {
registry.appendListeners(EventType.PRE_LOAD,
preLoadEventListeners.values().toArray(new PreLoadEventListener[0]));
}
Map postLoadEventListeners = applicationContext
.getBeansOfType(PostLoadEventListener.class);
if (!postLoadEventListeners.isEmpty()) {
registry.appendListeners(EventType.POST_LOAD,
postLoadEventListeners.values().toArray(new PostLoadEventListener[0]));
}
Map autoFlushEventListeners = applicationContext
.getBeansOfType(AutoFlushEventListener.class);
if (!autoFlushEventListeners.isEmpty()) {
registry.appendListeners(EventType.AUTO_FLUSH,
autoFlushEventListeners.values().toArray(new AutoFlushEventListener[0]));
}
Map preUpdateEventListeners = applicationContext
.getBeansOfType(PreUpdateEventListener.class);
if (!preUpdateEventListeners.isEmpty()) {
registry.appendListeners(EventType.PRE_UPDATE,
preUpdateEventListeners.values().toArray(new PreUpdateEventListener[0]));
}
Map preDeleteEventListeners = applicationContext
.getBeansOfType(PreDeleteEventListener.class);
if (!preDeleteEventListeners.isEmpty()) {
registry.appendListeners(EventType.PRE_DELETE,
preDeleteEventListeners.values().toArray(new PreDeleteEventListener[0]));
}
Map preInsertEventListeners = applicationContext
.getBeansOfType(PreInsertEventListener.class);
if (!preInsertEventListeners.isEmpty()) {
registry.appendListeners(EventType.PRE_INSERT,
preInsertEventListeners.values().toArray(new PreInsertEventListener[0]));
}
Map replicateEventListeners = applicationContext
.getBeansOfType(ReplicateEventListener.class);
if (!replicateEventListeners.isEmpty()) {
registry.appendListeners(EventType.REPLICATE,
replicateEventListeners.values().toArray(new ReplicateEventListener[0]));
}
Map dirtyCheckEventListeners = applicationContext
.getBeansOfType(DirtyCheckEventListener.class);
if (!dirtyCheckEventListeners.isEmpty()) {
registry.appendListeners(EventType.DIRTY_CHECK,
dirtyCheckEventListeners.values().toArray(new DirtyCheckEventListener[0]));
}
Map postUpdateEventListeners = applicationContext
.getBeansOfType(PostUpdateEventListener.class);
if (!postUpdateEventListeners.isEmpty()) {
registry.appendListeners(EventType.POST_UPDATE,
postUpdateEventListeners.values().toArray(new PostUpdateEventListener[0]));
}
Map postDeleteEventListeners = applicationContext
.getBeansOfType(PostDeleteEventListener.class);
if (!postDeleteEventListeners.isEmpty()) {
registry.appendListeners(EventType.POST_DELETE,
postDeleteEventListeners.values().toArray(new PostDeleteEventListener[0]));
}
Map postInsertEventListeners = applicationContext
.getBeansOfType(PostInsertEventListener.class);
if (!postInsertEventListeners.isEmpty()) {
registry.appendListeners(EventType.POST_INSERT,
postInsertEventListeners.values().toArray(new PostInsertEventListener[0]));
}
Map flushEntityEventListeners = applicationContext
.getBeansOfType(FlushEntityEventListener.class);
if (!flushEntityEventListeners.isEmpty()) {
registry.appendListeners(EventType.FLUSH_ENTITY,
flushEntityEventListeners.values().toArray(new FlushEntityEventListener[0]));
}
Map saveOrUpdateEventListeners = applicationContext
.getBeansOfType(SaveOrUpdateEventListener.class);
if (!saveOrUpdateEventListeners.isEmpty()) {
registry.appendListeners(EventType.SAVE_UPDATE,
saveOrUpdateEventListeners.values().toArray(new SaveOrUpdateEventListener[0]));
}
Map initializeCollectionEventListeners = applicationContext
.getBeansOfType(InitializeCollectionEventListener.class);
if (!initializeCollectionEventListeners.isEmpty()) {
registry.appendListeners(EventType.INIT_COLLECTION, initializeCollectionEventListeners.values()
.toArray(new InitializeCollectionEventListener[0]));
}
}
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
super.setApplicationContext(applicationContext);
this.bindSessionFactory(applicationContext);
this.bindValidateProperty(applicationContext);
this.registerEventListener(applicationContext);
}
@Override
public Object adaption(Object object) {
if (Hibernate.isInitialized(object)) {
return object;
} else if (object instanceof Map) {
return Collections.emptyMap();
} else if (object instanceof Set) {
return Collections.emptySet();
} else if (object instanceof List) {
return Collections.emptyList();
}
return null;
}
@Override
public void onServiceEvent(ServiceEvent event) {
Class> model = event.getService().getModel();
if (this.validate == null || Strings.matches(model.getName(), this.validate)) {
if (event instanceof InitEvent) {
this.validation((InitEvent) event);
} else if (event instanceof DeleteEvent) {
this.validation((DeleteEvent) event);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy