Spring 에 Hibernate Annotated Classes 자동 불 러 오기
<property name="annotatedClasses">
<list><value>com.systop.common.core.dao.testmodel.TestDept</value></list>
</property>
<property name="mappingLocations">
<list><value>classpath*:org/jbpm/**/*.hbm.xml</value></list>
</property>
Spring 은 mappingLocations 속성 에 정 의 된 Path Pattern 에 따라 hbm 파일 을 자동 으로 불 러 올 수 있 지만, annotated Classes 에 대해 서 는 하나의 고민 만 적 을 수 있 습 니 다.Hibernate 든 Spring 이 든 패키지 에 있 는 Anntated Classes 를 자동 으로 불 러 올 수 없습니다.이렇게 되면 프로젝트 를 재 구성 하거나 Tables 를 증가 / 감소 시 키 는 데 문제 가 생 길 수 있다.특히 포 장 된 애플 리 케 이 션 들 에 게 는 더욱 그렇다.Spring 에 Annotated Classes 를 자동 으로 불 러 올 수 있 습 니까? 저 는 Spring 2.5 에서 component - can 이 생각 나 서 AnnotationSession Factory Bean 의 자 류 를 고양이 처럼 썼 습 니 다.
package com.systop.common.core.dao.hibernate;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Entity;
import org.apache.oro.text.regex.MalformedPatternException;
import org.apache.oro.text.regex.Pattern;
import org.apache.oro.text.regex.PatternCompiler;
import org.apache.oro.text.regex.PatternMatcher;
import org.apache.oro.text.regex.Perl5Compiler;
import org.apache.oro.text.regex.Perl5Matcher;
import org.hibernate.HibernateException;
import org.hibernate.cfg.AnnotationConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
import com.systop.common.core.exception.ApplicationException;
@SuppressWarnings("unchecked")
public class AnnotationSessionFactoryBeanEx extends AnnotationSessionFactoryBean {
private static final Logger logger = LoggerFactory
.getLogger(AnnotationSessionFactoryBeanEx.class);
/**
* The locations of the hibernate enity class files. They are often some of the string with
* Sping-style resource. A ".class" subfix can make the scaning more precise.
* <p> example:
* <pre>
* classpath*:com/systop/** /model/*.class
* </pre>
*/
private String[] annotatedClassesLocations;
/**
* Which classes are not included in the session.
* They are some of the regular expression.
*/
private String[] excludedClassesRegexPatterns;
/**
* @param annotatedClassesLocations the annotatedClassesLocations to set
*/
public void setAnnotatedClassesLocations(String[] annotatedClassesLocations) {
this.annotatedClassesLocations = annotatedClassesLocations;
}
/**
* @see AnnotationSessionFactoryBean#postProcessAnnotationConfiguration(org.hibernate.cfg.AnnotationConfiguration)
*/
@Override
protected void postProcessAnnotationConfiguration(AnnotationConfiguration config)
throws HibernateException {
Set<Class> annClasses = scanAnnotatedClasses(); //Scan enity classes.
// Add entity classes to the configuration.
if (!CollectionUtils.isEmpty(annClasses)) {
for (Class annClass : annClasses) {
config.addAnnotatedClass(annClass);
}
}
}
/**
* Scan annotated hibernate classes in the locations.
* @return Set of the annotated classes, if no matched class, return empty Set.
*/
private Set<Class> scanAnnotatedClasses() {
ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(
resourcePatternResolver);
Set<Class> annotatedClasses = new HashSet<Class>();
if (annotatedClassesLocations != null) {
try {
for (String annClassesLocation : annotatedClassesLocations) {
//Resolve the resources
Resource[] resources = resourcePatternResolver.getResources(annClassesLocation);
for (Resource resource : resources) {
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(resource);
String className = metadataReader.getClassMetadata().getClassName();
//If the class is hibernate enity class, and it does not match the excluded class patterns.
if (isEntityClass(metadataReader) && !isExcludedClass(className)) {
Class clazz = ClassUtils.forName(className);
annotatedClasses.add(clazz);
logger.debug("A entity class has been found.
({})", clazz.getName());
}
}
}
} catch (IOException e) {
logger.error("I/O failure during classpath scanning, ({})", e.getMessage());
e.printStackTrace();
throw new ApplicationException(e);
} catch (ClassNotFoundException e) {
logger.error("Class not found, ({})", e.getMessage());
e.printStackTrace();
throw new ApplicationException(e);
} catch (LinkageError e) {
logger.error("LinkageError ({})", e.getMessage());
e.printStackTrace();
throw new ApplicationException(e);
}
}
return annotatedClasses;
}
/**
* @return True if the given MetadataReader shows
* that the class is annotated by <code>javax.persistence.Enity</code>
*/
private boolean isEntityClass(MetadataReader metadataReader) {
Set<String> annTypes = metadataReader.getAnnotationMetadata().getAnnotationTypes();
if (CollectionUtils.isEmpty(annTypes)) {
return false;
}
return annTypes.contains(Entity.class.getName());
}
/**
*
* @return True if the given class name match the excluded class patterns.
*/
private boolean isExcludedClass(String className) {
if (excludedClassesRegexPatterns == null) { // All class is included.
return false;
}
PatternCompiler compiler = new Perl5Compiler();
PatternMatcher matcher = new Perl5Matcher();
try {
for (String regex : excludedClassesRegexPatterns) { //Test each patterns.
logger.debug("Pattern is: {}", regex);
Pattern pattern = compiler.compile(regex);
if (matcher.matches(className, pattern)) {
logger.debug("class [{}], matches [{}], so it is excluded.", className, pattern
.getPattern());
return true;
}
}
} catch (MalformedPatternException e) {
logger.warn("Malformed pattern [{}]", e.getMessage());
}
return false;
}
/**
* @param exculdePatterns the exculdePatterns to set
*/
public void setExcludedClassesRegexPatterns(String[] excludedClassesRegexPatterns) {
this.excludedClassesRegexPatterns = excludedClassesRegexPatterns;
}
}
Spring 프로필 에 이렇게 쓰 기 를:
<bean id="sessionFactory" class="com.systop.common.core.dao.hibernate.AnnotationSessionFactoryBeanEx">
<property name="dataSource" ref="dataSource"/>
<property name="annotatedClassesLocations">
<list>
<value>classpath*:com/systop/**/model/*.class</value>
</list>
</property>
<!-- scan -->
<property name="excludedClassesRegexPatterns">
<list>
<value><![CDATA[^[\w\.]+Test[\w]+$]]></value>
</list>
</property>
</bean>
자, 한번 고생 하면 영원히 편안 해진 다!아, 맞다. 상기 코드 는 Spring 2.5 의 일부 API 를 사 용 했 고 apache oro 의 정규 표현 식 API 도 있 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Spring에서 DAO가 순환 호출될 때 데이터가 실시간으로 업데이트되지 않는 해결 방법문제를 설명하기 전에 몇 가지 전제 사항을 설명하십시오. Spring의 구성 파일에서 다음과 같은 방식으로 데이터베이스 트랜잭션을 구성했다고 가정하십시오. 현재 UserDao 및 Security Service가 있습...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.