没有鉴别器列的单个表继承

2022-09-01 14:31:03

早上好,我亲爱的同志们,

这开始变得烦人 - 一件简单的事情,但几个小时的挣扎,我变老了吗?

我正在尝试使用Hibernate的JPA将两个类映射到单个表。这个想法是在父类中只有一小部分列,在子类中具有更大/完整的列集。不涉及表继承,仅涉及类继承。如何做到这一点??

这样做将不起作用:

@Entity
@Table(name = "the_table")
class Parent implements Serializable {
}

@Entity
@Table(name = "the_table")
class Child extends Parent implements Serializable {
}

休眠假定默认继承策略InheritanceType.SINGLE_TABLE,并且默认情况下正在查找鉴别器列 - DTYPE。但是等等 - 没有表继承,具有鉴别器列不会有意义。

我还看了一下PolymorphismType.EXPLICIT,它没有任何区别。堆栈跟踪为:

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'apprentice0_.DTYPE' in 'where clause'
   at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
   at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
   at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
   at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
   at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
   at com.mysql.jdbc.Util.getInstance(Util.java:386)
   at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1052)
   at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3597)
   at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3529)
   at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1990)
   at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2151)
   at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2625)
   at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2119)
   at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2281)
   at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeQuery(NewProxyPreparedStatement.java:76)
   at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
   at org.hibernate.loader.Loader.getResultSet(Loader.java:1808)
   at org.hibernate.loader.Loader.doQuery(Loader.java:697)
   at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
   at org.hibernate.loader.Loader.loadEntity(Loader.java:1881)

是的,还有一件事:

和 是没有用的,因为它们不能与 - 父类必须是一个本身,因为它被用于其他地方的持久性。@MappedSuperclass@Embeddable@Entity@Entity


答案 1

@MappedSuperclass是必须使用的批注。如果同一类既是映射的超类又是实体,则只需将其拆分为两个类:

@MappedSuperclass
public class Parent {
    // ...
}

@Entity
public class ParentEntity extends Parent {
    // no code at all here
}

@Entity
public class Child extends Parent {
    // additional fields and methods here
}

答案 2

有几种方法,每种方法都有自己的警告。

1) 添加注释,如下所示:

@DiscriminatorFormula("0")
@DiscriminatorValue("0")
class BaseClass{  }

@DiscriminatorValue("00")
class SubClass extends BaseClass{  }

其中,子类鉴别器值必须与基类不同,但在传递到 Integer.valueOf(String s) 方法时,其计算结果也必须为相同值。

警告 - 如果您从基类的Hibernate返回一个对象,然后在调用子类类型时再次返回,您将收到一个错误,抱怨加载的对象属于错误的类。但是,如果先调用子类查询,则基类调用将返回子类。

2) 使用数据库中的视图来映射表,并将其用作子类的表。实际上,它可以是与列映射匹配的任何其他类,因为Hibernate认为它是一个完全独立的表。

警告 - 您可能会将同一行实例化为两个不同的对象,这两个对象不会同步,并可能导致数据库更新冲突/丢失。

最好是坚持使用会话的一种类型,并且可以通过使用实体映射xml文件来处理该类型,该文件将覆盖所需类的ConsiorValue以匹配常量Consior'Formula'值,您可以将其传递到初始配置中。


推荐