Fetching specific columns from multiple joined tables in Spring Data JPA - java

my company recently decided to switch to using Spring Data JPA instead of Mybatis for new projects, so I am pretty new to using Spring Data JPA in general.
I am trying to execute the following sql query
SELECT ab.status, buyer_rate, buyer_name, buyer_tel, bid_price, ADDTIME(complete_dt,"23:00:0.000000") AS send_time, brand, model
FROM auction_bid ab
INNER JOIN goods_auction ga ON ab.goods_auction_idx=ga.idx
INNER JOIN auction_info ai ON ga.auction_info_idx=ai.idx
WHERE is_success=1 and ab.status='008';
I have created 3 entities each corresponding to the table in my mariadb database
#Entity
#Getter
#Setter
#ToString
public class AuctionBid {
#Id
#Column(name = "auction_bid_idx")
private Long idx;
#Column
private Long userIdx;
#Column
private String status;
#Column
private Long bidPrice;
#Column
private int isSuccess;
#Column
private int rank;
#Column
private Date createdAt;
#Column
private Date updatedAt;
#ManyToOne(fetch = LAZY)
#JoinColumn(name="goods_auction_idx")
private GoodsAuction goodsAuction;
}
#Entity
#Getter
#Setter
public class AuctionInfo {
#Id
#Column(name = "auction_info_idx")
private Long idx;
#Column
private Long goodsIdx;
#Column
private String brand;
#Column
private String model;
#Column
private String pattern;
#Column
private String size;
#Column
private String color;
#Column
private String tag1;
#Column
private String tag2;
#Column
private String tag3;
#Column
private String comment;
#Column
private String korName;
#Column
private String oColor;
#Column
private String iColor;
#Column
private String hColor;
#Column
private String oMaterial;
#Column
private String iMaterial;
#Column
private String origin;
#Column
private String realSize;
#Column
private Long minBid;
#Column
private Double sellerRate;
#Column
private Double buyerRate;
#Column
private Date createdAt;
#Column
private Date updatedAt;
}
#Entity
#ToString
#Getter
#Setter
public class GoodsAuction {
#Id
#Column(name = "goods_auction_idx")
private Long idx;
#Column
private String auctionUid;
#Column
private String status;
#Column
private Date startDt;
#Column
private Date finishDt;
#Column
private Long step;
#Column
private int isReadyActive;
#Column
private int isFinishActive;
#Column
private int isRecommended;
#Column
private String invoice;
#Column
private String buyerName;
#Column
private String buyerTel;
#Column
private String buyerAddr1;
#Column
private String buyerAddr2;
#Column
private String buyerZipcode;
#Column
private Date completeDt;
#Column
private Date deliveryDt;
#Column
private Long returnTaxPrice;
#Column
private String returnInvoice;
#Column
private Date returnReqDt;
#Column
private Date returnCompDt;
#Column
private Date createdAt;
#Column
private Date updatedAt;
#ManyToOne(fetch = LAZY)
#JoinColumn(name="auction_info_idx")
private AuctionInfo auctionInfo;
}
And I am trying to map the info that I got from the query to the following object
public class MessageData {
private String status;
private Double buyerRate;
private String buyerName;
private String buyerTel;
private Long bidPrice;
private Date sendTime;
private String brand;
private String model;
}
I get that I have to make and interface that extends JpaRepository, but the examples that I have seen seems to just fetch the entire table instead of a select few columns, and I am a little bit confused on how I will be able to map the result to List.
Any feedback will be deeply appreciated!
Thank you in advance!!

You can hql joins instead of inner joins through entity models.
like that;
select a from auction_bid ab join ab.goodsAuction gA join auctionInfo aI
You can use 'Data Transfer Objects (DTO)' for fetch specific columns.

For projections, you can try a "select new".
I assume the MessageData is in package com.foo :
select new com.foo.MessageData(ab.status, buyer_rate, buyer_name, buyer_tel, bid_price, ADDTIME(complete_dt,"23:00:0.000000"), brand, model) FROM ...

