How to get column field only with spring-data-jpa? - spring

How can I make spring-data-jpa return a String column only, instead of a bean?
The following should return the bookingNumber String from a Booking #Entity:
public interface BookingRepository extends CrudRepository<Booking, Long> {
String findDistinctBookingNumberByLastname(String lastname);
}
If the booking exists, I'm getting the following exception instead of the bookingnumber string only:
java.lang.ClassCastException: class Booking cannot be cast to class java.lang.String
at com.sun.proxy.$Proxy198.findDistinctBookingNumberByLastname(Unknown Source) ~[?:?]
Sidenote: I know I could write a native #Query on the interface methods, but I'd prefer a query by method name only.

Related

Can we fetch data using JPA without using primary key

My Table:
Emotion
EID (Primary Key)
user_mood
Latitude
Longitude
uid
#Entity
public class Emotion
{
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer eId;
#Column(name = "user_mood")
private String mood;
private String latitude;
private String longitude;
private String uid;
}
My Interface:
public interface EmotionRepository extends JpaRepository<Emotion, String>{}
When I try to fetch values using uid
emotionRepo.findById(uid)
I am getting below type mismatch error
Error message:
org.hibernate.TypeMismatchException: Provided id of the wrong type for class mood_sensor.mood_sensor.pojos.Emotion. Expected: class java.lang.Integer, got class java.lang.String
Can I retrieve data using uid or I should use only the primaryKey(Integer) to retrieve data?
Yes, it's possible, but the method findById, from CrudRepository<T, ID> always expect to receive the ID as the argument - see here (be aware that JpaRepository extends from CrudRepository).
You can query by another field in a variety of ways, but as I saw that your use case is pretty simple, I'd suggest you to make use of Spring Data's query creation deriving from the method's name - see here and here
It's really simple, just create a method called findByUid in your EmotionRepository and Spring will take care of the rest by deriving the desired query from the method's name:
public interface EmotionRepository extends JpaRepository<Emotion, Integer> {
Optional<Emotion> findByUid(String uid);
}
Spring Data will then generate something like the following query:
SELECT e.* FROM Emotion e WHERE e.uid = <the-value>
Now, you can use findByUid method to query using the uid field.
And another fix: change from
EmotionRepository extends JpaRepository<Emotion, String>
to
EmotionRepository extends JpaRepository<Emotion, Integer>
this is because the id from Emotion is of type Integer, not String.
Inside your JpaRepository (EmotionRepository), you can make a function signature, anmd and the JPA will create a method to fetch whatever data you need.
This doc should help you understand exactly what is happening: http://static.springsource.org/spring-data/data-jpa/docs/1.0.0.M1/reference/html/#jpa.query-methods.query-creation

How to resolve No converter found capable of converting from type TupleBackedMap to type [com.example.dto.ExampleDto]

