Search code examples
jpaeclipselink

JPA The state field path cannot be resolved to a valid type


I need assistance in troubleshooting a relationship / query with EclipseLink 2.5.x provider.

The relationship from ThreePhaseMotorInput to ValidationMessage is supposed to be a uni-directional OneToMany, i.e. each motor can have 0..n messages and in Java object graph ValidationMessage does not have a reference back to ThreePhaseMotorInput.

I am getting an error that JPA can't find the attributes that are part of the ValidationMessage class when accessed via ThreePhaseMotor. (See error text below)

Thanks for thinking about my question!

Query

select msg.validationMsg, COUNT(m.id) from ThreePhaseMotorInput AS m JOIN m.valMessages AS msg GROUP BY msg.validationMsg

Error

 org.eclipse.persistence.exceptions.JPQLException: 
Exception Description: Problem compiling [select msg.validationMsg, COUNT(m.id) from ThreePhaseMotorInput AS m JOIN m.valMessages AS msg GROUP BY msg.validationMsg]. 
[7, 24] The state field path 'msg.validationMsg' cannot be resolved to a valid type.
[71, 84] The collection-valued path 'm.valMessages' cannot be resolved to a valid association field.
[119, 136] The state field path 'msg.validationMsg' cannot be resolved to a valid type.

ThreePhaseMotorInput class

@Entity
@Table(name = "three_phase_motor_input")
public class ThreePhaseMotorInput implements IThreePhaseMotorInput, Serializable {
    private static final long serialVersionUID = 8084370807289186987L;
    @Transient
    private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Version
    private Integer version;
    private Integer status;
    @Transient
    private Integer numMessages;

    @OneToOne(cascade = CascadeType.ALL, optional = true, targetEntity = UnapprovedThreePhaseMotor.class)
    @JoinColumn(name = "unapproved_id")
    private IThreePhaseMotor unapprovedMotor;

    @OneToOne(cascade = CascadeType.ALL, optional = true, targetEntity = ApprovedThreePhaseMotor.class)
    @JoinColumn(name = "approved_id")
    private IThreePhaseMotor approvedMotor;

    @OneToMany(orphanRemoval = true, cascade = CascadeType  .ALL, fetch = FetchType.LAZY, targetEntity = ValidationMessage.class)
    @JoinColumn(name = "input_id", referencedColumnName = "id", nullable = false)
    @OrderColumn(name = "idx")
    private List<IValidationMessage> valMessages;

ValidationMessage class

@Entity
@Table(name = "validation_message")
public class ValidationMessage implements Serializable, IValidationMessage {
    private static final long serialVersionUID = 8765213112015434057L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(name = "record_id")
    private Long recordId;
    @Column(name = "field_name")
    private String fieldName;
    @Column(name = "validation_msg")
    private String validationMsg;
    private Integer status;
    @Column(name = "fail_field")
    private String failField;
    @Column(name = "error_source")
    private Integer errorSource;

Solution

  • The problem seems to be in the following query: select m.approvedMotor, m.valMessages, m.valMessages.validationMsg, count(m.valMessages.id) from ThreePhaseMotorInput m group by m.valMessages.validationMsg.

    That query should be a JPQL query, i.e a query where you specify entities and their Java properties. Also you must use JOINs if you want to jump to another entity's properties: m.valMessages.validationMsg is not correct, but INNER JOIN m.valMessages msg GROUP BY msg is correct.

    So try the following query:

    select m, COUNT(msg) from ThreePhaseMotorInput AS m LEFT JOIN m.valMessages AS msg GROUP BY msg.validationMsg