Search code examples
javaspring-boothibernatespring-data-jpajpql

Associated values in JPQL : Unable to locate appropriate constructor on class


I have a Entities as shown below.

ThingType.java

@Entity
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
public class ThingType {
 @Id
 @Column(name = "thing_type_id")
 private String thingTypeId;

 @Column(length = 50)
 private String description;

 @Embedded
 private Managed managed;

 @OneToMany(orphanRemoval = true,mappedBy = "thingType",cascade = CascadeType.ALL,fetch = FetchType.LAZY)
 private List<ThingTypeBasicProperties> basicProperties = new ArrayList<>();

 @OneToMany(orphanRemoval = true,mappedBy = "thingType",cascade = CascadeType.ALL,fetch = FetchType.LAZY)
 private List<ThingTypeMeasurementProperties> measurementProperties = new ArrayList<>();
}

I have repository interface for ThingType.

ThingTypeRepository.java

@Repository
public interface ThingTypeRepository extends JpaRepository<ThingType,String> {
 @Query(value = "select new io.badhusha.iotmonitor.model.ThingType(t.thingTypeId,t.description,bp,mp) from ThingType t LEFT JOIN t.basicProperties bp LEFT JOIN t.measurementProperties mp where t.thingTypeId = ?1")
Optional<ThingType> findThingTypeById(@NonNull String thingTypeId);
}

I am trying to fetch the ThingType with its associated basicProperties and measurementProperties using JPQL query.

I get error below

Unable to locate appropriate constructor on class [io.project.model.ThingType]. Expected arguments are: java.lang.String, java.lang.String, io.project.model.ThingTypeBasicProperties, io.project.model.ThingTypeMeasurementProperties

The error is saying it is expecting a single value of ThingTypeBasicProperties and ThingTypeMeasurementProperties. Why ? I am having a OneToMany relationship, it should be a List.

Can anyone please help me here ?


Solution

  • I guess you should rather use t.basicProperties and t.measurementProperties to bind the List instances. Give a try the following query:

    @Query(value = 
            "select new" + 
            "io.badhusha.iotmonitor.model.ThingType(" +
                "t.thingTypeId, t.description, t.basicProperties, t.measurementProperties" +
            ")" +
            "from ThingType t" +
            "left join t.basicProperties" +
            "left join t.measurementProperties" +
            "where t.thingTypeId = ?1")
    
    "select new io.badhusha.iotmonitor.model.ThingType(t.thingTypeId, t.description, t.basicProperties, t.measurementProperties) from ThingType t LEFT JOIN t.basicProperties LEFT JOIN t.measurementProperties where t.thingTypeId = ?1"
    

    Finally, your constructor generated with @AllArgsConstructor contains 5 parameters (with Managed as the 3rd parameter). You need to define new constructor matching:

    (String, String, List<ThingTypeBasicProperties>, List<ThingTypeMeasurementProperties>)