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 object
s 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
- Create a response model that outputs the format you expect as response.
- 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
Spring-Data-Jpa Repository - Underscore on Entity Column Name
Log File Is Created But File Is Empty
Delete Everything After Part of a String
How to Append a Query Parameter to an Existing Url
How to Store Original Date/Time Without Timezone Calculation to Mongodb
How to Convert a Byte to Its Binary String Representation
Java Input Validation for Number Range and Numeric Values Only With Counter
Java Nullpointerexception When Adding to Arraylist
Rsa Decryption Error - Illegalblocksizeexception: Data Must Not Be Longer Than 128 Bytes
Java8 Way to Handle If..Else Check in Collections
How to Indicate to Spring Boot to Use Utc Time Zone for Date Parameters
How to Check Hikaricp Connection Pooling Is Working or Not in Java
Checking If a String Contains a Dot
Javac: File Not Found: First.Java Usage: Javac <Options> <Source Files>
Spring - Read Property Value from Properties File in Static Field of Class
Refactor Multiple If' Statements in Java-8
How to Listen With Multiple Port for Multiple Client in Single Jpos Instance