2014-05-02 19 views
3

有一個抽象類NodeBase和幾個擴展類(NodeAnnounceNodeTransfer,...),我想與JPA的註解@Inheritance@DiscriminatorColumn申請繼承。JPA「的多部分標識符......無法綁定」

這裏是我的課(我凝聚了一點,這不是我的風格,雖然getter和setter方法是顯而易見的反正):

@Entity 
@Inheritance(strategy=InheritanceType.JOINED) 
@DiscriminatorColumn(name="nodeType") 
@Table(name="node_base") 
@NamedQueries({ 
    @NamedQuery(name="NodeBase.findAll", query="SELECT n FROM NodeBase n"), 
    @NamedQuery(name="NodeBase.findByTarget", query="SELECT n FROM NodeBase n JOIN Target t ON t.firstNode = n.id WHERE t.id = :targetID") 
}) 
public abstract class NodeBase implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    private int id; 
    private int customer; 
    private String exitNames; 
    private int nodeType; 
    private int diagramPosX; 
    private int diagramPosY; 

    public NodeBase() {} 

    public int getId() { return this.id; } 
    public void setId(int id) { this.id = id; } 

    public int getCustomer() { return this.customer; } 
    public void setCustomer(int customer) { this.customer = customer;} 

    public String getExitNames() { return this.exitNames; } 
    public void setExitNames(String exitNames) { this.exitNames = exitNames; } 

    public int getDiagramPosX() { return diagramPosX; } 
    public void setDiagramPosX(int diagramPosX) { this.diagramPosX = diagramPosX; } 

    public int getDiagramPosY() { return diagramPosY; } 
    public void setDiagramPosY(int diagramPosY) { this.diagramPosY = diagramPosY; } 

    public int getNodeType() { return nodeType; } 
    public void setNodeType(int nodeType) { this.nodeType = nodeType; } 
} 

一個繼承類(只是一個例子)

@Entity 
@Table(name="node_announce") 
@DiscriminatorValue(value="2") 
@NamedQuery(name="NodeAnnounce.findAll", query="SELECT n FROM NodeAnnounce n") 
public class NodeAnnounce extends NodeBase implements Serializable { 
    private static final long serialVersionUID = 1L; 

    private String wavefile; 

    public NodeAnnounce() {} 

    public String getWavefile() { return this.wavefile; } 
    public void setWavefile(String wavefile) { this.wavefile = wavefile; } 
} 

我現在撥打以前定義的指定查詢

NodeBase nodeBase = 
(NodeBase) em.createNamedQuery("NodeBase.findByTarget") 
    .setParameter("targetID", target.getId()) 
    .getSingleResult(); 

我可以保證target不爲空,它返回的ID是存在的。在上面的函數調用,一個相當長的異常被拋出:

[EL Warning]: 2014-05-02 18:39:31.287--UnitOfWork(138297553)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DatabaseException 
Internal Exception: com.microsoft.sqlserver.jdbc.SQLServerException: The multi-part identifier "node_base.nodeType" could not be bound. 
Error Code: 4104 
Call: SELECT DISTINCT node_base.nodeType FROM target t0, node_base t1 WHERE ((t0.ID = ?) AND (t0.FIRSTNODE = t1.ID)) 
    bind => [1 parameter bound] 
Query: ReadObjectQuery(name="NodeBase.findByTarget" referenceClass=NodeBase sql="SELECT DISTINCT node_base.nodeType FROM target t0, node_base t1 WHERE ((t0.ID = ?) AND (t0.FIRSTNODE = t1.ID))") 
    at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:340) 
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:679) 
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:558) 
    (...) 
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: The multi-part identifier "node_base.nodeType" could not be bound. 
    at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:216) 
    at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1515) 
    (...) 

堆棧跟蹤的這行看起來很奇怪對我說:

SELECT DISTINCT node_base.nodeType FROM target t0, node_base t1 WHERE ((t0.ID = ?) AND (t0.FIRSTNODE = t1.ID)) 

爲什麼t0.ID = ??它不應該。

我知道,這是另一個The multi-part identifier的問題。但我認爲這與JPA有關。 數據庫中的字段nodeType與表node_type有關係 - 我沒有在我的Java項目中使用該表。但是這個領域的價值無論如何都是重要的。

後端是SQL Server。這裏的相關表定義:

CREATE TABLE [dbo].[node_base](
    [id] [int] IDENTITY(1,1) NOT NULL, 
    [nodeType] [int] NOT NULL, 
    [exitNames] [varchar](20) NOT NULL, 
    [customer] [int] NOT NULL, 
    [diagramPosX] [int] NULL, 
    [diagramPosY] [int] NULL, 
CONSTRAINT [PK_node_base] PRIMARY KEY CLUSTERED 
(
    [id] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 
+0

此只是在黑暗中拍攝的,但也許你的findByTarget查詢應該以'SELECT OBJECT(n)FROM NodeBase n'開始。 't0.ID =?'就是爲targetID參數生成的SQL。 –

+0

你也可以顯示目標的部分與節點基地有關嗎?並且還提供您正在使用的EclipseLink版本。 – lpiepiora

回答

2

正如在評論中提及,在您的查詢的問題是不是與t0.ID = ?,因爲這是從JPQL SELECT n FROM NodeBase n JOIN Target t ON t.firstNode = n.id WHERE t.id = :targetID預期。問題是,當查詢NodeBase時,EclipseLink首先會檢查要從查詢返回的所有子類,因此只選擇DiscriminatorColumn「nodeType」。這將返回由於繼承而需要構建的所有子類,然後EclipseLink將用於後續查詢。
不幸的是,你正在繼承EclipseLink bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=344721

我的解決方法是讓EclipseLink使用外連接策略來引入子類而不是單獨的查詢。這允許使用單個查詢被帶到一切,並且可以使用定製工具如這裏所描述進行配置:https://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Entities/Inheritance#Outer_Joining_Subclasses

的優點和使用一個查詢VS繼承多個查詢的缺點在此討論:http://en.wikibooks.org/wiki/Java_Persistence/Inheritance

相關問題