这个问题围绕着JPA和Discriminators。
动机:我正在实现一个包含各种字段的系统,这些字段需要一些域值。例如,字段类型(性别类型:男性和女性; ID类型:驾驶执照;大道类型等等)。
由于我的系统是元数据驱动的,因此我不会将这些属性创建为ENUM。我需要它们在一个容易取出的地方。
为了做到这一点,我创建了一个标记为ALNDOMAIN(Alpha Numeric Domains)的父抽象类。并且所有继承的类都将成为我的对象的一部分(例如,IDType扩展了ALNDomain)。
问题:我的系统将有大约200个ALNDomains子类。我不想为每个子类创建一个存储库。我更喜欢在ALNDomain类中有一个存储库并获取Discriminator Value。每当我获取我的域时,鉴别器列将变为NULL:
@Entity
@DiscriminatorColumn(name="ALNNAME", discriminatorType = DiscriminatorType.STRING)
public abstract class ALNDomain {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@Column(name="ALNNAME", insertable = false, updatable = false, nullable = false)
private String alnname;
private String value;
private String description;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getAlnname() {
return alnname;
}
public void setAlnname(String alnname) {
this.alnname = alnname;
}
}
这是子类:
package com.ang.entity.core;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import com.ang.entity.base.domains.ALNDomain;
@Entity
@DiscriminatorValue("IDTYPE")
public class IDType extends ALNDomain {
}
这是我的存储库:
@RepositoryRestResource(collectionResourceRel = "alndomain", path = "alndomain")
@CrossOrigin(maxAge = 3600)
public interface ALNDomainRepository extends PagingAndSortingRepository<ALNDomain, Long>{
List<ALNDomain> findByAlnname(@Param("alnname") String alnname);
}
当我访问我的存储库时,discriminator列为null。这就是结果:
{
"_embedded" : {
"iDTypes" : [ {
**"alnname" : null,**
"value" : "RG",
"description" : "Registro Nacional",
"_links" : {
"self" : {
"href" : "http://localhost:8080/iDType/1"
},
"iDType" : {
"href" : "http://localhost:8080/iDType/1"
}
}
} ]
},
ALNNAME不应为null。我需要它来避免创建200个存储库来访问每种类型的ALNDOMAIN的所有可能值列表。
感谢您的关注。
答案 0 :(得分:0)
您的实体有两个映射到“ALNNAME”列 -
使用@DiscriminatorColumn和指定的类类型 @DiscriminatorValue注释。
alnname属性通过@Column设置只读标记。
这两个映射完全相互独立,在JPA中没有链接。因此,如果从数据库加载实体时将设置alnname,那么在此之前它将不会由JPA设置。
虽然JPA在查询中支持TYPE函数,但Java实例能够获取类名,但这个属性几乎完全是多余的。如果必须将此属性保存在实体中,则最好在创建子类的新实例时设置它,或者改为覆盖子类上的get方法以返回所需的字符串。无法更改实例上的值 - java不允许您将对象从一个类转换为另一个类,因此在JPA中无法创建全新实例。
答案 1 :(得分:0)
我发现的方法是基于Class类型以dinamically方式实例化一个Repository,因为我在Server中。
基本上我替换了我的方法: 列表findByAlnname(@Param(“alnname”)String domainClassName)
执行以下操作:
Class domainClass;
try {
domainClass = ClassLoader.getSystemClassLoader().loadClass(domainClassName);
if (domainClass!=null && ALNDomain.class.isAssignableFrom(domainClass)) {
SimpleJpaRepository<ALNDomain, Long> jpaRep = new SimpleJpaRepository<ALNDomain, Long>(domainClass,em);
return jpaRep.findAll();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}