单表inheritanceWITHOUT Discriminator列

亲爱的同志们,早上好,

这开始变得烦人 – 一件简单的事情,但是几个小时的斗争,我变老了吗?

我试图使用JPA by Hibernate将两个类映射到一个表。 我们的想法是在父类中只有一小部分列,在子类中只有更大/全集。 没有涉及TABLEinheritance,只有类inheritance。 怎么能完成?

这样做不起作用:

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

Hibernate假设默认inheritance策略为InheritanceType.SINGLE_TABLE,并且默认情况下正在寻找鉴别器列 – DTYPE。 但是等等 – 没有表inheritance,鉴别器列没有出现。

我还看了一下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本身,因为它被用于其他地方的持久性。

@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 } 

有几种方法各有其自己的警告。

1)添加注释如下:

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

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

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

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

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

通过使用实体映射xml文件来覆盖所需类的DiscriminatorValue以匹配常量Discriminator’Formula’值,可以将一个类型用于会话并且可以在没有运行时风险的情况下处理,这可以传递到初始配置。

使用有限的列集来查看表,并将第二个类映射到该表。 使用有限的列集定义接口,并使两个类都实现接口。 这可能会让你获得95%的需求。 如果需要,创建方法来定义两者之间的相等性,以及能够将较大的类(通过构造函数?)转换为较小的类。

您必须为两个实体选择inheritance类型。

你想要做的是不合适的,因为hibernate不会知道要实例化的对象。

如果您只需要一个对象拥有较少的字段,那么不要将其映射为实体 – 只需提供一个复制其他类中所有字段的构造函数。