`
taowen
  • 浏览: 193558 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

让AnnotationConfiguration支持自定义UserCollectionType

阅读更多
在Hibernate的Jira上,这个两个issue已经放了很久了:
Add annotation support for serCollectionType
Add the annotations to map the User Collection Type
但是官方一直不给解决,咋办呢?以前唯一的办法就是不用Annotation,回到hbm文件的时代。

经过我几天的跟踪Hibernate的源代码,终于找到了解决办法,在这里分享给大家。

如果我们有这样的实体

@Entity
public class Cat {

    @Id
    @GeneratedValue
    private long id;
    String name;

    @ManyToOne
    @JoinColumn(name = "children")
    Cat mother;

    @OneToMany(mappedBy = "mother")
    QSet<Cat> children = new QHashSet<Cat>();
}

public interface QSet<E> extends Set<E> {
   // my stuff
}


直接拿给Hibernate持久,毫无疑问会遇到错误。但是之前用hbm文件的时候,是可以配置的。参见

Hibernate: Custom Collection Types

核心的部分就是一行
<set name="subordinates" collection-type="com.javalobby.tnt.hib.FastSetType">


这个设置到了Annotation时代,要么是消失了,要么是我鼠目寸光,找不到。结果是,再也不能试用自定义的Collection类型了。那么我们来看看Hibernate报了什么错误吧:

引用

"Illegal attempt to map a non collection as a @OneToMany, @ManyToMany or @CollectionOfElements: "


通过跟踪源代码,可以发现。之所以会出现这个错误,是因为Hibernate的反射系统认为QSet这个类型不是Collection。再进一步跟踪,发现只有Set.class, List.class这些才被EJB3ReflectionManager认为是Collection。所以第一步,就是通过继承,让ReflectionManager认为QSet也是Collection。

public class CustomizableEJB3ReflectionManager extends EJB3ReflectionManager {

    private JavaXTypeConverter xTypeConverter = new NoopJavaXTypeConverter();

    @Inject
    public CustomizableEJB3ReflectionManager(JavaXTypeConverter xTypeConverter) {
        this.xTypeConverter = xTypeConverter;
    }

    @Override
    public JavaXType toXType(TypeEnvironment context, Type propType) {
        // do things differently here, to make it aware of QSet
        PublicJavaXType converted = xTypeConverter.convert(context, propType, this);
        if (converted != null) {
            return converted;
        }
        return super.toXType(context, propType);
    }
}


这样,我们就可以通过第一步了。但是仍然会出错,这回的错误是session.save的时候Hibernate尝试用自己的包装过的collection来代替你手工new出来的collection的时候出错,Hibernate找不到合适的setter。当然嘛,Hibernate认为类型时Set.class,但是实际类型是QSet.class,显然会出错。

为了解决这个问题,还是要像过去一样通过配置一个UserCollectionType。好在Hibernate的Annotation配置和Hbm配置都是一张皮,肉都是一样,都是Configuration这个对象。通过
    private void processValues(AnnotationConfiguration config, ValueProcessor processor) {
        Iterator classMappings = config.getClassMappings();
        while (classMappings.hasNext()) {
            PersistentClass classMapping = (PersistentClass) classMappings.next();
            Iterator properties = classMapping.getPropertyIterator();
            while (properties.hasNext()) {
                Property property = (Property) properties.next();
                Value value = property.getValue();
                processor.process(value);
            }
        }
    }

我们可以拿到所有映射的类(其实不完全是,还有subclass和component,不过简便起见,略过)的属性的映射类。然后再:
public class SetValueProcessor implements ValueProcessor {

    public void process(Value value) {
        if (!(value instanceof Set)) {
            return;
        }
        Set set = (Set) value;
        if (set.getTypeName() != null) {
            return;
        }
        set.setTypeName(QueryableSetType.class.getName());
    }
}

public class QueryableSetType implements UserCollectionType {
  // ...
}

我们就可以把我们定义的UserCollectionType附加上去了。而且这样还有一个好处,不需要在所有使用的地方都去声明UserCollectionType,只需要用代码去遍历一遍Configuration就搞定了。具体的代码参加:
http://javaonhorse.googlecode.com/svn/trunk/
分享到:
评论

相关推荐

    Hibernate中注解的使用

    自从JDK 1.5引入注解机制后,Hibernate也开始支持使用注解来替代传统的XML配置文件。通过在实体类上添加特定的注解,我们可以告诉Hibernate如何将Java对象映射到数据库中的表。这种方法的优势在于,减少了配置文件的...

    hibernate api 文档

    9. **Listeners and Interceptors**: Hibernate允许注册监听器或拦截器来处理对象生命周期的各个阶段,例如在对象加载、保存、更新或删除时执行自定义逻辑。 10. **Hibernate Tools**: 提供了诸如逆向工程、生成...

    Hibernate4注解全教程

    Hibernate4注解主要依赖于Hibernate Annotation库,支持EJB3持久性规范,为Java持久化提供了一种标准化机制。 在Hibernate中使用注解进行配置,仍然需要配置文件cfg.xml,但是它被用来指定哪些类通过注解进行配置。...

    Hibernate-Annotation中文教程.pdf

    * Hibernate Annotation 库需要 Java 5 的支持。 * 需要添加 HibernateAnnotations .jar 文件和 Java 持久性 API。 * 需要使用 AnnotationConfiguration 类来建立会话工厂。 * 需要在 Hibernate 配置文件中声明持久...

    hibernate4.22源码

    7. **映射文件解析**:`org.hibernate.cfg`包包含了Hibernate的配置和映射文件解析器,如`AnnotationConfiguration`和`Configuration`,它们负责读取`hibernate.cfg.xml`和实体类上的注解,生成相应的元模型。...

    JDK 5.0的新特性

    此外,JDK 5.0的注解还支持元注解,允许自定义注解并为其指定元数据,例如`@Target`和`@Retention`。`@Target`定义了注解可以应用的目标(如类、方法、字段等),而`@Retention`指定了注解的生命周期(源码级、编译...

    Hibernate 注解

    现代IDEs(如IntelliJ IDEA和Eclipse)通常都支持注解的自动补全和语法高亮,使得编写和维护Hibernate实体类变得更加容易。 - **EJB3标准兼容**:Hibernate注解遵循EJB3标准,这意味着你可以使用EJB3编程模型来...

    hibernate3.2官方源代码

    - Hibernate的`org.hibernate.event`和`org.hibernate.interceptor`包支持事件监听和拦截器机制,允许开发者在特定操作(如插入、更新、删除)前后插入自定义逻辑,增强了框架的可扩展性。 7. **实体状态管理:** ...

    Hibernatetools_Reference_Guide

    - 注解基础配置:使用 `&lt;annotationconfiguration&gt;` 标签定义。 - JPA 基础配置:使用 `&lt;jpaconfiguration&gt;` 标签定义。 - JDBC 反向工程配置:使用 `&lt;jdbcconfiguration&gt;` 标签定义。 4. **Exporters**: - ...

    ssh框架搭建教程

    &lt;property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration"/&gt; &lt;!-- other properties --&gt; ``` 最后,配置Struts2与Spring的整合,确保Action类可以被Spring管理: ```xml ...

    5分钟利用Myeclipse快速搭建ssh(JPA)环境,自动生成dao,model

    &lt;filter-class&gt;org.hibernate.cfg.AnnotationConfiguration &lt;filter-name&gt;hibernateFilter &lt;url-pattern&gt;/* ``` 3. **测试应用**: - 启动应用服务器,访问项目主页进行测试。 - 确认数据库表是否正确...

    hibernate-src.zip源代码包

    `AnnotationConfiguration`或`EnhancedAnnotationConfiguration`可能是其中的一部分,用于处理基于注解的配置。 3. **org.hibernate.boot** 包:这部分涉及Hibernate的启动过程和元数据加载,比如`MetadataSources`...

    spring声明式事务配置

    &lt;property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration"/&gt; ``` 2. **事务管理器**:配置HibernateTransactionManager,它是Spring与Hibernate集成时用于管理事务的关键组件。...

    hibernate 4.3.10 版本的笔记

    - 添加Hibernate 4.3.10的相关库文件(例如:`hibernate-core-4.3.10.Final.jar`等)到自定义库中。 - 对于Hibernate 4.3.10版本,还需要确保项目中包含了对SLF4J的支持。可以访问...

    JAVA 使用hibernate配置实例

    4. 使用SessionFactory:在代码中,通过AnnotationConfiguration或HibernateUtil类加载配置文件并创建SessionFactory。 5. 数据操作:与普通Java工程一致,使用SessionFactory的Session对象进行数据库操作。 在...

    Hibernate API

    Hibernate通过事件监听机制处理对象生命周期的各个阶段,如`PreInsertEvent`、`PostUpdateEvent`等,开发者可以通过实现相应的监听器接口,自定义对象持久化过程的行为。 9. **org.hibernate.criterion package** ...

    hibernate-commons-annotations-5.0.1.Final.jar

    3. `org.hibernate.cfg`:这里的类主要用于配置和初始化Hibernate环境,如`AnnotationConfiguration`类就是配置Hibernate的入口,它会读取注解并生成相应的映射信息。 4. `org.hibernate.boot.model`和`org....

    在hibernate中的数据库操作

    它允许开发人员将Java对象映射到关系型数据库中的表,并支持面向对象的方法来处理数据库操作,从而简化了对数据库的操作。 #### 重要概念解析 **1. Session** - **作用**: `Session` 是 Hibernate 中的核心接口之...

    hibernate-annotations-3.4.0.GA+hibernate-distribution-3.3.2.GA-dist

    1. 支持JPA 1.0:Hibernate 3.3.2不仅支持其自身的API,还完全兼容Java Persistence API (JPA),为开发者提供了更多选择。 2. 性能优化:通过改进缓存机制和查询执行效率,提升了整体性能。 3. 更好的类型安全:引入...

    Hibernate学习教程和笔记

    - **Configuration/AnnotationConfiguration**: 负责读取和解析配置文件。 - **SessionFactory**: 创建`Session`的工厂,每个应用只需一个。 - **Session**: 数据库交互的主要接口,提供CRUD操作方法,如`save()`、`...

Global site tag (gtag.js) - Google Analytics