首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > 其他数据库 >

一个数据库表映射成多个Hibernate的实体的有关问题

2012-11-17 
一个数据库表映射成多个Hibernate的实体的问题在最近一个项目中,由于项目管理的不善,导致了开发人员之间的

一个数据库表映射成多个Hibernate的实体的问题

在最近一个项目中,由于项目管理的不善,导致了开发人员之间的相对独立的开发,所以就造成了本来是同一个数据库的表,但是映射成了两个Java类,本来相安无事,但是因为需求变动,造成此表要增加很多字段,本着节省工作的思想,于是在其中一个实体类中增加了成员变量,而由另外一个实体类继承之,由此引出了一下问题:

?

数据库表为test

两个实体类分别为testDomain1和testDomain2,其中testDomain2 extends testDomain1

?

在业务代码中,使用QBC查询testDomain1时的count时,是这么写的:

criteria.setProjection(Projections.rowCount()).uniqueResult();

?

在执行时抛出了异常:

org.hibernate.NonUniqueResultException: query did not return a unique result: 2at org.hibernate.impl.AbstractQueryImpl.uniqueElement(AbstractQueryImpl.java:758)at org.hibernate.impl.CriteriaImpl.uniqueResult(CriteriaImpl.java:431)at com.ibm.b2e.framework.base.dao.BaseDaoImpl.pagedQuery(BaseDaoImpl.java:784)at com.ibm.b2e.framework.base.dao.BaseDaoImpl.pagedQuery(BaseDaoImpl.java:651)

?而看Hibernate打印出的SQL执行了两次select count(*)的操作,于是猜到是表被映射了两次的问题,想从网上查一下解决方法,但是不知道选择什么关键词,只好自己看源代码,

?

发现在uniqueResult()这个方法中调用的是SessionImpl的list(CriteriaImpl criteria)方法

而list()这个方法中调用了sessionFactory的getImplementors(?String className?)方法,这个方法返回的是一个字符串数组,调试发现,它的值正好是我两个实体类的全类名,后面的代码则是根据这两个类名来执行查询,

?

焦点就在sessionFactory的getImplementors(?String className?)中了,马上冲进去一看,发现其中有一个遍历所有已映射对象的循环操作:

while ( iter.hasNext() ) {//test this entity to see if we must query itEntityPersister testPersister = (EntityPersister) iter.next();if ( testPersister instanceof Queryable ) {Queryable testQueryable = (Queryable) testPersister;String testClassName = testQueryable.getEntityName();boolean isMappedClass = className.equals(testClassName);if ( testQueryable.isExplicitPolymorphism() ) {if (isMappedClass) return new String[] { className }; //NOTE EARLY EXIT}else {if (isMappedClass) {results.add(testClassName);}else {final Class mappedClass = testQueryable.getMappedClass( EntityMode.POJO );if ( mappedClass!=null && clazz.isAssignableFrom( mappedClass ) ) {final boolean assignableSuperclass;if ( testQueryable.isInherited() ) {Class mappedSuperclass = getEntityPersister( testQueryable.getMappedSuperclass() ).getMappedClass( EntityMode.POJO);assignableSuperclass = clazz.isAssignableFrom(mappedSuperclass);}else {assignableSuperclass = false;}if (!assignableSuperclass) results.add(testClassName);}}}}}

??看代码的意思,首先是判断当前循环到的class是不是本次查询所查的class,其次再判断Mapped class的一个属性值:testQueryable.isExplicitPolymorphism() 如果此值为true的话,直接就返回一个值只有className的字符串数组;而如果isExplicitPolymorphism()方法返回的值是false的话,那么下面的代码将会继续检查当前循环到的类是否是QBC的类的子类,如果是,则加在字符串数组中一起返回,我所遇到的问题正是后者。

?

看来关键出在isExplicitPolymorphism() 的值上面。

?

查询了Hibernate的sessionFactory初始化代码后,发现此方法的返回值来自于Mapping配置文件,打开Mapping配置文件用代码提示看了一下,<class>元素果然有一个名为polymorphism的属性,此属性有两个候选值:explicit,implicit,在研究此值的实际作用时,发现了JavaEye上原来早已经有一篇文章QBC 解惑,里面很详尽的介绍了此方法,

而对于这样的设计梦秋雨童鞋的解释更是一针见血,非常形象,不得不在此处引用一下:

梦秋雨写道这个事情不用去看实现,仅从对象层面上理解我觉得也能够得出同样的结论。hibernate的管理下应用似乎得到了一个大的对象池,你去查Person,好比和这个对象池的管理员说“把所有的人都叫出来”。当然会返回池中所有的Person,如果不是,那么,你还当学生是人么?

类比,查询Object类的对象,好比说“芸芸众生啊,都来举个手”,结果可想而知。

?

强人啊强人。。强人啊强人。。。(此处重复30遍)

热点排行