Hibernate JPA issue doesnt apply IS-A Relationship of table at some times - oracle

I have a Parent Table A and extended Child tables B and C
ex:
public class A {
private Long id;
//getters setters//
}
public class B extends A{
private String name;
//getters setters//
}
now at my repository,
public interface B extends JpaRepository<B, Long> {
#Query("select a from A a")//--This works
B getAll()
#Query("select a.id, b.name from A a join a.B b")//-- This doesn't
B getSpecificCols()
}
I need an explanation since "B is an A" that's why getAll() works
how come getSpecificCols() isn't working?
Error is
java.lang.ClassCastException: java.lang.Long cannot be cast to <package>.B
BTW I'm using Hibernate Spring

The query returns a long (a.id) and a string (b.name). The interface assumes that you return an entity (B). The returned id cannot be cast into a B, so you get a ClassCastException. If you want individual fields you can return List<Object[]>, where each record will be an array with id and name. Or you can use a projection (https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections).
By the way, does the first query really work when there are A entities in the database that are not B entities, for example if A also has a subclass C? It looks plain wrong to select the base class and return the derived class without filtering. I would select from B to return B.

After reading documentation what I needed all along was to put constructors in my entity/table where you put what specific parameters you need.

Related

JPA #OneToMany but with only one rekord