Related

Ignore some fields for JSONB Deserialization in Spring JPA

I have a Spring JPA Model
#Entity
#Table(name = "projects")
#TypeDefs({ #TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) })
public class Project implements Serializable {
#Id
private long id;
#Column(name = "version_id")
private Long version;
#Column(name = "created_by")
private String createdBy;
#Column(name = "created_at")
private LocalDateTime createdAt;
#Column(name = "updated_by")
private String updatedBy;
#Column(name = "updated_at")
private LocalDateTime updatedAt;
#Column(name = "is_archived")
private Boolean archived;
private String commentsRoomId;
private String workflowType;
private String workflowId;
#Type(type = "jsonb")
#Column(columnDefinition = "jsonb")
private Map<String, ProjectSection> sections;
Now the data in the last property is a JSONB Property which should ignore some of the fields. as it wouldnt be present in the DB either.
Now when I try to get the data I get the following error.
The given Json object value: {s06=ProjectSection(version=1, enabled=true, type=milestones, values={}, visibility=null, sectionId=null, sectionSchema=null)
which says this after the json repr.
Now my Section looks like
#NoArgsConstructor
#AllArgsConstructor
#Data
public class ProjectSection {
#JsonProperty("version_id")
private Long version;
#JsonProperty("enabled")
private Boolean enabled;
#JsonProperty("type")
private String type;
#JsonProperty("values")
private Map<String, ProjectField> values;
#JsonProperty("visibility")
private List<String> visibility;
// Not Srtored in DB
#JsonIgnore
#Transient
private String sectionId;
#JsonIgnore
#Transient
private ProjectTemplate.SectionSchema sectionSchema;
I think maybe because of it being in a JSONB Nested fields the transient doesn't make sense.
How should I make sure these values are ignored when its deserialising from the DB and loads properly.
If I remove these extra fields, it seems to work.
Why don't you use some mappers ModelMapper or DozerMapper to handle such cases.

How to delete entity with many to many relation? JPA

i don't know how to delete this. Only one thing i noticed that the OrderToProvider will be deleted after deleting all entities in a table named "OrderToProvider-Goods".
Code:
OrderToProvider
public class OrderToProvider {
#GeneratedValue (strategy = GenerationType.IDENTITY)
#Id
private int id;
#Basic
private int price;
#Basic
private Date dataOfOrder;
#Basic
private Date dateOfProcessing;
#ManyToOne(optional = false)
private main.data.Provider provider;
#ManyToMany (cascade = CascadeType.ALL)
private Collection<Good> goods;
Good
public class Good implements Comparable<Good>{
#GeneratedValue (strategy = GenerationType.IDENTITY)
#Id
private int id;
#Basic
private String name;
#Basic
private String model;
#Basic
private int price;
#Basic
private String type;
#Basic
private int amount;
#ManyToOne(optional = false)
private Provider provider;
To delete the OrderToProvider from your DB, first you retrieve it from your DB, then setGoods(null) and setProvider(null), then delete it afterwards. This should work with conditions that you have a properly implemented setters.
I hope this is helpful.

spring.jackson.date-format property does not work properly for the date serialization with #Temporal annotation

I have the following property in application.properties file:
spring.jackson.date-format=yyyy-MMM-dd
There is object definition to be serialized:
public class InjuryDTO {
private Long id;
private String kindOfInjury;
private String muscle;
private String side;
private Integer outOfTraining;
private Date injuryDate;
private Long athleteId;
// getters and setters are omitted for brevity }
This is class from which InjuryDTO object is originally created:
#Entity
#Table(name = "INJURY")
public class Injury {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "INJURY_ID")
private Long id;
#Column(name = "KIND_OF_INJURY")
private String kindOfInjury;
#Column(name = "MUSCLE")
private String muscle;
#Column(name = "SIDE")
private String side;
#Column(name = "OUT_OF_TRAINING")
private Integer outOfTraining;
#Temporal(value = TemporalType.DATE)
#Column(name = "INJURY_DATE")
private Date injuryDate;
#ManyToOne
#JoinColumn(name = "ATHLETE_ID")
#JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private Athlete athlete;
// get,set-ters are removed for brevity
}
So, if the deserialization of this JSON property happens:
"injuryDate":"2018-Jun-02"
Jackson accepts this string and transforms it to the corresponding java.util.Date object, but when serialization happens with no commented #Temporal(value = TemporalType.DATE) annotation then server gets back the following JSON property: "injuryDate":"2018-06-02".
Question is: Why #Temporal annotation affects the actual representation of the date property in JSON?
Try this one:
#Temporal(TemporalType.DATE)
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
#Column(name="INJURY_DATE")
private Date injuryDate;

Using the subselect hibernate annotation with entity

I want to create a view from two tables using annotations in java/JEE,
so after some researching I found that the only way to do it is using #Subselectannotation so I created 3 entities
the test entity:
#Table
#Entity
public class Test {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column
private String nom;
#Column
private String prenom;
#Column
private int age;
#Column
private String adresse;
#Column
private Date dateNaissance;
// getters and setters
}
The compte entity:
#Entity
public class Compte {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column
private long solde;
#Column
private long numero;
#Column
private String description;
// getters and setters
}
and the entity Compte_Test which has the same role as a view
#Entity
#Subselect("SELECT c2.id as idTest,c1.id as id,c1.solde as solde,c1.numero as numero, c2.nom as nom, c2.prenom as prenom FROM Compte c1 INNER JOIN Test c2 ON c1.id_test= c2.id")
#Synchronize({ "compte", "test" })
public class Compte_Test {
#Id
private long idCompte_Test;
#Column
private long idTest;
#Column
private long id;
#Column
private long solde;
#Column
private long numero;
#Column
private String nom;
#Column
private String prenom;
// getters and setters
}
I'm using spring data #Query annotation to get data from Compte_Test entity
#Query(value = "SELECT c from Compte_Test c ")
List<Compte_Test> fullTextSearch(Pageable pageable);
The problem is that it generates for me an error
org.postgresql.util.PSQLException: ERROR: column compte_tes0_.id_compte_test does not exist
Position : 8
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2440) ~[postgresql-42.2.5.jar:42.2.5]
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2183) ~[postgresql-42.2.5.jar:42.2.5]
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:308) ~[postgresql-42.2.5.jar:42.2.5]

How to return only specific field in spring

In the following code when I used projection it returns me the whole object of Group , But I want to get only roleName of class Group
how can I do this?
Projection: UserWithProfile
#Projection(name="UserWithProfile",types=User.class)
public interface UserWithProfile extends UserGetters {
UserPhoto getProfilePhoto();
}
UserGetters
public interface UserGetters{
Long getId();
String getName();
String getLogonEmail();
boolean isEmailVerified();
Group getGroup();
}
User.class
#Entity
public class User implements Serializable, UserGetters {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToMany(cascade = CascadeType.REMOVE, fetch = FetchType.EAGER, targetEntity = Property.class)
private Set<Property> favouriteProperty;
#OneToOne
private AcceptanceLetter acceptanceLetter;
#Column(unique=true)
private String logonEmail;
private String name;
#JsonProperty(access = Access.WRITE_ONLY)
#Column(updatable=false)
private String password;
private boolean emailVerified;
#ManyToOne
private Group group;
#OneToOne
private Business business;
private String address;
private String postcode;
private String phoneNo;
private String passportNo;
#Column(length=1000)
private String description;
#JsonIgnore
private float meanRating;
#OneToOne(mappedBy="user",targetEntity=UserPhoto.class)
private UserPhoto profilePhoto;
#ManyToOne
private Country country;
Getter and setters... }
First I tried #RestResource(exported = false) its not worked but then I tried
#JsonIgnore it finally works :'D

Categories

Resources