Java 具有子类和泛型的双向多对一

Java 具有子类和泛型的双向多对一,java,hibernate,jpa,Java,Hibernate,Jpa,我正在努力实现两个类层次结构之间的双向多对一映射 我有以下资料: 超类Queue,带有子类AQueue,BQueue,CQueue。 超类元素,带有子类aeelement,BElement,celelement AQueue有一个aeelement列表,BQueue有一个BElement列表,依此类推,aeelement有一个AQueue列表,依此类推 我试过这样的方法: @Entity @Inheritance(strategy InheritanceType.SINGLE_TABLE) pu

我正在努力实现两个类层次结构之间的双向多对一映射

我有以下资料:

超类
Queue
,带有子类
AQueue
BQueue
CQueue
。 超类
元素
,带有子类
aeelement
BElement
celelement

AQueue
有一个
aeelement
列表,
BQueue
有一个
BElement
列表,依此类推,
aeelement
有一个
AQueue
列表,依此类推

我试过这样的方法:

@Entity
@Inheritance(strategy InheritanceType.SINGLE_TABLE)
public abstract class Queue<T extends Element> {
    @OneToMany(mappedBy="queue")
    private List<T> elements = new ArrayList<>();
    //...
}

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Element<T extends Element> {
    @ManyToOne
    @JoinColumn("queue_id")
    private Queue<T> queue;
}
@实体
@继承(strategy InheritanceType.SINGLE_表)
公共抽象类队列{
@OneToMany(mappedBy=“队列”)
私有列表元素=新的ArrayList();
//...
}
@实体
@继承(策略=InheritanceType.JOINED)
公共抽象类元素{
@许多酮
@JoinColumn(“队列id”)
专用队列;
}
只有
Hibernate
投诉
mappedBy引用未知的目标实体属性

有没有一种方法可以使用泛型在超类中映射这样的关系,或者我必须选择每个子类对,每个子类对维护一个关系

这里有一个适合我的Spring启动测试(跳过样板文件)(Hibernate 5.0):

