Jpa Repository Query - Java.Lang.Object; Cannot Be Cast to Model

Jpa Repository query - java.lang.Object; cannot be cast to model

Essentially the question is about how to do a Projection from a JPA query to a return type with nested values. This is something that is not really there with JPA queries at the moment.

Besides DTOs, there are projection interfaces in Spring JPA that can actually handle a bit of nesting (see the Spring Docs). These would be a reasonably simple option, but you still can't easily coerce one into a Movie.

The main other option at the moment is a ResultTransformer back in Hibernate. For example this could be accessed by using a named JPA query and then dropping back to the Hibernate query API before running it.

This is the declared named query (slightly simplified against the available classes in the samples in the question):

@Entity
@NamedQuery(name = "Movie.byCelebrity",
query = "SELECT m.id, m.name, m.releaseDate, mc.characterName FROM Movie m JOIN m.movieCelebrities mc " +
"WHERE mc.role = :role")
public class Movie {

This can then be called with a result transformer like this:

    List<Movie> movies = entityManager
.createNamedQuery("Movie.byCelebrity")
.setParameter("role", role)
.unwrap(org.hibernate.query.Query.class)
.setResultTransformer(new MovieResultTransformer())
.getResultList();

Normally, for a single level query, you can use the AliasToBeanResultTransformer that comes with Hibernate, but this won't merge or group the results by Movie.

Here's an example result transformer to first map the return columns (in the 'tuple' which is a list of result fields), and then merge those by Movie:

public class MovieResultTransformer
implements ResultTransformer {
@Override
public Object transformTuple(Object[] tuple,
String[] aliases) {
Movie movie = new Movie();
movie.setId((Long) tuple[0]);
movie.setName((String) tuple[1]);
movie.setReleaseDate((Date) tuple[2]);
MovieCelebrity movieCelebrity = new MovieCelebrity();
movieCelebrity.setCharacterName((String) tuple[3]);
movie.getMovieCelebrities().add(movieCelebrity);
return movie;
}

@Override
public List transformList(List collection) {
Map<Long, Movie> movies = new LinkedHashMap<>();
for (Object item : collection) {
Movie movie = (Movie) item;
Long id = movie.getId();
Movie existingMovie = movies.get(id);
if (existingMovie == null)
movies.put(id, movie);
else
existingMovie.getMovieCelebrities()
.addAll(movie.getMovieCelebrities());
}
return new ArrayList<>(movies.values());
}
}

It is worth noting that ResultTransformer was deprecated with Hibernate 5.2, with the wonderful comment in the source: @todo develop a new approach to result transformers.

Clearly the area of Projections in JPA is still a bit incomplete. The suggestion for Hibernate 6 is that they'll switch to a functional interface and lambda style API which would be a great improvement - it would be good to see something similar ripple into JPA.

java.lang.Object; cannot be cast to model class: error in Spring Boot

Option 1) Make sure the RoomCPCMapping is a projection interface:

public interface RoomCPCMappingResult {

String getNCCPCode();
String getNPercent();

...
}

Option 2) Use the result class legacy option:

SELECT new com.my.package.RoomCPCMappingResult(u.nCCPCode,u.nPercent)
FROM RoomCPCMapping u JOIN u.clientCPC ur
where u.nRoomAllocationId=:nRoomAllocationId

just make sure you have an adequate constructor present there.

java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to

