Pet*_*ete 5 java inheritance hibernate single-table-inheritance querydsl
我们对应用程序中的每个表使用单表继承.这允许同一应用程序堆栈的不同实例与相同的DAO一起工作,而它们的实体可能略有不同,可能包含该实例特有的信息.抽象类定义基本表结构,如果该实例需要,扩展定义其他列:
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Table(name = "client")
public abstract class Client extends AbstractPersistable<Long> {
// ...
}
Run Code Online (Sandbox Code Playgroud)
申请A:
@Entity
public class ClientSimple extends Client {
private String name;
// getter, setter
}
Run Code Online (Sandbox Code Playgroud)
申请B:
@Entity
public class ClientAdvanced extends Client {
private String description;
// getter, setter
}
Run Code Online (Sandbox Code Playgroud)
现在DAO可以处理Client应用程序A和B的对象,但是应用程序B可以为其客户端对象定义其他信息,这些信息可以由应用程序B特有的管理器方法读取:
申请A:
Client client = new ClientSimple();
clientDao.save(client);
Run Code Online (Sandbox Code Playgroud)
申请B:
Client client = new ClientAdvanced();
clientDao.save(client);
Run Code Online (Sandbox Code Playgroud)
不幸的是,这意味着每个表中都有一个DTYPE列(或者我可能选择的任何其他名称).有没有办法摆脱这个?我们不需要它,它正在耗尽数据库空间......
谢谢!
编辑
重要提示:@MappedSuperclass不起作用.我们使用QueryDSL作为我们的HQL抽象层.这需要为类型保存查询自动生成查询类型类.但是,只有在使用注释抽象类时才会正确生成这些@Entity.
这是必要的,因为我们想Client在实际查询ClientSimple应用程序A和ClientAdvanced应用程序B时查询抽象类:
所以在任何应用程序中都可以使用:
query.where(QClient.client.name.equals("something");
Run Code Online (Sandbox Code Playgroud)
在应用程序B中,这将起作用:
query.where(QClientSimple.client.description.equals("something else");
Run Code Online (Sandbox Code Playgroud)
编辑2 - 归结为
它似乎可以归结为:我可以在部署时配置hibernate,以将已设置实体的鉴别器类型设置为固定值.因此,使用我的示例a Client将始终ClientSimple在一个应用程序中,而在另一个应用程序ClientAdvanced中,以便我不必将该信息存储在数据库中?
就像我说的:每个应用程序都将是基本应用程序堆栈的一个实例.每个应用程序可能为其本地数据库定义其他列,但所有对象与该实例的类型相同,因此我们保证鉴别器始终相同,使其在数据库中成为冗余,并且是hibernate配置的用例.
我知道,这是一个非常古老的问题,但我最近遇到了这个问题,这可能对某人有用.
这可以使用Hibernate的@DiscriminatorFormula注释来完成.以下描述基于Java Persistence with Hibernate一书,第5.1.3节; 相关部分从第202页最后一段的页面开始.
使用@DiscriminatorFormula,您可以提供一个SQL语句,用于确定discriminator从数据库中获取相关行的while 值.在您的情况下,它必须是一个简单的字符串,评估一些任意选择的值.为此,您需要确定将用于您的Client实体的名称.假设您选择'GenericClient'作为.的名称entity.这是应@Entity作为name属性值出现在注释中的名称.因此,完整的示例,在您的情况下将如下所示.
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Table(name = "client")
@DiscriminatorFormula("'GenericClient'") // *1*
public abstract class Client extends AbstractPersistable<Long> {
// ...
}
// Application A
@Entity
@DiscriminatorValue("GenericClient") // *2*
public class SimpleClient extends Client {
// ...
}
// Application B
@Entity
@DiscriminatorValue("GenericClient") // *3*
public class AdvancedClient extends Client {
// ...
}
Run Code Online (Sandbox Code Playgroud)
由' 1 ' 表示的行是SQL片段的一部分,它将始终返回'GenericClient'作为其值.该subclasses的Client应该始终与注解@DiscriminatorValue("GenericClient").这意味着当Hibernate从DB中获取行时,要构造的对象的类型将始终是特定的子类Client.
如果Client驻留子类的包和子类的名称是固定的:
在这种情况下,@DiscriminatorValue("GenericClient")不需要子类,您需要做的就是:
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Table(name = "client")
@DiscriminatorFormula("'com.example.fixed.path.FixedSubClassName'")
public abstract class Client extends AbstractPersistable<Long> {
// ...
}
Run Code Online (Sandbox Code Playgroud)
子类不需要任何注释.该discriminator-value默认为entity-name,这本身默认为完全合格的类名.
注:该SQL内部的语句@DiscriminatorFormula()可以是任何有效的SQL为您的目标数据库服务器的语句.
| 归档时间: |
|
| 查看次数: |
7576 次 |
| 最近记录: |