Hibernate 单表继承 - 作为属性嵌套在子类中的基类抛出 PropertyAccessException

问题描述

我有以下类结构和 2 个基类(Filter 和 Map)。


@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 的 setter

我尝试稍微调试 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 识别正确的子类?

解决方法

还请显示生成的查询。我猜您的数据可能被搞砸了,即您有一个 AMap 指的是 BFilter 而不是 AFilter。也许您需要通过在 @DiscriminatorOptions(force = true) 上注释 Filter 来强制使用鉴别器。

更新:

关键点是字段在子类型中具有不同的名称。 Hibernate 支持隐式向下转换,即可以使用 select m.filter from Map m 并解析向下转换的关联。由于有多种可能的向下转换具有该属性,因此存在冲突。我实际上在 Hibernate 中实现了对这部分的支持,但我猜在那种特殊情况下只是缺少鉴别器。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...