问题
I need to implement a query in Spring Data like this :-
Select User.name, sum(Activity.minutes)
From User, Activity, ActivityStatus
Where User.id = ActivityStatus.userId
And Activity.id = ActivityStatus.activityId
AND ActivityStatus = "COMPLETED"
GROUP BY user.name;
So i need to join 3 tables, therefore I have to use @Query
with nativeQuery = true
( correct me if I'm wrong here )
And so my Repository method looks like this :-
@Query(value = "Select User.name, sum(Activity.minutes) as total_minutes
From User, Activity, ActivityStatus
Where User.id = ActivityStatus.userId
And Activity.id = ActivityStatus.activityId
AND ActivityStatus = "COMPLETED"
AND User.Type = ?1
GROUP BY user.name;",
nativeQuery = true
)
List<MyObj> getTotalActivityMinutesByUserType(String userType);
MyObj
class looks like this :-
public class MyObj {
String name;
long total_minutes;
// getter and setter methods
public MyObj(String name, long total_minutes) {
this.name = name;
this.total_minutes = total_minutes;
}
}
My Test Method :-
@Test
public void TotalActivityTest() throws Exception {
List<MyObj> objA = myRepository.getTotalActivityMinutesByUser("TEST");
}
and i get the following exception :-
org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.Object[]] to type [com.mycomp.MyObj] for value '{TEST, 5.0}'; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [com.mycomp.dto.MyObj]
I need a way to return the result as MyObj
. ( Or at least a way to cast it to MyObj) Is this possible?
EDIT:
Building from @Cepr0's answer My Entity class looks like this :-
@Entity
public class ActivityStatus extends Base {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH})
private Activity activity;
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH})
private User user;
}
I am not sure how the JOIN query in JPQL should look like...
回答1:
Just use Projection and JPQL query:
public interface NameAndDuration {
String getName();
Long getDuaration();
}
@Query("select u.name as name, sum(a.minutes) as duration from User u join u.activityStatus st join st.activity a where st.status = "COMPLETED" and u.type = ?1 group by u.name")
List<NameAndDuration> getNameAndDurationByUserType(String userType);
List<NameAndDuration> list = getNameAndDurationByUserType("TEST");
String userName = list.get(0).getName();
This query is probably not exact what you need because I don't know a structure of your entity classes. But if you show them I will correct the query...
回答2:
The query is returning object array which you are storing in an normal object.Iterate through object array and set it to object like below
List<MyObj > test= new ArrayList<>();
List<Object[]> rows= query.list();
for (Object[] row : rows) {
MyObj temp=new MyObj (arg1,arg2);
temp.set((Dataype) row[0])//You need to create getters and setters for your pojo
..
test.add(temp);
}
回答3:
I actually had a similar issue with this exception. I have 3 tables: Project, Asset, and ProjectAsset. ProjectAsset is the reference table where one project can have many assets. So I created 3 repositories, one for each entity. The problem is I placed my @Query in the ProjectAssetRepository and that didn't work due to the repository extending CrudRepository. ProjectAssetId is an embedded id made up of projectid and assetid. I can't just return Asset objects in this repository so I moved the method to AssetRepository and everything worked. If you are using cross-reference tables, make sure you pull the correct object or else you will run into this exception.
来源:https://stackoverflow.com/questions/44436287/nativequery-spring-data-return-object