Having one abstract class NodeBase
and several extending classes (NodeAnnounce
, NodeTransfer
, ...), I'd like to apply inheritance with JPA's annotation @Inheritance
and @DiscriminatorColumn
.
Here are my classes (I condensed it a bit, it's not my style though getters and setters are obvious anyway):
@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; }
}
One inheriting class (only an example)
@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; }
}
I'm now calling the named query previously defined
NodeBase nodeBase =
(NodeBase) em.createNamedQuery("NodeBase.findByTarget")
.setParameter("targetID", target.getId())
.getSingleResult();
I can assure target
isn't null and the id it returns is existing. In the above function call, a pretty long exception is thrown:
[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)
(...)
This line of the stack trace looks strange to me:
SELECT DISTINCT node_base.nodeType FROM target t0, node_base t1 WHERE ((t0.ID = ?) AND (t0.FIRSTNODE = t1.ID))
Why is t0.ID = ?
? It shouldn't.
I know, it's yet another The multi-part identifier
question. But I think it is related to JPA. The field nodeType
in the database has a relation to the table node_type
- which I'm not using in my Java project. But the value of the field is important anyway.
The backend is SQL Server. Here the relevant table definition:
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]