在hibernate和spring集成时,使用annotation方式来替代xml配置方式可以减少项目中配置文件的数量。使项目结构看起来更佳简洁、干净。为此,spring提供了AnnotationSessionFactoryBean 类。但是,在配置的时候,这个类不是很灵活,eg:
Java代码
<bean id="sessionFactory" class="com.derbysoft.hibernate.core.LocaleAnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
<property name="annotatedClasses">
<list>
<value>com.example.domain.Role</value>
<value>com.example.domain.Permission</value>
</list>
</property>
</bean>
<bean id="sessionFactory" class="com.derbysoft.hibernate.core.LocaleAnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
<property name="annotatedClasses">
<list>
<value>com.example.domain.Role</value>
<value>com.example.domain.Permission</value>
</list>
</property>
</bean> 注意到这几行配置代码:
Java代码
<property name="annotatedClasses">
<list>
<value>com.example.domain.Role</value>
<value>com.example.domain.Permission</value>
</list>
</property>
<property name="annotatedClasses">
<list>
<value>com.example.domain.Role</value>
<value>com.example.domain.Permission</value>
</list>
</property> 在你的项目中,你的所有持久化类都需要手动配置到annotatedClasses属性中,很不灵活。所以,为了能过达到更高的灵活性,我们需要自己去扩展AnnotationSessionFactoryBean sessionFacotory工厂类。spring team 也考虑到这一点,为我们提供了预留方法,方便我们实现客户化的功能,eg:
Java代码
/**
* To be implemented by subclasses that want to to perform custom
* post-processing of the AnnotationConfiguration object after this
* FactoryBean performed its default initialization.
* @param config the current AnnotationConfiguration object
* @throws HibernateException in case of Hibernate initialization errors
*/
protected void postProcessAnnotationConfiguration(AnnotationConfiguration config)
throws HibernateException {
}
/**
* To be implemented by subclasses that want to to perform custom
* post-processing of the AnnotationConfiguration object after this
* FactoryBean performed its default initialization.
* @param config the current AnnotationConfiguration object
* @throws HibernateException in case of Hibernate initialization errors
*/
protected void postProcessAnnotationConfiguration(AnnotationConfiguration config)
throws HibernateException {
} 这个方法就是 AnnotationSessionFactoryBean 提供给我们让我们能够实现自己特定功能的方法。因此,我们可以创建一个子类,然后继承AnnotationSessionFactoryBean 实现此方法。
附件中,是我的详细实代码,需要的可以进行下载。下面,我来详细分析一下我的实现思路,希望大家多多指教。
大家都知道,在使用spring的时候,spring在加载bean的时候可以按这样一种路径方式来加载,eg:classpath*:com/derbysoft/**/*.class,spring就会加载com.derbysoft包下及其所有子包的class文件,这个叫ant-style模式。在使用struts的时候,我们用annotation注释action的时候。会在web.xml配置这样一段代码:
Java代码
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
<init-param>
<param-name>actionPackages</param-name>
<param-value>com.derbysoft.drental.action</param-value>
</init-param>
</filter>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
<init-param>
<param-name>actionPackages</param-name>
<param-value>com.derbysoft.drental.action</param-value>
</init-param>
</filter> 会指定一个actionPackages属性,然后struts在初始化的时候会认为这个指定的包或子包下,所有的类为action类。(当然在搜索过程中,struts默认会进行过滤,你也可以自己实现过滤条件,eg:没被注解的类不进行加载)
在我实现的代码中,我参照了这两种模式的实现,底层代码都是依赖spring和struts的核心代码的。
Java代码
/**
* @see AnnotationSessionFactoryBean#postProcessAnnotationConfiguration(org.hibernate.cfg.AnnotationConfiguration)
*/
@Override
protected void postProcessAnnotationConfiguration(AnnotationConfiguration config) throws HibernateException {
DomainClassLoader[] domainClassLoaders = DomainClassLoaderFactory.buildDomainClassLoader(annotatedClassesLocations);
for (DomainClassLoader domainClassLoader : domainClassLoaders) {
if (domainClassLoader == null) continue;
Set<Class<? extends Class>> annClasses = domainClassLoader.loadAnnotatedClasses();
for (Class annClass : annClasses) {
config.addAnnotatedClass(annClass);
}
}
}
/**
* @see AnnotationSessionFactoryBean#postProcessAnnotationConfiguration(org.hibernate.cfg.AnnotationConfiguration)
*/
@Override
protected void postProcessAnnotationConfiguration(AnnotationConfiguration config) throws HibernateException {
DomainClassLoader[] domainClassLoaders = DomainClassLoaderFactory.buildDomainClassLoader(annotatedClassesLocations);
for (DomainClassLoader domainClassLoader : domainClassLoaders) {
if (domainClassLoader == null) continue;
Set<Class<? extends Class>> annClasses = domainClassLoader.loadAnnotatedClasses();
for (Class annClass : annClasses) {
config.addAnnotatedClass(annClass);
}
}
} 这是整个类的核心代码,我们通过工厂模式来获得不同加载domain方式的实现(spring ant-sttyle模式和struts模式)
Java代码
/**
* DomainClassLoader
* @author leo
*
*/
public static abstract class DomainClassLoader {
protected String[] annotatedClassesLocations;
public DomainClassLoader(String[] annotatedClassesLocations) {
this.annotatedClassesLocations = annotatedClassesLocations;
}
/**
*
* @return set collection of of domain class that has annotation
*/
public abstract Set<Class<? extends Class>> loadAnnotatedClasses();
}
/**
* DomainClassLoader
* @author leo
*
*/
public static abstract class DomainClassLoader {
protected String[] annotatedClassesLocations;
public DomainClassLoader(String[] annotatedClassesLocations) {
this.annotatedClassesLocations = annotatedClassesLocations;
}
/**
*
* @return set collection of of domain class that has annotation
*/
public abstract Set<Class<? extends Class>> loadAnnotatedClasses();
} 这段代码是加载类的抽象,不同的实现都必须去继承它,eg:
Java代码
/**
* struts action pattern implements
* @author leo
* @see ResolverUtil
*/
public static class PackageDomainClassLoaderProvider extends DomainClassLoader {
public PackageDomainClassLoaderProvider(String[] annotatedClassesLocations) {
super(annotatedClassesLocations);
}
@Override
public Set<Class<? extends Class>> loadAnnotatedClasses() {
ResolverUtil<Class> resolver = new ResolverUtil<Class>();
resolver.find(new ResolverUtil.AnnotatedWith(Entity.class), annotatedClassesLocations);
Set<Class<? extends Class>> actionClasses = resolver.getClasses();
return actionClasses;
}
}
/**
* struts action pattern implements
* @author leo
* @see ResolverUtil
*/
public static class PackageDomainClassLoaderProvider extends DomainClassLoader {
public PackageDomainClassLoaderProvider(String[] annotatedClassesLocations) {
super(annotatedClassesLocations);
}
@Override
public Set<Class<? extends Class>> loadAnnotatedClasses() {
ResolverUtil<Class> resolver = new ResolverUtil<Class>();
resolver.find(new ResolverUtil.AnnotatedWith(Entity.class), annotatedClassesLocations);
Set<Class<? extends Class>> actionClasses = resolver.getClasses();
return actionClasses;
}
} 这个就是struts 包模式的实现,主要的业务是通过ResolverUtil这个struts类来实现的。
最后通过工厂方法返回一个DomainClassLoader 对象,eg:
Java代码
/**
* DomainClassLoader Factory
* @author leo
*
*/
public static class DomainClassLoaderFactory {
/**
*
* @param includedClass
* @param excludedClass
* @return array of DomainClassLoader
*/
public static DomainClassLoader[] buildDomainClassLoader(String[] includedClasses) {
List<String> packages = new ArrayList<String>();
List<String> regexClasses = new ArrayList<String>();
DomainClassLoader[] domainClassLoaders = new DomainClassLoader[2];
for (String regexOrpackage : includedClasses) {
if (regexOrpackage.contains(ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX)) {
regexClasses.add(regexOrpackage);
} else {
packages.add(regexOrpackage);
}
}
if (packages.size() != 0) {
DomainClassLoader domainClassLoader = new PackageDomainClassLoaderProvider(packages.toArray(new String[packages.size()]));
domainClassLoaders[0] = domainClassLoader;
}
if (regexClasses.size() != 0) {
DomainClassLoader domainClassLoader = new RegexDomainClassLoaderProvider(regexClasses.toArray(new String[regexClasses.size()]));
domainClassLoaders[1] = domainClassLoader;
}
return domainClassLoaders;
}
}
/**
* DomainClassLoader Factory
* @author leo
*
*/
public static class DomainClassLoaderFactory {
/**
*
* @param includedClass
* @param excludedClass
* @return array of DomainClassLoader
*/
public static DomainClassLoader[] buildDomainClassLoader(String[] includedClasses) {
List<String> packages = new ArrayList<String>();
List<String> regexClasses = new ArrayList<String>();
DomainClassLoader[] domainClassLoaders = new DomainClassLoader[2];
for (String regexOrpackage : includedClasses) {
if (regexOrpackage.contains(ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX)) {
regexClasses.add(regexOrpackage);
} else {
packages.add(regexOrpackage);
}
}
if (packages.size() != 0) {
DomainClassLoader domainClassLoader = new PackageDomainClassLoaderProvider(packages.toArray(new String[packages.size()]));
domainClassLoaders[0] = domainClassLoader;
}
if (regexClasses.size() != 0) {
DomainClassLoader domainClassLoader = new RegexDomainClassLoaderProvider(regexClasses.toArray(new String[regexClasses.size()]));
domainClassLoaders[1] = domainClassLoader;
}
return domainClassLoaders;
}
} 最后,我配置的时候只需这样:
Java代码
<property name="annotatedClassesLocations">
<list>
<value>classpath*:com/example/**/domain/*.class</value>
<value>com.example.domain</value>
</list>
</property>
<property name="annotatedClassesLocations">
<list>
<value>classpath*:com/example/**/domain/*.class</value>
<value>com.example.domain</value>
</list>
</property> spring在加载的时候,会去匹配类路径下com.example.xxx.domain.xxx.class 类和com.example.domain包及其子包下所有的类。至于具体的实现细节请下载附件
分享到:
相关推荐
要让Hibernate同时支持XML和注解映射,我们可以创建一个新的配置类,该类扩展`AnnotationSessionFactoryBean`,并在需要时调用其父类`LocalSessionFactoryBean`的方法来处理XML映射。这样,我们就可以拥有一个单一的...
`mappedBy`属性用于指定反向映射的字段,`fetch`属性则用于指定加载策略,如`EAGER`立即加载或`LAZY`延迟加载。 - **多对多(Many-to-Many)**:这种关系涉及多个实体之间的关联。`@ManyToMany`注解用于映射这种...
2. **Hibernate**:一个开放源码的对象关系映射框架,允许开发者将Java对象映射到数据库表中。它简化了持久化层的开发工作,使开发者能够更专注于业务逻辑的编写。 3. **LocalSessionFactoryBean**:Spring框架中的...
例如,使用UUID作为主键时,可以通过`@GenericGenerator(name="system-uuid",strategy="uuid")`和`@GeneratedValue(generator="system-uuid")`组合来实现。 #### 2. Spring下的SessionFactory配置 - **...
通过使用Spring Data,开发者无需手动编写大量的DAO方法,只需定义好Repository接口,Spring Data就能自动生成对应的实现。 2. **数据库设计与管理**:项目使用了Oracle数据库,通过PowerDesigner工具进行数据库...
Hibernate 是一个开放源代码的对象关系映射(ORM)工具,它可以将 Java 类映射为数据库表,并自动将 Java 应用程序数据转换为 SQL 语句。Hibernate3.2 版本引入了许多新特性,如延迟加载、批处理等,以提高性能和...
本文将深入探讨Hibernate注解的使用,包括SessionFactory的配置、POJO类的声明、主键的设定、普通字段的处理以及级联操作和一对一关联的实现。 首先,我们来看SessionFactory的配置。在传统的XML配置中,我们需要...
在业务层(Service)和数据访问层(DAO)中,使用@Autowired注解或XML配置文件来实现依赖注入,使得Spring管理的对象能够自动获取所需的SessionFactory或HibernateTemplate实例。 ### 7. 测试与运行 完成以上配置后...
通过这种方式,开发人员可以在不编写XML映射文件的情况下,利用Java注解实现对象和数据库之间的映射,简化了开发过程,提高了开发效率。 在实际项目中,还需要注意其他配置,比如事务管理、异常处理等。Spring提供...
Hibernate是Java环境下的一款开源的对象关系映射(ORM)框架,可以有效地将Java对象映射到数据库表中,从而简化了数据持久化操作。 ### Spring与Struts的集成 在给定的内容中提到了Spring与Struts的集成方式,具体...
- **扩展词典**:`<entry key="ext_dict">/dic/extendWord.dic</entry>`指定了自定义扩展词典的路径。 - **停用词典**:`<entry key="ext_stopwords">/dic/stopWords.dic</entry>`指定了停用词的路径。 3. **...
- **ContextLoaderListener**:这是Spring框架中的一个监听器,用于在启动时加载Spring的配置文件。具体配置如下: ```xml <param-name>contextConfigLocation <param-value>classpath*:spring/*.xml ...
自Spring 2.5.6版本开始,`AnnotationSessionFactoryBean`增加了`setPackagesToScan`方法,这是一个重要的改进。此方法允许我们在配置文件中直接指定需要扫描的实体类包名,从而自动发现并注册实体类,无需手动配置...
《SSH2框架零配置技术详解》 SSH2框架,由Struts2、Spring和Hibernate2组成,是Java Web开发中...在实际项目中,结合Spring的自动扫描和依赖注入功能,可以进一步实现更全面的零配置,实现更加灵活和高效的开发模式。
Spring框架的自动装配特性可以减少XML配置,通过`autowire`属性实现。`byName`根据bean名称匹配,`byType`根据bean类型匹配。可以在`beans`节点中设置全局自动装配,但需要注意,过度依赖自动装配可能导致组件间...
- 可以选择将 Hibernate 和 Spring 的配置合并,通过 Spring 的 `LocalSessionFactoryBean` 或 `AnnotationSessionFactoryBean` 来管理 Hibernate 的 SessionFactory。 6. **配置启动环境** - 配置 `web.xml`,...
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <value>com.example.entity.Book</value> <prop key="hibernate.dialect">org....