import java.util.ArrayList;
导入java.util.List;
导入javax.persistence.Entity;
导入javax.persistence.EntityManager;
导入javax.persistence.Id;
导入javax.persistence.heritation;
导入javax.persistence.InheritanceType;
导入javax.persistence.manytone;
导入javax.persistence.OneToMany;
导入javax.transaction.Transactional;
导入org.junit.Test;
导入org.junit.runner.RunWith;
导入org.springframework.beans.factory.annotation.Autowired;
导入org.springframework.boot.test.context.SpringBootTest;
导入org.springframework.test.context.junit4.SpringRunner;
导入静态org.assertj.core.api.Assertions.*;
@春靴测试
@RunWith(SpringRunner.class)
公共类JpaTest{
@自动连线
私人实体管理者;
@试验
@交易的
公开无效测试(){
QueueA QueueA=新队列A(1L);
ElementA ElementA=新的ElementA(1L,队列A);
queueA.getElements().add(elementA);
em.persist(queueA);
em.persist(elementA);
QueueB QueueB=新队列b(2L);
ElementB ElementB=新的ElementB(2L,队列B);
queueB.getElements().add(elementB);
em.persist(queueB);
em.persist(elementB);
List queues=em.createQuery(“从队列q中选择q”).getResultList();
资产(队列)。仅包含(队列A、队列B);
List elements=em.createQuery(“从元素e中选择e”).getResultList();
资产(要素)。仅包含(要素A、要素B);
}
}
@实体
@继承(策略=InheritanceType.SINGLE_表)
抽象类队列{
@身份证
私人长id;
@OneToMany(mappedBy=“queue”,targetEntity=Element.class)
私有列表元素=新的ArrayList();
公共队列(长id){
this.id=id;
}
公共长getId(){
返回id;
}
公共无效集合id(长id){
this.id=id;
}
公共列表getElements(){
返回元素;
}
公共void集合元素(列表元素){
这个元素=元素;
}
}
@实体
@继承(策略=InheritanceType.JOINED)
抽象类元素{
@身份证
私人长id;
@manytone(targetEntity=Queue.class)
专用队列;
公共元素(长id,队列){
this.id=id;
this.queue=队列;
}
公共长getId(){
返回id;
}
公共无效集合id(长id){
this.id=id;
}
公共队列getQueue(){
返回队列;
}
公共无效集合队列(队列队列){
this.queue=队列;
}
}
@实体
类QueueA扩展了队列{
公用队列A(长id){
超级(id);
}
}
@实体
类ElementA扩展元素{
公共元素A(长id,队列){
超级(id,队列);
}
}
@实体
类QueueB扩展了队列{
公共队列B(长id){
超级(id);
}
}
@实体
类ElementB扩展元素{
公共元素B(长id,队列){
超级(id,队列);
}
}
需要解决的重要问题是:

  • 使所有泛型正确并正确地相互引用
  • @OneToMany/@ManyToOne
    关系中设置
    targetEntity
    。否则,Hibernate无法仅从泛型字段确定实际引用的类。这里,通过指定
    targetEntity=Element.class
    /
    targetEntity=Queue.class
    ,我们想让Hibernate将其映射到整个实体类层次结构
    • 这里有一个适合我的Spring引导测试(跳过样板文件)(Hibernate 5.0):

      import java.util.ArrayList;
      导入java.util.List;
      导入javax.persistence.Entity;
      导入javax.persistence.EntityManager;
      导入javax.persistence.Id;
      导入javax.persistence.heritation;
      导入javax.persistence.InheritanceType;
      导入javax.persistence.manytone;
      导入javax.persistence.OneToMany;
      导入javax.transaction.Transactional;
      导入org.junit.Test;
      导入org.junit.runner.RunWith;
      导入org.springframework.beans.factory.annotation.Autowired;
      导入org.springframework.boot.test.context.SpringBootTest;
      导入org.springframework.test.context.junit4.SpringRunner;
      导入静态org.assertj.core.api.Assertions.*;
      @春靴测试
      @RunWith(SpringRunner.class)
      公共类JpaTest{
      @自动连线
      私人实体管理者;
      @试验
      @交易的
      公开无效测试(){
      QueueA QueueA=新队列A(1L);
      ElementA ElementA=新的ElementA(1L,队列A);
      queueA.getElements().add(elementA);
      em.persist(queueA);
      埃姆波斯
      
      import java.util.ArrayList;
      import java.util.List;
      import javax.persistence.Entity;
      import javax.persistence.EntityManager;
      import javax.persistence.Id;
      import javax.persistence.Inheritance;
      import javax.persistence.InheritanceType;
      import javax.persistence.ManyToOne;
      import javax.persistence.OneToMany;
      import javax.transaction.Transactional;
      
      import org.junit.Test;
      import org.junit.runner.RunWith;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.boot.test.context.SpringBootTest;
      import org.springframework.test.context.junit4.SpringRunner;
      
      import static org.assertj.core.api.Assertions.*;
      
      @SpringBootTest
      @RunWith(SpringRunner.class)
      public class JpaTest {
      
          @Autowired
          private EntityManager em;
      
          @Test
          @Transactional
          public void test() {
              QueueA queueA = new QueueA(1L);
              ElementA elementA = new ElementA(1L, queueA);
              queueA.getElements().add(elementA);
              em.persist(queueA);
              em.persist(elementA);
      
              QueueB queueB = new QueueB(2L);
              ElementB elementB = new ElementB(2L, queueB);
              queueB.getElements().add(elementB);
              em.persist(queueB);
              em.persist(elementB);
      
              List queues = em.createQuery("SELECT q FROM Queue q").getResultList();
      
              assertThat(queues).containsOnly(queueA, queueB);
      
              List elements = em.createQuery("SELECT e FROM Element e").getResultList();
      
              assertThat(elements).containsOnly(elementA, elementB);
          }
      }
      
      @Entity
      @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
      abstract class Queue<T extends Element<T>> {
      
          @Id
          private Long id;
      
          @OneToMany(mappedBy = "queue", targetEntity = Element.class)
          private List<T> elements = new ArrayList<>();
      
          public Queue(Long id) {
              this.id = id;
          }
      
          public Long getId() {
              return id;
          }
      
          public void setId(Long id) {
              this.id = id;
          }
      
          public List<T> getElements() {
              return elements;
          }
      
          public void setElements(List<T> elements) {
              this.elements = elements;
          }
      }
      
      @Entity
      @Inheritance(strategy = InheritanceType.JOINED)
      abstract class Element<T extends Element<T>> {
      
          @Id
          private Long id;
      
          @ManyToOne(targetEntity = Queue.class)
          private Queue<T> queue;
      
          public Element(Long id, Queue<T> queue) {
              this.id = id;
              this.queue = queue;
          }
      
          public Long getId() {
              return id;
          }
      
          public void setId(Long id) {
              this.id = id;
          }
      
          public Queue<T> getQueue() {
              return queue;
          }
      
          public void setQueue(Queue<T> queue) {
              this.queue = queue;
          }
      }
      
      @Entity
      class QueueA extends Queue<ElementA> {
      
          public QueueA(Long id) {
              super(id);
          }
      }
      
      @Entity
      class ElementA extends Element<ElementA> {
      
          public ElementA(Long id, Queue<ElementA> queue) {
              super(id, queue);
          }
      }
      
      @Entity
      class QueueB extends Queue<ElementB> {
      
          public QueueB(Long id) {
              super(id);
          }
      }
      
      @Entity
      class ElementB extends Element<ElementB> {
      
          public ElementB(Long id, Queue<ElementB> queue) {
              super(id, queue);
          }
      }