I am using spring with JPA and trying to execute query using @query with SQL query.and trying to map the result to an object. I have different entity class and mapping to other
You can solve this issue and achieve the result by using projections by making your DTO an interface with getters for columns returned by the query. That's what I did when I faced the same issue.
For example in your case change StatsDTO
to interface like shown below, make sure to give alias for your columns if you are using '.' operator:
public interface StatsDTO {
Integer getUserCount();
Byte getTypeId();
Instant getModifiedAt();
}
Also in your query give alias for your columns like userCount, typeId, modifiedAt respectively so that it is mapped correctly.
replying to @Thanthu
the code should be like this
public interface StatsDTO {
Integer getUserCount();
Byte getTypeId();
Instant getModifiedAt();
}
not this
public interface StatsDTO {
Integer getUserCount;
Byte getTypeId;
Instant getModifiedAt;
}
Also you could try changing the UserRepository Interface declaration to below,
public interface UserRepository extends CrudRepository<StatsDTO, Long> {
@Query(value = "select count(type_id) userCount, type_id, modified_at from "
+ "user_campaign_objective where camp_id = ?1 group by objective_type_id,modified_at", nativeQuery = true)
List<StatsDTO> getStatsDTO(Long camp_id);
}
The change is : CrudRepository <StatsDTO, Long>
from CrudRepository < UserEntity, Long>
.
I faced the same issue while using a different data object inside a repository declared with another data object.
You can use the constructor expression JPQL query, your query looks like this:
select new StatsDTO(count(u),u.typeId,u.modifiedAt) from UserCampaignObjective u where campId = ? group by objectiveTypeId,modifiedAt
But you make sure the constructor StatsDTO existed already.
If you are still looking for an answer, here is how I did
@Data
@NoArgsConstructor
@AllArgsConstructor
public class StatsDTO {
private Integer userCount;
private Byte typeId;
private Instant modifiedAt;
}
and your query should be like this
public interface UserRepository extends CrudRepository<UserEntity, Long> {
@Query(value = "select new com.example.package.StatsDTO(count(type_id) userCount, typeId, modifiedAt from "
+ "UserCampaignObjective where campId = ?1 group by objectiveTypeId,modifiedAt")
List<StatsDTO> getStatsDTO(Long camp_id);
}
make sure you have a constructor present in StatsDTO to map all fields.
You have a mismatch between the column names:
userCount
type_id
modified_at
And your property names:
userCount
typeId
modifiedAt
Since this is a native query the JPA naming strategy doesn't apply and the column names should match the property names. So if you change the query to the following, it should work:
select count(type_id) userCount, type_id as typeId, modified_at as modifiedAt from ...