spring jpa join two entities - spring

I'm struggling to join two entity models using jpa crudRepository interface. i can't figure out how to map two entity model and write query inside #Query annotation. these are my entity classes.
I want to execute this query "SELECT dppd.payment_plan_id,dppd.attribute_value,dppd.attribute_id FROM taxi_driver_mapping AS tdm JOIN driver_payment_plan_details AS dppd on dppd.payment_plan"
#Getter
#Setter
#Entity
#ToString
#Table(name = "driver_payment_plan_details")
#NoArgsConstructor
public class DriverPaymentPlanDetails
{
#Id
#Column(name = "id")
private int id ;
#Column(name = "payment_plan_id")
private long paymentPlanId;
#Column(name = "attribute_id")
private int attributeId;
#Column(name = "attribute_value")
private float attributeValue;
}
#Getter
#Setter
#ToString
#Table(name = "taxi_driver_mapping")
#Entity
#NoArgsConstructor
public class TaxiDriverMapping
{
#Column(name = "mapping_id")
#Id
private Long mappingId;
#Column(name = "mapping_driverid")
private Long mappingDriverId;
#Column(name = "mapping_taxi_model_id")
private String mappingTaxiModelId;
#Column(name = "mapping_status")
private String mappingStatus;
#Column(name = "mapping_payment_plan_id")
private Long mappingPaymentPlanId;
}

thank you guys for showing a correct path, this is my code.
#Getter
#Setter
#ToString
#Table(name = "taxi_driver_mapping")
#Entity
#NoArgsConstructor
public class TaxiDriverMapping
{
#Column(name = "mapping_id")
#Id
private Long mappingId;
#Column(name = "mapping_driverid")
private Long mappingDriverId;
#Column(name = "mapping_taxi_model_id")
private String mappingTaxiModelId;
#Column(name = "mapping_status")
private String mappingStatus;
#Column(name = "mapping_payment_plan_id")
private Long mappingPaymentPlanId;
#OneToMany(mappedBy = "taxiDriverMapping")
private List<DriverPaymentPlanDetails> driverPaymentPlanDetails;
}
#Getter
#Setter
#Entity
#ToString
#Table(name = "driver_payment_plan_details")
#NoArgsConstructor
public class DriverPaymentPlanDetails
{
#Id
#Column(name = "id")
private int id ;
#Column(name = "payment_plan_id")
private long paymentPlanId;
#Column(name = "attribute_id")
private int attributeId;
#Column(name = "attribute_value")
private float attributeValue;
#ManyToOne()
#JoinColumn(name="payment_plan_id",insertable = false,updatable = false)
private TaxiDriverMapping taxiDriverMapping;
}

Related

How to implements entity with 2 entity as primary key with jpa annotation and repository

i want to implement a many to many association with quantity information in it . like this :
#Entity
#Table(name = "reserves")
#Getter #Setter #NoArgsConstructor
public class Reserve {
#Id
#ManyToOne(cascade = CascadeType.ALL,fetch = FetchType.EAGER)
#JoinColumn(name = "groupe_id")
private GroupeSanguin bloodGroup;
#Id
#ManyToOne(cascade = CascadeType.ALL,fetch = FetchType.EAGER)
private Banque banque;
private int quantity;
}
the GroupSanguin and the Banque are two class stored in the database two . here is the code for the two if you need :
#Entity
#Table(name = "groupe_sanguins")
public class GroupeSanguin {
#Id
private String groupe;
#OneToMany(mappedBy = "groupeSanguin")
private List<Donneur> donneurs;
}
#Entity #Getter #Setter #NoArgsConstructor
public class Banque {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(unique = true,nullable = false)
private String nom;
private String adresse;
#Column(unique = true)
private String telephone;
private String localisation;
}
so my i want to know how to annotate the JpaRepository to take the two as primary key like this and is my annotation good for it to work ?
public interface ReserveRepository extends JpaRepository<
Reserve,
//what to put here ?
>
This isn't a JPA question in fact, it's a relationnal database conception.
If Reserve has is own data and links with other entity it has it own Id
You can add unicity constraint
#Entity
#Table(name = "reserves", uniqueConstraints={
#UniqueConstraint(columnNames = {"banque_id", "groupe_id"})
#Getter #Setter #NoArgsConstructor
public class Reserve {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne(cascade = CascadeType.ALL,fetch = FetchType.EAGER)
#JoinColumn(name = "groupe_id")
private GroupeSanguin bloodGroup;
#ManyToOne(cascade = CascadeType.ALL,fetch = FetchType.EAGER)
#JoinColumn(name = "banque_id")
private Banque banque;
private int quantity;
}
i've found this solutions too.
#Entity
#Table(name = "reserves")
#Getter #Setter #NoArgsConstructor
#IdClass(ReserveId.class) //this annotation will tell that id that the
// the id will be represented by a class
public class Reserve {
#Id
#ManyToOne(cascade = CascadeType.ALL,fetch = FetchType.EAGER)
#JoinColumn(name = "groupe_id")
private GroupeSanguin groupeSanguin;
#Id
#ManyToOne(cascade = CascadeType.ALL,fetch = FetchType.EAGER)
#JoinColumn(name = "banque_id")
private Banque banque;
private int quantity;
}
and the id class should implements Serializable like this :
#Getter #Setter
public class ReserveId implements Serializable {
private Banque banque;
private GroupeSanguin groupeSanguin;
}
and finally the repository will be like that :
#Repository
public interface ReserveRepo extends JpaRepository<Reserve, ReserveId>{}
See your Reserve class has nowhere mentioned composite primary key. First you need to fix the model, You can refer to the solution here How to create and handle composite primary key in JPA