I have a table in the database that has a #OneToMany link to another table, JPA in standard form will return me the values from the other table as a list, however I would like to get the records as :
SELECT * FROM a LEFT JOIN b ON b.a_id = a.id
so if there are 2 records in the table "b" then I should get a list of 2 elements, not a one element list with a list inside that has values from table "b". Additionally, I will point out that I care to implement this by the function "Page findAll(#Nullable Specification spec, Pageable pageable);".
Example entity:
#Entity
public class A {
private Long id;
#OneToMany
private List<B> b;
soo i like to look like this
#Entity
public class A {
private Long id;
#OneToOne
private B b;
But when theres more that one B i will get second rekord instede of error.
What can I do to achieve this?

Spring JPA Two Entities for same DB table

I am writing Spring Boot Data JPA application and I have following situation:
I have 2 database queries fetching from same table but they are fetching different columns and data based on their WHERE clauses. For example:
SELECT CAR_TYPE, CAR_MODEL, CAR_YEAR, ACCIDENT_YEAR, BUY_DAY FROM CAR WHERE ACCIDENT_YEAR IS NULL
, and
SELECT CAR_MODEL, CAR_YEAR FROM CAR WHERE CAR_YEAR >= CURRENT_YEAR
As you can see these 2 queries (whose results will be exposed through 2 different API points) reference the same table CAR, but return different fields and have different WHERE clauses.
I know in JPA, I have to create an entity CarEntity like:
#Entity
#Table(name = "CAR")
public class CarEntity {
// I can only have fields from one or the other query
// here, so I guess I have to have 2 of these
}
, but my problem is that this entity needs to apply for the 2 different queries (with different fields returned, different data, different WHERE clauses).
So, it looks like I have to have actually 2 CarEntity classes. But, I am not sure how to make these 2 CarEntities so they both reference the same table CAR?
You can do by using projection that basically you define an interface with field methods which you want to get them. Projections
#Entity
public class Car implement CarSummary { // if you want you can implement JIC
private UUID id;
private String carType;
private String carModel;
private LocalDateTime carYear;
//getters and setters
}
public interface CarSummary {
String getCardModel();
String getCarYear();
}
Then on your query.
public interface CarRepository extends Repository<Car, UUID> {
Collection<CarSummary> findByCarYearGreaterThan(LocalDateTime now);
Collection<Car> findByAccidentYearIsNull();
}

select distinct values using spring data rest

I'm using java 8 and spring-data-rest to create API on my data.
I have a table Car(id, name, date...)
I'm trying to have an endpoint to retrieve distinct car names.
here's my Repository :
#RepositoryRestResource(path = "cars")
public interface CarRepository extends JpaRepository<Car, Long> {
//What i want to do
//#Query(value = "select distinct c.name as name from Car c")
#Query(value = "select distinct c from Car c")
List<Car> findDistinctName();
}
The query commented does not work , i have an exception
java.lang.IllegalArgumentException: PersistentEntity must not be null!
apparently this is the normal behavior of SDR.
I tried another solution by using Projections
#Projection(name = "name", types = {Car.class})
public interface CarName {
String getName();
}
but i cant get the distinct values, any idea?
Thank you :)
All you need, to do if you need a distinct list of cars, is such this query method:
public interface CarRepository extends JpaRepository<Car, Long> {
List<Car> findDistinctBy();
}
Spring Data JPA supports the Distinct keyword in repository query methods to set a distinct flag on the query to be created.
I found an (ugly) workaround, using jpql :
#Query(value = "select c from Car C WHERE c.id IN (SELECT min(ca.id) FROM Car ca Group by ca.name)")
I think you should remove the #Query annotation.
Just
List<Car> findDistinctName(); or List<Car> findNameDistinct(); should suffice.
It will automatically generate the query select c.name from Car c

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.

Spring data JPA for returning specific fields

Does Spring Data have a mechanism for returning specific fields?
I'm familiar with the syntax:
Invoice findByCode(String code);
How about this:
Integer findIdByCode(String code);
which returns the id field only. Or
Tuple findIdAndNameByCode(String code);
which returns a tuple. Or
Invoice findIdAndNameByCode(String code);
which returns an entity only populated with specific fields. Can use a constructor taking only those field if defined - else construct empty and populate the fields.
EDIT
To qualify some more, I'm aware of solutions like #Query, constructor expressions and now, #NamedEntityGraph. My question is simply - does Spring data support such a shorthand syntax as I'm suggesting?
If not, perhaps this is a cool enhancement for a later version...
I'm not looking for workarounds.
You can use JPQL Constructor Expressions:
SELECT NEW com.company.PublisherInfo(pub.id, pub.revenue, mag.price)
FROM Publisher pub JOIN pub.magazines mag WHERE mag.price > 5.00
The constructor name must be fully qualified
If you want to return just 1 field from table and it's primitive(or autoboxing), you can use next:
#Query("select distinct t.locationId from Table t")
List<Long> findAllWashroomLocationId();
Where:
Table - name of class which represent your table
t - alias
locationId - name of field(in your Table object)
Long - type of locationId (Integer, String, ...)
Not sure if what you're trying to achieve is the same as using multiple projections on the same JPA generated query (where method name are the same). I have posted an answer in this post.
https://stackoverflow.com/a/43373337/4540216
So I've managed to figure out how to use multiple projections with a
single query.
<T> T getByUsername(String username, Class<T> projection) This allows the method caller to specified the type of projection to be
applied to the query.
To further improve this so it is less prone to error, I made a blank
interface that the projection will have to extend in order to be able
to insert class into the parameter.
public interface JPAProjection {
}
public interface UserRepository extends CrudRepository<UserAccount, Long> {
<T extends JPAProjection > T getByUsername(String username, Class<? extends JPAProjection> projection);
}
Projection Interface
public interface UserDetailsProjection extends JPAProjection{
#Value("#{target.username}")
String getUsername();
#Value("#{target.firstname}")
String getFirstname();
#Value("#{target.lastname}")
String getLastname();
}
Then I can call the query method by
getByUsername("...", UserDetailsProjection.class)
i have a nativequery,
this is a insert and i going to return all fields after insert whit "RETURNING *"
this query return all fields of my database, and this data going to save in my entity
"Perfil Detalles"
my entity have all configurations of my fields of my database
#Query(
value= "INSERT INTO \"USUARIO\".\"PERFIL_CONFIGURACION\" (id_perfil, id_group, id_role) VALUES(:id_perfil, :id_group, :id_role) returning *",
nativeQuery = true)
public PerfilDetalles insertPerfilDetalles(
#Param("id_perfil") Long id_perfil,
#Param("id_group") int id_group,
#Param("id_role") int id_role);

Resources