`
taowen
  • 浏览: 190619 次
  • 性别: 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简单测试

    测试: @Test public void create() { new SchemaExport(new AnnotationConfiguration().configure()).create(true, true); }

    hibernate2

    Hibernate Annotation简单应用 接着上次的程序我们将其改为Annotation版本的...SessionFactory factory = new AnnotationConfiguration().configure() .buildSessionFactory(); 这时,我们就可以运行这个测试类了。

    java-session-generic-dao:用于 Hibernate ORM (JSE) 的通用数据访问对象的非常简单的实现

    在这个实现中,我们使用通过 AnnotationConfiguration 从 hibernate.cfg.xml 文件创建的 Hibernate ORM Session 来实现基本操作,例如从数据库中插入、更新、删除和检索实体。 这种实现的主要优点是,由于这个 dao ...

    TCABEE 008-2020 轨道交通车站高效空调系统技术标准.docx

    TCABEE 008-2020 轨道交通车站高效空调系统技术标准.docx

    node-v5.12.0-x86.msi

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    基于阿里云的 ECS 部署 Ghost 博客内含源码以及说明书可以自己运行复现.zip

    基于阿里云的 ECS 部署 Ghost 博客内含源码以及说明书可以自己运行复现.zip

    2023-04-06-项目笔记 - 第一百二十六阶段 - 4.4.2.124全局变量的作用域-124 -2024.05.07

    2023-04-06-项目笔记-第一百二十六阶段-课前小分享_小分享1.坚持提交gitee 小分享2.作业中提交代码 小分享3.写代码注意代码风格 4.3.1变量的使用 4.4变量的作用域与生命周期 4.4.1局部变量的作用域 4.4.2全局变量的作用域 4.4.2.1全局变量的作用域_1 4.4.2.124全局变量的作用域_124 - 2024-05-07

    node-v10.4.1-linux-armv7l.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    66297787762147sf22346mod.apk

    66297787762147sf22346mod.apk

    对k8s的client的封装

    对k8s的client的封装

    node-v7.7.3-linux-x64.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    Java学习路线逐步成为资深的Java专家.pdf

    上文对于初学者学习Java具有非常重要的指导作用。以下是对初学者学习Java的具体作用: 明确学习方向: 学习路线为初学者提供了一个清晰的学习方向,使他们能够系统地掌握Java从基础到进阶再到企业级开发的核心知识和技能。这有助于初学者避免在学习过程中迷失方向,减少无效学习的时间。 阶梯式学习: 学习路线按照从易到难的顺序,将Java知识划分为不同的阶段,每个阶段都有明确的学习目标和内容。这种阶梯式的学习方式有助于初学者逐步建立起对Java的深入理解和应用能力,提高学习效率。 理论与实践相结合: 学习路线不仅包含了理论知识的学习,还强调了实践项目的重要性。通过实践项目,初学者可以将所学知识应用到实际开发中,加深对知识的理解和掌握。这种理论与实践相结合的学习方式有助于培养初学者的动手能力和解决问题的能力。 技能拓展与提升: 学习路线不仅涵盖了Java语言的基础和进阶知识,还涉及了Java Web开发、企业级开发、性能优化与分布式系统等高级主题。这些高级主题的学习有助于初学者拓展自己的技能范围,提升在Java领域的竞争力。 激发学习兴趣: 通过不断挑战自己,尝试构建更复杂的项目或系

    2024-2030中国SDS-PAGE蛋白质分析市场现状研究分析与发展前景预测报告.docx

    2024-2030中国SDS-PAGE蛋白质分析市场现状研究分析与发展前景预测报告

    node-v9.0.0-darwin-x64.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    遥感图像滤波处理(去除条带噪声、PCA变换、数据融合、图像平滑、图像锐化)

    1.1 实习目的 1) 掌握图像滤波的基本定义及目的。 2) 掌握进行图像的空间域滤波、频率域滤波的基本原理及方法。 3) 掌握傅立叶变换及逆变换的基本原理方法。 4) 掌握主成分变换的基本原理方法。 5) 学习图像融合和图像锐化基本处理。 1.2 实习内容 1) 使用频率域滤波去除spot周期性条带。 2) 使用波段运算计算大气校正结果的NDVI、NDWI、NDBI。 3) 使用L7数据做PCA变换,查看各主成分信息,使用前三波段进行数据压缩。 4) 使用L7和pan做数据融合。 5) 使用IKONOS数据做高斯噪声和椒盐噪声的去除,比较不同滤波方法的差异,不同尺寸的影响。 6) 使用IKONOS数据做图像锐化,分别使用Robert、SOBEL、Laplacian算子和方向滤波进行处理。

    node-v7.10.0-sunos-x64.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    JDBC 入门教程内含源码以及说明书可以自己运行复现.zip

    JDBC 入门教程内含源码以及说明书可以自己运行复现.zip

    node-v8.11.3-linux-armv7l.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    Microsoft365-E5-Renew-Plus-with-runtime.rar

    Microsoft365-E5-Renew-Plus-with-runtime.rar

    基于java的个人博客项目,支持文章发布和管理

    一个个人博客项目。适合用于个人或小型团队分享知识和经验。特点是可以提供一个简洁的博客平台,支持文章发布和管理。 数据库文件目录为static-files/my_blog_db.sql; 部署后你可以根据自己需求修改版权文案、logo 图片、备案记录等网站基础信息; My Blog 后台管理系统的默认登陆账号为 admin 默认登陆密码为 123456;

Global site tag (gtag.js) - Google Analytics