Spring boot #OneToMany association saves id with null value

Hello guys i don't know why but when i tried to define an association
#one to many i get a null in the service_id and question_id.
first entity
#Entity
#Data
#NoArgsConstructor
#AllArgsConstructor
#Inheritance(strategy = InheritanceType.JOINED)
public class Services implements Serializable{
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
#Column(nullable = false, updatable = false)
private Long id;
private String serviceName;
private String description;
private String image;
#OneToMany(cascade = CascadeType.ALL)
private List<Questions> questions;
Second entity
#Entity
#Data
#NoArgsConstructor
#AllArgsConstructor
public class Questions implements Serializable {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
#Column(nullable = false, updatable = false)
private Long id;
private String question;
#Column(name="service_id")
private String service_id;
#OneToMany(cascade = CascadeType.ALL)
private List<Answers> answers;
third entity
#Entity
#Data
#NoArgsConstructor
#AllArgsConstructor
public class Answers implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(nullable = false, updatable = false)
private Long id;
private String answer;
private double cost;
#Column(name="question_id")
private String question_id;
you can find the image for the tables bellow
enter image description here
All you need to do is remove the following line from Both of your models:
#Column(nullable = false, updatable = false)
After this line: #GeneratedValue(strategy = GenerationType.IDENTITY)
That will solve your problem.

#ManyToOne and #OneToMany ends up in unlimited loop when retrieved through profileRepository.getByProfileId(id);

Class Jobs has Many to One relationship with Profile.
When I retrieve through profileRepository.getByProfileId(id) the response returns recursive data.
Also if you notice Profile has Login object. I don't want to return that as well.
#Entity
#Table(name = "tbl_profile")
#Builder(toBuilder = true)
#NoArgsConstructor
#AllArgsConstructor
#Getter
public class Profile {
#Id
#Column(name = "profile_id")
#GeneratedValue(strategy = GenerationType.AUTO)
long profileId;
#NonNull
#Column(name = "name")
String name;
#Column(name = "description", nullable = false)
String description;
#OneToOne
#JoinColumn(name = "login_id",
referencedColumnName = "login_id")
Login login;
#OneToMany(
mappedBy = "profile"
)
List<Jobs> job;
Class Jobs
#Entity
#Table(name = "tbl_job")
#Builder(toBuilder = true)
#NoArgsConstructor
#AllArgsConstructor
#Getter
public class Jobs {
#Id
#Column(name = "job_id")
#GeneratedValue(strategy = GenerationType.AUTO)
long jobId;
#NonNull
#Column(name = "job_role", nullable = false)
String joRole;
#Column(name = "description", nullable = false)
String description;
#ManyToOne
#JoinColumn(name = "profile_id",
referencedColumnName = "profile_id")
Profile profile;
}
Use #JsonIgnore to the property to ignore the output on JSON. Also according to your business logic, recheck if you need bidirectional association. You could maybe add only unidirectional association.

(Do not display relationship values)