Your query is returning a List of Object[] because you aren't selecting an Equip Entity, but you are only selecting columns in :

   Query query = manager.createNativeQuery("SELECT"
+ " checksl.id_check_lists as IdCheckLists,"
+ " checksl.titre_check as NomCheckLists,"
+ " checksl.recommendation as Recommendation, "
+ " resp.id_responsescheck as IdResponse, "
+ " resp.conformite as Conformite, "
+ " resp.date_response as DateResponse, "
+ " resp.missions_id as IdMission "

Hibernate won't convert the ResultSet results to an Equip entity object, the result will be an array of objects because Hibernate won't determine the types of selected columns.

You need to loop over this List elements and transform each Object[] to an Equip object manually.

Edit:

This is how you should implement it:

List<Object[]> res = query.getResultList();
List<Equip> list= new ArrayList<Equip>();
JSONObject obj = new JSONObject();

Iterator it = res.iterator();
while(it.hasNext()){
Object[] line = it.next();
Equip eq = new Equip();
eq.setIdEquipement(line[0]);
eq.setTitre(line[1]);
eq.setDescription(line[2]);
//And set all the Equip fields here
//And last thing add it to the list

list.add(eq);
}

Ljava.lang.Object; cannot be cast when getting multipile fields Hibernate Repository

Thats because you are retrieving individual properties - not the entire Cms Object.

I would use an instance of Query for this:

EntityManager em = emf.createEntityManager();
Query query = em.createQuery("Select u.id_page,u.title from Cms u");
List<Object[]> results = query.getResultList();
for(Object[] elements: results){
Long id = Long.valueOf(String.valueOf(elements[0]));
String title = String.valueOf(elements[1]);
}

java.lang.ClassCastException: [B cannot be cast to [Ljava.lang.Object; while using JPA 2.2 query.getResultStream().findFirst()

Try with getResultList first, and see if it works:

public Optional<Byte[]> findShipmentLabelByClientIdAndAwb(
String clientId, String awb) {
return entityManager.createQuery("""
select
g.shipmentLabel as shipmentLabel
from GenericShipment g
where
g.client.id = :clientId and
g.shipmentId = :awb and
(
g.processingStatus is null or
g.processingStatus <> 'DELETED'
) and
g.shipmentLabel is not null
""")
.setParameter("clientId", clientId)
.setParameter("awb", awb)
.setMaxResults(1)
.getResultList()
.stream()
.findFirst();
}

Note that it's inefficient to select N records only to take the first one using fidFirst. What if this query returns 100 records? You'd still select all 100 from the DB.

That's why I added the setMaxResults call.

If that doesn't work, try debugging the Hibernate BinaryType and see why it doesn't return byte[].

Ljava.lang.Object; cannot be cast to .model.ISOVER at java.util.ArrayList.forEach

I believe this is your culprit:

if (stud != null) {
stud.forEach(d -> {
HashMap<String, Object> entry = new HashMap<>(); // < -- here

entry.put("adultquestionary","Yes");
entry.put("caseNumber", d.getCASE());
listings.add(entry);
});
}

Have your tried using *.model.ISECO instead of java.lang.Object? Does that work, any particular limitation?

Additionally, you could refactor you code to something way more simple, if you follow the same explanation provided in here: How to make nested JSON response with Array from a Stored procedure

  1. Create a response model that outputs the format you expect as response.
  2. There is no need for you to do all that collections handling one-by-one. The representation of an object in JSON is a MAP, basically let the
    Jackson JSON library do all that work for you.

java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast or BeanUtils.copyProperties not working

Your statement

@Query("select A.id, A.position ,A.title,A.shortdescription,A.thumbnailimage, A.linkactions, A.last_updated_date, A.last_updated_by, B.countryName " +
"from ContentManage as A inner join Country as B on A.countryid=B.countryId")

contains parts from ContentManage and Country in select.
But your result is only a List<ContentManage>

To solve this you can create a new Dto class containing all the fields from A and from B you need. This Dto class must have an all-args constructor. Then instead of

 "select A.id, A.position ,A.title,A.shortdescription,A.thumbnailimage, A.linkactions, A.last_updated_date, A.last_updated_by, B.countryName " +
"from ContentManage as A inner join Country as B on A.countryid=B.countryId"

you can write:

"select new com.you.package.YourDtoClass (A.id, A.position ,A.title,A.shortdescription,A.thumbnailimage, A.linkactions, A.last_updated_date, A.last_updated_by, B.countryName) " +
"from ContentManage as A inner join Country as B on A.countryid=B.countryId"

Java.lang.Object; cannot be cast to <hibernate entity>

Change for

@Query("SELECT func FROM Function func") 
List<Function> findItAll();

to retrieve all Functions instead of a array with the two attributes. it would also works:

@Query("FROM Function") 
List<Function> findItAll();

Spring jpa throws ClassCastException when using custom Query

I found a solution by using projections in spring. However, I am not sure if it is the best solution.

FileItemNoBlob

import java.util.Date;
import java.util.UUID;

public interface FileItemNoBlob {
UUID getId();
Long getVersion();
Date getCreatedAt();
Long getTotalSize();
String getName();
}

FileItemNoBlob findByIdAndVersion(UUID id, Long version); in repository seems working. It would be better to create another repository for projection classes as well to make it cleaner.



Related Topics



Leave a reply



Submit