Hibernate single table inheritance - base class 嵌套为 属性 inside a subclass throws PropertyAccessException

Hibernate single table inheritance - base class nested as a property inside a subclass throws PropertyAccessException

我有以下 class 结构,其中包含 2 个基础 classes(过滤器和映射)。


@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: Could not set field value [com.xxx.filter.BFilter@6197da84] value by reflection : [class com.xxx.map.AMap.filter] setter of com.xxx.map.AMap.filter

我尝试稍微调试一下 Hibernate(v5.4.18) 库,它以某种方式假定 Map.class 的 filter 属性 是 BFilter 的实例,而不是基于 Map subclass 类型的动态 subclass.

这是 Hibernate 生成的查询(已编辑以删除额外字段并加入 tables):

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 没有 select 过滤器 table 的 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 列已在过滤器 table 上正确设置):

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)

如果我使用 subclasses 创建条件,我可以毫无问题地查询数据库: dao.getCurrentSession().createCriteria(AMap.class) 要么 dao.getCurrentSession().createCriteria(BMap.class)

但这不是我想要的。

如何让 Hibernate 识别正确的子class?

还请显示生成的查询。我猜你的数据可能被弄乱了,即你有一个 AMap 指的是 BFilter 而不是 AFilter。也许您需要通过在 Filter.

上注释 @DiscriminatorOptions(force = true) 来强制使用鉴别器

更新:

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