【发布时间】:2021-05-28 18:05:03
【问题描述】:
我有以下具有 2 个基类(过滤器和映射)的类结构。
@Entity
public abstract class Filter {
}
@Entity
public class AFilter extends Filter {
}
@Entity
public class BFilter extends Filter {
}
@Entity
public abstract class Map {
public abstract Filter getFilter();
}
@Entity
public class AMap extends Map {
@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
private AFilter filter;
@Override
public AFilter getFilter() {
return filter;
}
public void setFilter(AFilter filter) {
this.filter = filter;
}
}
@Entity
public class BMap extends Map {
@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
private BFilter filter;
@Override
public BFilter getFilter() {
return filter;
}
public void setFilter(BFilter filter) {
this.filter = filter;
}
}
当我查询数据库并且结果集有一个 AMap 的实例时,我得到以下异常:
@Override
public List<Map> getMaps() {
Criteria criteria = dao.getCurrentSession().createCriteria(Map.class);
return criteria.list();
}
org.hibernate.PropertyAccessException:无法设置字段值 [com.xxx.filter.BFilter@6197da84] 反射值:[class com.xxx.map.AMap.filter] com.xxx.map.AMap.filter 的设置器
我尝试稍微调试一下 Hibernate(v5.4.18) 库,不知何故它假定 Map.class 的 filter 属性是 BFilter 的实例,而不是基于 Map 子类类型的动态子类。
这是由 Hibernate 生成的查询(经过编辑以删除额外的字段和连接表):
select this_.id as id2_103_4_, this_.name as name15_103_4_, this_.status as status16_103_4_, this_.filter_id as filter_25_103_4_, this_.DTYPE as dtype1_103_4_, claimfilte5_.id as id2_89_3_, claimfilte5_.companyId as companyi3_89_3_, claimfilte5_.tableName as tablenam5_89_3_, claimfilte5_.zoomLevel as zoomleve6_89_3_ from public.Map this_ left outer join public.Filter claimfilte5_ on this_.filter_id=claimfilte5_.id
查看查询,Hibernate 没有为过滤表选择dtype 列。 => 导致问题。
这是使用 psql 查询的结果:
id2_103_4_ | name15_103_4_ | status16_103_4_ | filter_25_103_4_ | dtype1_103_4_ | id2_89_3_ | companyi3_89_3_ | tablenam5_89_3_ | zoomleve6_89_3_
------------+---------------+-----------------+------------------+---------------+-----------+-----------------+-----------------+-----------------
245921700 | 123123 | t | 245921702 | BMap | 245921702 | 16 | B |
250077365 | Test2 | t | 250077367 | BMap | 250077367 | 4 | B |
250365744 | Test | t | 250365746 | BMap | 250365746 | 0 | B |
250367720 | test3 | f | 250367722 | BMap | 250367722 | 0 | B |
254371277 | gdal new test | t | 254371279 | BMap | 254371279 | 0 | B |
254371748 | test4 | t | 254371750 | AMap | 254371750 | 0 | A |
(6 rows)
当我手动添加 dtype 列时(以显示过滤表上的 dtype 列设置正确):
id2_103_4_ | name15_103_4_ | status16_103_4_ | filter_25_103_4_ | dtype1_103_4_ | id2_89_3_ | companyi3_89_3_ | tablenam5_89_3_ | zoomleve6_89_3_ | dtype
------------+---------------+-----------------+------------------+---------------+-----------+-----------------+-----------------+-----------------+--------------
245921700 | 123123 | t | 245921702 | BMap | 245921702 | 16 | B | | BFilter
250077365 | Test1 | t | 250077367 | BMap | 250077367 | 4 | B | | BFilter
250365744 | Test | t | 250365746 | BMap | 250365746 | 0 | B | | BFilter
250367720 | test3 | f | 250367722 | BMap | 250367722 | 0 | B | | BFilter
254371277 | gdal new test | t | 254371279 | BMap | 254371279 | 0 | B | | BFilter
254371748 | test4 | t | 254371750 | AMap | 254371750 | 0 | A | | AFilter
(6 rows)
如果我使用子类创建条件,我可以毫无问题地查询数据库:
dao.getCurrentSession().createCriteria(AMap.class)
或者
dao.getCurrentSession().createCriteria(BMap.class)
但这不是我想要的。
如何让 Hibernate 识别正确的子类?
【问题讨论】:
-
你有 AFilter 过滤器和 BFilter 过滤器的 getter 和 setter 吗?
-
是的,我愿意。我已更新问题以显示它们。
-
是 Map 和 Filter 抽象类吗?您能否尝试在 Map 中添加方法
public abstract void setFilter(Filter filter); -
是的,它们是抽象类(更新了问题)。不幸的是,即使我添加了抽象设置器,也会出现同样的错误。
-
@nilgun 您如何解决实施问题?你怎么知道是 A 级还是 B 级?
标签: java hibernate single-table-inheritance