Avoir une classe abstraite NodeBase
et plusieurs classes s'étendant (NodeAnnounce
, NodeTransfer
, ...), je voudrais appliquer l'héritage avec l'annotation de JPA @Inheritance
et @DiscriminatorColumn
.JPA « L'identifiant plusieurs parties ... ne pouvait pas être lié »
Voici mes cours (je condensé un peu, ce n'est pas mon style mais accesseurs sont évidents quand même):
@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; }
}
Une classe héritant (seulement un exemple)
@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; }
}
Je suis maintenant appeler la requête nommée précédemment définie
NodeBase nodeBase =
(NodeBase) em.createNamedQuery("NodeBase.findByTarget")
.setParameter("targetID", target.getId())
.getSingleResult();
Je peux assurer target
n'est pas nul et l'identifiant qu'il renvoie est existant. Dans l'appel de fonction ci-dessus, est jeté une exception assez longue:
[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)
(...)
Cette ligne de la trace de la pile semble étrange pour moi:
SELECT DISTINCT node_base.nodeType FROM target t0, node_base t1 WHERE ((t0.ID = ?) AND (t0.FIRSTNODE = t1.ID))
Pourquoi t0.ID = ?
? Ça ne devrait pas. Je sais, c'est encore une autre question de The multi-part identifier
. Mais je pense que c'est lié à JPA. Le champ nodeType
dans la base de données a une relation avec la table node_type
- que je n'utilise pas dans mon projet Java. Mais la valeur du champ est importante de toute façon.
Le serveur principal est SQL Server. Voici la définition de table pertinente:
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]
Ce est juste un coup dans le noir, mais peut-être votre requête findByTarget devrait commencer comme 'SELECT OBJECT (n) FROM NodeBase n'. Et 't0.ID =?' Est simplement le SQL généré pour le paramètre: targetID. –
Pourriez-vous également montrer la partie de la cible qui se rapporte à la base du nœud? Et donnez également la version d'EclipseLink que vous utilisez. – lpiepiora