2017-01-16 39 views
0

我正在努力實現兩個類層次之間的雙向多對一映射。與子類和泛型的雙向多對一

我有以下幾點:

超類Queue,與子類AQueueBQueueCQueue。 超類Element,其子類爲AElement,BElement,CElement

AQueueAElement列表,BQueueBElement列表,等等,AElementAQueue等。

我已經試過這樣的事情:

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

只有有Hibernate抱怨mappedBy reference an unknown target entity property

有沒有辦法在使用泛型的超類中映射這種關係,還是我必須選擇每個保持一種關係的子類對?

+0

'Queue'和'Element'類是抽象的還是可以與A,B和C子類一起存在?由於您將'Element'轉換爲泛型類,因此您的聲明可能應該是'class Queue >'class class >' –

+0

它們是抽象的,忘記將其添加到示例類..會修復。 – Tobb

+0

我仍然會接受您提出的更改。 – Tobb

回答

1

這裏的春天開機測試,對我的作品(跳過樣板)(休眠5.0):

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); 
    } 
} 

最重要的事情是修復:

  • 讓所有的仿製藥正確,正確引用
  • 設置targetEntity中的@OneToMany/@ManyToOne關係。否則Hibernate無法確定從通用字段確定什麼應該是實際引用的類。在這裏,通過指定targetEntity = Element.class/targetEntity = Queue.class我們說我們希望Hibernate將它映射到整個實體類層次結構。