I have two entity with name of the article and article Category.
and they have one-to-many relationships.
I use #JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class,property = "id")
but I cant see data of article category(category_id) in spring data rest.
ArticleCategory.class
#Entity
#Table(name = "article_category")
#Getter
#Setter
public class ArticleCategory implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "category_name")
private String categoryName;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "articleCategory", fetch = FetchType.LAZY)
private Set<Article> articles = new HashSet<>();
}
Article.class
#Entity
#Table(name = "article")
#Getter
#Setter
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
public class Article implements Serializable {
public Article() {
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "category_id", nullable = false)
private ArticleCategory articleCategory;
#Column(name = "title")
private String title;
#Column(name = "image_url")
private String image_url;
#Column(name = "short_description")
private String short_description;
#Column(name = "text")
private String text;
#Column(name = "keywords", nullable = true)
private String keywords;
#Column(name = "visit", nullable = false)
private int visit;
#Column(name = "code", nullable = false)
private UUID code;
#Column(name = "date_created")
#CreationTimestamp
private Date dateCreated;
#Column(name = "date_updated", nullable = false)
#UpdateTimestamp
private Date dateUpdated;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "user_id")
private User user;
public Article(String title, String image_url, String short_description, String text, String keywords, int visit, UUID code) {
this.title = title;
this.image_url = image_url;
this.short_description = short_description;
this.text = text;
this.keywords = keywords;
this.visit = visit;
this.code = code;
}
}
Article Repository
#CrossOrigin("http://localhost:4200")
#RepositoryRestResource(collectionResourceRel = "article", path = "article")
public interface ArticleRepository extends JpaRepository<Article,Long> {
Article findByCode(UUID uuid);
}
And this is output of spring data rest
enter image description here
That is exactly because you used #JsonManagedReference and #JsonBackReference. Keep in mind the following when using them:
#JsonManagedReference is the forward part of the relationship and is the one that gets serialized normally.
#JsonBackReference is the back part of the relationship and it will be omitted from serialization.
The serialized Article object does not contain a reference to the ArticleCategory object.
If you want to have any ArticleCategory data when serializing Article you can either use #JsonIdentityInfo so that one of the properties is serialized (in this case I've chosen id for both):
#Entity
#Table(name = "article")
#Getter
#Setter
#JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
public class Article implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "category_id", nullable = false)
private ArticleCategory articleCategory;
}
#Entity
#Table(name = "article_category")
#Getter
#Setter
#JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
public class ArticleCategory implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "category_name")
private String categoryName;
#OneToMany(cascade = CascadeType.ALL,mappedBy = "articleCategory" ,fetch = FetchType.LAZY)
private Set<Article> articles=new HashSet<>();
}
If you are only interested in categoryId another possibility would be to use #JsonIgnore on private Set<Article> articles property so that it is not serialized:
#Entity
#Table(name = "article_category")
#Getter
#Setter
public class ArticleCategory implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "category_name")
private String categoryName;
#JsonIgnore
#OneToMany(cascade = CascadeType.ALL,mappedBy = "articleCategory" ,fetch = FetchType.LAZY)
private Set<Article> articles=new HashSet<>();
}
If none of those suits your needs you might need to implement your own custom serializer. You can read more about all those options at https://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion.
I solved the problem using the controller
And that's why #JsonManageRefrence and #JsonBackRefrence do not work
I replaced the lazy load with the eager load in both entity
#ManyToOne(fetch = FetchType.Eager)
#JoinColumn(name = "user_id")
#JsonManageRefrence
private User user;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "articleCategory",
fetch = FetchType.Eager)
#JsonBackRefrence
private Set<Article> articles = new HashSet<>();
and then add a controller
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
#RestController
#RequestMapping("/getAllArticle")
public class MyController {
private ArticleRepository articleRepository;
// you must do constructor injection
#GetMapping("/getAllArticle")
public List<Article> allArticle()
{
return articleRepository.findAll();
}
}

Embed complex object in entity

I want to embed the following
#Embeddable
public class BaseEntity implements Serializable {
#Id
#GeneratedValue
private UUID id;
#CreatedDate
#Column(name = "created_date", updatable = false)
private LocalDateTime createdDate;
}
into my room entity
#Entity
#Data
#NoArgsConstructor
#Table(name = "room")
public class room {
#EmbeddedId
private BaseEntity baseEntity;
#Column(length = 80, nullable = false)
private String name;
}
So that my generated table looks like this
room
id
createdDate
name
But id and createdDate are not getting embedded
Instead of #Embeddable just extend your BaseEntity
#MappedSuperclass
#Getter
#Setter
public class BaseEntity implements Serializable {
#Id
#GeneratedValue
private UUID id;
#CreatedDate
#Column(name = "created_date", updatable = false)
private LocalDateTime createdDate;
}
#Entity
#Data
#NoArgsConstructor
#Table(name = "room")
public class room extends BaseEntity{
#Column(length = 80, nullable = false)
private String name;
}

Resources