org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter$TupleBackedMap] to type [com.example.dto.ExampleDto]
at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:321) ~[spring-core-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:194) ~[spring-core-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:174) ~[spring-core-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.data.repository.query.ResultProcessor$ProjectingConverter.convert(ResultProcessor.java:293) ~[spring-data-commons-2.1.5.RELEASE.jar:2.1.5.RELEASE]
The above error is being thrown when I have a query that returns 2 values in a native JPA query is being used. I'm capturing the query response in the DTO below:
#Data
#Entity
#NoArgsConstructor
#AllArgsConstructor
#Builder
public class ExampleDto {
#Id
private String name1;
private int nameFlag;
}
And in a DAO class, I'm calling the native query as below. The query works in SQL Developer and returns 2 records. But when called as below , it throws the above error.
List<ExampleDto> getExampleDto = myJPARepository.
.findNameObject(uuid);
There is something wrong in the DTO class, which i need to change. Annotations? I'm not sure what is missing here, and try as I might , putting in #Entity annotation, #Data annotation , I'm not able to resolve this error when the query is called.
UPDATE: The native query associated with this is
#Query(value = "select name1, nameFlag from NameTable",
nativeQuery = true, name = "findNameObject where namekey = ?")
List<ExampleDto> findNameObject(
#Param("nameKey") UUID nameKey);
This is a bug: https://jira.spring.io/browse/DATAJPA-1714
You can either use JPQL with a constructor expression, an interface projection or a custom method implementation as a workaround.
Make sure, your Repository class is using same class, as you are using for extracting the records from native query. Example shown below for XYZDTO
#Repository
public interface XYZRepository extends JpaRepository <XYZDTO, Long> {
}

Impossible to return a list / collection of projection

I made a spring-boot project to access to my datas.
My main class is Patient.java:
#Entity
public class Patient {
private Long id;
private String numeroSs;
private String profession;
// lot of stuff...., getters, setters, ...
}
In order to improve my requests, I've made a very simple projection of my class Patient. I've called this projection PatientCustom :
public interface PatientCustom {
String getNumeroSs();
Timestamp getDateProchainRdv();
}
And in my repository "PatientRepo.java", I created two custom methods :
#Transactional
#RepositoryRestResource(collectionResourceRel = "patient", path = "patient")
public interface PatientRepo extends JpaRepository<Patient, Long> {
PatientCustom findOneByNumeroSs(String numeroSs);
Collection<PatientCustom> findByNumeroSs(String numeroSs);
}
When I use the first method, no problem : it returns a PatientCustom :
{
numeroSs: "150505617017002",
dateProchainRdv: null
}
But When I want a list or a collection, it sends me an error :
{
cause: null,
message: "Couldn't find PersistentEntity for type class com.sun.proxy.$Proxy165!"
}
And the traces in my terminal :
2019-03-12 10:32:34.671 ERROR 2072 --- [nio-8090-exec-2] o.s.d.r.w.RepositoryRestExceptionHandler : Couldn't find PersistentEntity for type class com.sun.proxy.$Proxy165!
java.lang.IllegalArgumentException: Couldn't find PersistentEntity for type class com.sun.proxy.$Proxy165!
at org.springframework.data.mapping.context.PersistentEntities.lambda$getRequiredPersistentEntity$2(PersistentEntities.java:96) ~[spring-data-commons-2.1.5.RELEASE.jar:2.1.5.RELEASE]
at java.util.Optional.orElseThrow(Optional.java:290) ~[na:1.8.0_181]
at org.springframework.data.mapping.context.PersistentEntities.getRequiredPersistentEntity(PersistentEntities.java:95) ~[spring-data-commons-2.1.5.RELEASE.jar:2.1.5.RELEASE]
I understand very well that spring wants to add a proxy class to my interface, but when it want to add this proxy to a list or a collection, it's unhappy because list and collection are not interfaces but classses.
What can I do to solve this ?

Spring Data JPA native query result binding

Entity class:
#Entity
#SqlResultSetMapping(
name="hourMapping",
classes=#ConstructorResult(
targetClass=Representation.class,
columns={
#ColumnResult(name="hour", type=BigDecimal.class),
#ColumnResult(name="transactions", type=BigDecimal.class)
}
)
)
#NamedNativeQuery(name="MyEntity.reportByHour", query="SELECT hour,SUM(tran_per_hour) AS transactions FROM MY_ENTITY GROUP BY hour ORDER BY hour"
,resultSetMapping="hourMapping")
#Table(name="MY_ENTITY")
public class MyEntity implements Serializable {
Pojo class:
#Data //Lombok
#JsonAutoDetect(fieldVisibility = Visibility.ANY)
public class Representation {
public Representation(BigDecimal hour, BigDecimal transactions) {
this.hour = hour;
this.transactions = transactions;
}
private BigDecimal hour;
private BigDecimal transactions;
Repository interface:
public interface MyEntityRepository extends JpaRepository<MyEntity, MyEntityPK> {
List<Representation> reportByHour();
}
When I run the endpoint which invokes the native query, I get exception:
Failed to convert from type [java.lang.Object[]] to type [com.representation.Representation] for value '{0, 198}'; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.math.BigDecimal] to type [com.representation.Representation]
Now if I just have "hour" field returned from my native query (and relevant changes to POJO constructor etc) it works fine.
Any help appreciated.
Ok, false alarm. My hibernate dependencies were all messed up and causing conflicts so resulting in the above exception.
After fixing these dependency issues, works great!!
Long story short: let spring-boot-* handle most hibernate dependencies instead of overriding or managing your own.

How to Define Dynamic Model in Spring Framework

I am using Spring Framework as my back end
I have define know as Entity class The Entity class know contain 5 Fields
Below is the class , The code below dose not have setter getter part to make shorter and cleaner
#Entity
#Table(name="TblKnow")
public class Know {
#Id
private Double idKnow;
private String SubjectKnow;
private String BodyKnow;
private String ImgKnow;
private double CountView;
In JpaRepository interface i want to only query two column not all of columns.
public interface KnowRepository extends JpaRepository<Know,Double> {
#Query("SELECT idKnow,SubjectKnow FROM Know")
public Page<Know> findCByOrderByIdKnowDesc(Pageable pageable);
Problem: i try to run but i get below exception
java.lang.IllegalArgumentException: Cannot create TypedQuery for query with more than one return using requested result type [java.lang.Long]
But if i use without below query it is fine
public Page<Know> findAllByOrderByIdKnowDesc(Pageable pageable);
You can create a custom constructor and use that to select only some fields in JPA query.
public Know(Double idKnow, String SubjectKnow) {
this.idKnow = idKnow;
this.SubjectKnow = SubjectKnow;
}
And the use this constructor in JPA query. Make sure you use complete path of class with package.
#Query("SELECT NEW packagePath.Know(idKnow,SubjectKnow) FROM Know")
query :
public Page<Know> findAllByOrderByIdKnowDesc(Pageable pageable);
works dut to you select Know objects with fields that are mapped correct into Know class (and after wrapped into Page).
with query :
#Query("SELECT idKnow,SubjectKnow FROM Know")
public Page<Know> findCByOrderByIdKnowDesc(Pageable pageable);
returns some custome bean/object that spring data can't map in correct way into Know class (as you declared it as expected return class wrapped into Page). add counstructor into Know with idKnow,SubjectKnow fields , or you can wrap it into some DTO with idKnow,SubjectKnow fields.

Resources