I have a unidirectional one-to-many mapping between the following two entities:
@Entity
@Table(name="INVC_CNTRL")
public class InvoiceControl implements Serializable {
@Id
@Column(name="INVC_CNTRL_ID")
private Long invoiceControlId = null;
...
@OneToMany(fetch = FetchType.LAZY)
private List<UserDefined> userDefineds;
@Entity
@Table(name="USER_DEFINED")
public class UserDefined implements Serializable {
...
@Column(name="USER_DEFINED_TABLE")
private java.lang.String userDefinedTable;
@Column(name="USER_DEFINED_FK")
private long userDefinedForeignKey;
I wrote the following DescriptorCustomizer to address a constant JoinColumn value:
ManyToManyMapping mapping = (ManyToManyMapping) descriptor.getMappingForAttributeName("userDefineds");
if (null != mapping) {
String tableName = descriptor.getTableName();
String primaryKey = descriptor.getPrimaryKeyFields().get(0).getName();
ExpressionBuilder builder = new ExpressionBuilder(mapping.getReferenceClass());
mapping.setSelectionCriteria(builder.getField("USER_DEFINED_FK").equal(builder.getParameter(primaryKey))
.and(builder.getField("USER_DEFINED_TABLE").equal(tableName)));
}
This works as expected with JPQL "select a from InvoiceControl a join fetch a.userDefineds" but when I change the "join fetch" to "left join fetch", I get the following NPE:
Caused by: java.lang.NullPointerException
at org.eclipse.persistence.internal.expressions.SQLSelectStatement.appendFromClauseForOuterJoin(SQLSelectStatement.java:403)
at org.eclipse.persistence.internal.expressions.SQLSelectStatement.appendFromClauseToWriter(SQLSelectStatement.java:521)
at org.eclipse.persistence.internal.expressions.SQLSelectStatement.printSQL(SQLSelectStatement.java:1679)
at org.eclipse.persistence.internal.databaseaccess.DatabasePlatform.printSQLSelectStatement(DatabasePlatform.java:3178)
at org.eclipse.persistence.platform.database.OraclePlatform.printSQLSelectStatement(OraclePlatform.java:932)
at org.eclipse.persistence.internal.expressions.SQLSelectStatement.buildCall(SQLSelectStatement.java:782)
at org.eclipse.persistence.internal.expressions.SQLSelectStatement.buildCall(SQLSelectStatement.java:792)
at org.eclipse.persistence.descriptors.ClassDescriptor.buildCallFromStatement(ClassDescriptor.java:813)
at org.eclipse.persistence.internal.queries.StatementQueryMechanism.setCallFromStatement(StatementQueryMechanism.java:390)
at org.eclipse.persistence.internal.queries.StatementQueryMechanism.prepareSelectAllRows(StatementQueryMechanism.java:315)
at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.prepareSelectAllRows(ExpressionQueryMechanism.java:1721)
at org.eclipse.persistence.queries.ReadAllQuery.prepareSelectAllRows(ReadAllQuery.java:813)
at org.eclipse.persistence.queries.ReadAllQuery.prepare(ReadAllQuery.java:744)
at org.eclipse.persistence.queries.DatabaseQuery.checkPrepare(DatabaseQuery.java:661)
... 8 more
Inspecting the 2.5.1 source, this suggests relationAlias is null.
I've tried a number of things to no avail. If I disable the DescriptorCustomizor and instead add a @JoinColumn on the OneToMany defining half of the join, it works. Of course the result is incorrect because it's failing to discriminate by the table name.
Is this a bug or am I making another JPA noob mistake?
Thanks.