Need to save/update child 500 or more rows in parent-child relationship with-in 10sec using Spring-Data-JPA - spring-boot

I have a scenario where I need to save or update 500 or more item in postgres db within 10sec using spring-data-jpa. below are my domain and service class.
GroupingForm.java
#Setter
#Getter
#NoArgsConstructor
#AllArgsConstructor
#EqualsAndHashCode
#Entity
#Table(name = "GroupingForm")
public class GroupingForm implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GenericGenerator(name = "uuid", strategy = "uuid2")
#GeneratedValue(generator = "uuid")
#Column(name = "grouping_form_id",unique = true, nullable = false)
private UUID groupingFormId;
#Column(name = "grouping_form_name")
private String groupingFormName;
#Column(name = "vid")
private String vid;
#Column(name = "vendor_name")
private String vendorName;
#Column(name = "hovbu")
private String hovbu;
#Column(name = "fid")
private String fid;
#Column(name = "factory_name")
private String factoryName;
#Column(name = "item_count")
private Integer itemCount;
#CreationTimestamp
#Column(name = "creation_date")
private Timestamp creationDate;
#Column(name = "created_by")
private String createdBy;
#UpdateTimestamp
#Column(name = "modified_date")
private Timestamp modifiedDate;
#Column(name = "modified_by")
private String modifiedBy;
#Column(name = "product_engineer")
private String productEngineer;
#Column(name = "status")
private String status;
#Column(name = "sourcing_type")
private String sourcingType;
#Column(name = "total_comments")
private Integer totalComments;
#Column(name = "factory_name_chinese")
private String factoryNameChinese;
#Column(name = "grouping_form_type")
private String groupingFormType;//to save as Product/transit/Product_transit
#Column(name = "ref_id")
private String refId;
#JsonManagedReference
#OneToMany(mappedBy = "groupingForm", cascade = CascadeType.ALL, orphanRemoval = true)
private List<ProductItemsMapping> productItems = new ArrayList<>();
#JsonManagedReference
#OneToMany(mappedBy = "groupingForm", cascade = CascadeType.ALL, orphanRemoval = true)
private List<TransitItemsMapping> transitItems = new ArrayList<>();
#Column(name = "pdf_status")
private String pdfStatus;
}
ProductItemsMapping.java
#Data
#Entity
#Table(name = "ProductItemsMapping")
public class ProductItemsMapping implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GenericGenerator(name = "uuid", strategy = "uuid2")
#GeneratedValue(generator = "uuid")
#Column(name = "product_item_id",unique = true, nullable = false)
private UUID productItemId;
#ToString.Exclude
#JsonBackReference
#JsonIgnore
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "grouping_form_id")
private GroupingForm groupingForm;
#JsonIgnore
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(referencedColumnName = "dim_Item_ID",name = "item_id")
private Item item;
#Column(name ="item_relationship_id", insertable = false,updatable = false)
private String itemRelationshipId;
#JsonIgnore
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "item_relationship_id",referencedColumnName = "dim_item_relationship_id")
private VendorFactoryItem vendorFactoryItem;
#Column(name = "edam_id")
private String edamId;
#Column(name = "model_number")
private String modelNumber;
#Column(name = "description")
private String description;
#Column(name = "material")
private String material;
#Column(name = "finishing_colour")
private String finishingColour;
#Column(name = "dimensions")
private String dimensions;
#Column(name = "product_net_weight")
private String productNetWeight;
#Column(name = "insertion_order")
private Integer insertionOrder;
#Column(name = "comments")
private String comments;
#Column(name = "item_unique_id")
private String itemUniqueId;
}
TransitItemsMapping.java
#Data
#Entity
#Table(name = "TransitItemsMapping")
public class TransitItemsMapping implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GenericGenerator(name = "uuid", strategy = "uuid2")
#GeneratedValue(generator = "uuid")
#Column(name = "transit_Item_id",unique = true, nullable = false)
private UUID transitItemId;
#ToString.Exclude
#JsonBackReference
#JsonIgnore
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "grouping_form_id")
private GroupingForm groupingForm;
#JsonIgnore
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(referencedColumnName = "dim_Item_ID",name = "item_id")
private Item item;
#Column(name ="item_relationship_id", insertable = false,updatable = false)
private String itemRelationshipId;
#JsonIgnore
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "item_relationship_id",referencedColumnName = "dim_item_relationship_id")
private VendorFactoryItem vendorFactoryItem;
#Column(name = "edam_id")
private String edamId;
#Column(name = "model_number")
private String modelNumber;
#Column(name = "description")
private String description;
#Column(name = "packaging_details")
private String packagingDetails;
#Column(name = "packaging_method")
private String packagingMethod;
#Column(name = "is_side_stack")
private String isSideStack;
#Column(name = "quantity")
private Integer quantity;
#Column(name = "dimensions")
private String dimensions;
#Column(name = "product_net_weight")
private String productNetWeight;
#Column(name = "plastic_bag_ind")
private String plasticBagInd;
#Column(name = "insertion_order")
private Integer insertionOrder;
#Column(name = "comments")
private String comments;
#Column(name = "item_unique_id")
private String itemUniqueId;
#Column(name = "itm_pak_qty")
private Integer itemPackQuantity;
}
Item.java
#Setter
#Getter
#NoArgsConstructor
#AllArgsConstructor
#EqualsAndHashCode
#Entity
#Table(name = "Item")
public class Item implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
//#GenericGenerator(name = "uuid", strategy = "uuid2")
//#GeneratedValue(generator = "uuid")
#JsonIgnore
#Column(name = "dim_Item_ID", unique = true, nullable = false)
private UUID dimItemId;
//mdm columns start
#Valid
#EmbeddedId
private ItemId itemId;
#Column(name = "model")
private String model;
#Column(name = "description")
private String description;
#CreationTimestamp
#Column(name="effective_date")
private Timestamp effectiveDate;
#JsonIgnore
#Column(name="expiration_date")
private Timestamp expirationDate;
#JsonIgnore
#Column(name="business_area_number")
private Integer businessAreaNumber;
#JsonIgnore
#Column(name="business_area_desc")
private String businessAreaDesc;
#JsonIgnore
#Column(name="division_number")
private Integer divisionNumber;
#JsonIgnore
#Column(name="division_desc")
private String divisionDesc;
#JsonIgnore
#Column(name="sub_division_number")
private Integer subDivisionNumber;
#JsonIgnore
#Column(name="sub_division_desc")
private String subDivisionDesc;
#JsonIgnore
#Column(name="product_group_number")
private Integer productGroupNumber;
#JsonIgnore
#Column(name="product_group_desc")
private String productGroupDesc;
#JsonIgnore
#Column(name="assortment")
private Integer assortment;
#JsonIgnore
#Column(name="assortment_desc")
private String assortmentDesc;
#JsonIgnore
#Column(name="status")
private Integer status;
#JsonIgnore
#Column(name="status_desc")
private String statusDesc;
#Column(name = "origin_country")
private String originCountry;
#Column(name = "destination_country")
private String destinationCountry;
#Column(name = "is_private_brand")
private String isPrivateBrand;
#Column(name = "brand")
private String brandName;
#Column(name = "item_weight")
private Double itemWeight;
#Column(name = "in_box_height")
private Double inBoxHeight;
#Column(name = "in_box_width")
private Double inBoxWidth;
#Column(name = "in_box_depth")
private Double inBoxDepth;
#Column(name = "primary_image")
private String primaryImage;
#Column(name = "component_materials")
private String componentMaterials;
#Column(name = "product_detail")
private String productDetail;
#Column(name = "finishing_color")
private String finishingColor;
#Column(name = "packaging_method")
private String packagingMethod;
#Column(name = "packaging_quantity")
private Integer packagingQuantity;
#Column(name = "out_box_depth")
private Double outBoxDepth;
#Column(name = "out_box_height")
private Double outBoxHeight;
#Column(name = "out_box_width")
private Double outBoxWidth;
#Column(name = "net_weight")
private Double netWeight;
#Column(name = "plastic_bag_ind")
private String plasticBagInd;
//mdm columns ends
//Adhoc specific start
#JsonIgnore
#Column(name="is_current")
private Integer isCurrent;
#JsonIgnore
#Column(name="remark")
private String remark;
#JsonIgnore
#Column(name="is_valid")
private String isValid;
#CreationTimestamp
#Column(name="creation_date")
private Timestamp creationDate;
#JsonIgnore
#Column(name="created_by")
private String createdBy;
#JsonIgnore
#UpdateTimestamp
#Column(name="last_modified_date")
private Timestamp lastModifiedDate;
#Column(name = "is_adhoc_item")
private String isAdhocItem;
//Adhoc specific ends
#JsonIgnore
#OneToMany(cascade = CascadeType.ALL, mappedBy = "item")
private List<VendorFactoryItem> vendorFactoryItems;
#JsonIgnore
#OneToMany(cascade = CascadeType.ALL, mappedBy = "item")
private List<ProductItemsMapping> productItems = new ArrayList<>();
#JsonIgnore
#OneToMany(cascade = CascadeType.ALL, mappedBy = "item")
private List<TransitItemsMapping> transitItems = new ArrayList<>();
#Transient
#JsonIgnore
private Integer itemNumber;
#Transient
#JsonIgnore
private String itemRelationshipId;
#Transient
#JsonIgnore
private String vendorId;
#Transient
#JsonIgnore
private String retailer;
#Transient
#JsonIgnore
private String fid;
#Transient
#JsonIgnore
private String hovbu;
#Column(name="sourcing_type")
private String sourcingType;
#Column(name = "itm_pak_qty")
private Integer itemPackQuantity;
#Column(name = "barcode")
private String barcode;
#Column(name = "item_type")
private String itemType;
#Column(name = "item_cube")
private String itemCube;
}
VendorFactoryItem.java
#Setter
#Getter
#NoArgsConstructor
#AllArgsConstructor
#EqualsAndHashCode
#Entity
#Builder
#Table(name = "vendorfactoryitem")
public class VendorFactoryItem implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#EmbeddedId
private VendorFactoryItemId vendorFactoryItemId;
#JsonIgnore
#Column(name = "dim_item_relationship_id")
private String itemRelationshipId;
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumns({
#JoinColumn(name = "hovbu",updatable = false,insertable = false),
#JoinColumn(name = "item_number",updatable = false,insertable = false),
#JoinColumn(name = "retailer",updatable = false,insertable = false)
})
private Item item;
#Column(name = "item_id")
private String itemIdRel;
#Column(name = "is_adhoc_rel")
private String isAdHocRel;
#Column(name = "dim_factory_import_id")
private String dimFactoryImportId;
#Column(name = "factory_short_name")
private String factoryShortName;
#Column(name = "company_id")
private String companyId;
#Column(name = "vendor_short_name")
private String vendorShortName;
#Column(name = "remark")
private String remark;
#Column(name = "is_valid")
private String isValid;
#Column(name = "created_on")
private Timestamp createdOn;
#Column(name = "created_by")
private String createdBy;
#Column(name = "last_modified_date")
private Timestamp lastModifiedDate;
#Column(name = "effective_date")
private Timestamp effectiveDate;
#JsonIgnore
#OneToMany(cascade = CascadeType.ALL, mappedBy = "vendorFactoryItem")
private List<ProductItemsMapping> productItems = new ArrayList<>();
#JsonIgnore
#OneToMany(cascade = CascadeType.ALL, mappedBy = "vendorFactoryItem")
private List<TransitItemsMapping> transitItems = new ArrayList<>();
}
GroupingFormRepository.java
#Repository
public interface GroupingFormRepository
extends JpaRepository<GroupingForm, UUID>, GroupingFormRepositoryCustom {
}
GroupingFormService.java
#Transactional
public GroupingFormDto saveGroupingFormV1(GroupingFormDto groupingFormDto) {
//do the mapping DTO to DOMAIN..remove the code ..
**GroupingForm groupingFormSaved = groupingFormRepository.save(groupingForm);**
}
With in the GroupingForm object I am setting the transitItem and productItem to save or update. And also adding Item and VendorfactoryItems not for save or update. what are the best way I can optimize this save and update with in 10 sec while I am passing more than 500 productItem and 500 transitItem.
Thanks in advance.

Related

Spring specification query for one to many join and sum of field is grater then given value

I am creating filter using joining this three entity seeker_job_application,seeker_profile and seeker_experience. where I want achieve result as below query.
In filter I want to find out seeker_profile whose total_moth of experience should be grater then or equal to given value i.e 20, one seeker_profile has multiple experience so I need to group by profile and sum of their experience and then compare with given value. is it possible to do this using spring specification?
How to check that seeker total month of experience is grater then or equal to given value?
Relation between table is
seeker_job_application 1<-->1 seeker_profile 1<---->* seeker_experience
Want to achieve query like this
select r.sja_id,r.sp_id,r.name,r.company_name,r.total_month from (
select sja.id as sja_id , sp.id as sp_id , sp.`name`,se.company_name,sum(se.total_month) as total_month
from seeker_job_application sja
INNER JOIN seeker_profile sp on sp.id = sja.seeker_id
INNER JOIN seeker_experience se on se.seeker_id = sp.id
where job_id =1 group by sp.id ) as r where r.total_month > 20;
#Entity
#Table(name = "seeker_job_application")
#Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class SeekerJobApplication implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#NotNull
#Column(name = "seeker_id", nullable = false)
private Long seekerId;
#NotNull
#Column(name = "job_id", nullable = false)
private Long jobId;
#Column(name = "apply_date")
private Instant applyDate;
#Column(name = "profile_viewed")
private Boolean profileViewed;
#Column(name = "on_hold")
private Boolean onHold;
#Column(name = "interview_schedule")
private Boolean interviewSchedule;
#Column(name = "rejected")
private Boolean rejected;
#Column(name = "selected")
private Boolean selected;
#Column(name = "prefered_location_id")
private Long preferedLocationId;
#Column(name = "work_preference")
private String workPreference;
#Column(name = "resume_file_path")
private String resumeFilePath;
#Column(name = "status")
private String status;
#ManyToOne
#JoinColumn(name="seeker_id",referencedColumnName = "id", insertable = false, updatable = false)
private SeekerProfile seekerProfile;
#Data
#Entity
#Table(name = "seeker_profile")
#Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class SeekerProfile implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "id")
private Long id;
#Column(name = "name", nullable = false)
private String name;
#Column(name = "mobile_number", nullable = false)
private String mobileNumber;
#Column(name = "password")
private String password;
#Column(name = "email", nullable = false)
private String email;
#Column(name = "house_number")
private String houseNumber;
#Column(name = "address_line_1")
private String addressLine1;
#Column(name = "address_line_2")
private String addressLine2;
#Column(name = "city")
private String city;
#Column(name = "postcode")
private String postcode;
#Column(name = "state")
private String state;
#Column(name = "country")
private String country;
#Column(name = "website")
private String website;
#Column(name = "linkedin")
private String linkedin;
#Column(name = "facebook")
private String facebook;
#Column(name = "gender")
private String gender;
#Column(name = "dob")
private String dob;
#Column(name = "resume")
private String resume;
#Column(name = "wfh")
private String wfh;
#Column(name = "profile_completed")
private String profileCompleted;
#OneToOne
#JoinColumn(unique = true)
private Location preferedLocation;
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(name = "seeker_skill", joinColumns = { #JoinColumn(name = "seeker_id") }, inverseJoinColumns = { #JoinColumn(name = "skill_id") })
private Set<Skill> skills;
#OneToMany(fetch = FetchType.EAGER)
#JoinColumn(name="seeker_id",referencedColumnName = "id", insertable = false, updatable = false)
private Set<SeekerExperience> seekerExperiences;
#OneToMany
#JoinColumn(name="seeker_id",referencedColumnName = "id", insertable = false, updatable = false)
private Set<SeekerEducation> seekerEducation;
#Entity
#Table(name = "seeker_experience")
#Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class SeekerExperience implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#NotNull
#Column(name = "seeker_id", nullable = false)
private Long seekerId;
#NotNull
#Column(name = "job_title", nullable = false)
private String jobTitle;
#NotNull
#Column(name = "company_name", nullable = false)
private String companyName;
#NotNull
#Column(name = "start_date", nullable = false)
private String startDate;
#NotNull
#Column(name = "end_date", nullable = false)
private String endDate;
#Column(name = "total_month")
private Integer totalMonth;
#Column(name = "location")
private String location;
#Column(name = "role_description")
private String roleDescription;
Specification<SeekerJobApplication> specification = Specification.where(null);
specification = specification.and((root, query, cb) -> {
Join<SeekerJobApplication, SeekerProfile> seekerProfile=root.join(SeekerJobApplication_.seekerProfile);
Join<SeekerProfile, SeekerExperience> seekerExperience = seekerProfile.join(SeekerProfile_.seekerExperiences);
query.having(cb.greaterThanOrEqualTo(cb.sum(seekerExperience.get(SeekerExperience_.totalMonth)), criteria.getTotalExperience().getEquals()));
query.getRestriction();
});
This will give me result as below query
select sja.* from seeker_job_application sja
INNER JOIN seeker_profile sp on sja.seeker_id = sp.id
INNER JOIN seeker_experience se on se.seeker_id = sp.id
where sja.job_id = 1
GROUP BY sp.id
having sum(se.total_month) > 20

Hibernate Enver - Listening for only one change in referenced class

I have an entity as shown below that I am auditing using Hibernate Enver
#Entity
#Table(name = "watch_item")
#Audited
public class WatchItemEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Type(type = "uuid-char")
#Column(name = "watch_item_id", columnDefinition = "VARCHAR(36)")
private UUID watchItemId;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "watch_model_id")
private WatchModelEntity watchModel;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "private_user_id")
private PrivateUserEntity privateUser;
private String serialNumber;
private Integer productionYear;
private String generalCondition;
private Boolean isMovementFullyFunctional;
private Boolean isInOriginalCondition;
private String comment;
private Boolean isProofOfPurchaseAvailable;
private String country;
private Boolean isCustomsDeclared;
private Boolean hasPaper;
private Boolean hasBox;
private String otherAccessories;
#CreatedDate private LocalDateTime createdDate;
#LastModifiedDate private LocalDateTime modifiedDate;
private String lastServiceProvider;
private LocalDate lastServiceDate;
private BigDecimal lastServiceCost;
private BigDecimal purchasedPrice;
private LocalDate purchasedOn;
...
}
As you can see, it has a PrivateUserEntity field. I want Hibernate Envers to record a change when the privateUser changes (and not record changes in PrivateUserEntity that correspond to the privateUser). However, I don't want to create a Private_User_Aud table. To give some context, a WatchItem can only be owned by one PrivateUser and hence, when the PrivateUser field changes, that means that the WatchItem's owner changed. The entity can be seen below
#Entity
#Table(name = "private_user")
public class PrivateUserEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Type(type = "uuid-char")
#Column(name = "private_user_id", columnDefinition = "VARCHAR(36)")
private UUID privateUserId;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "user_id")
private UserEntity user;
#LastModifiedDate private LocalDate modifiedDate;
private String title;
private String firstName;
private String lastName;
private String phone;
private LocalDate dateOfBirth;
private String email;
private String gender;
private String nationality;
private String residencyPermitType;
private LocalDate residencyPermitValidSince;
private String preferredLanguage;
...
}
Is this possible? And if so, how?
You can disable audit for it, doesn't work?
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "private_user_id")
#NotAudited
private PrivateUserEntity privateUser;

Why am i getting an infinite list with stack overflow?

Im making an bungalow reservation system but i cant get a list with an many to many relationship i keep getting an infinite list with stackoverflow error.
This worked find but happens when i added the many to many relationship.
Attraction Entity this contains a many to many relationship with
the visit entity
#Entity
#Table(name = "attraction")
public class Attraction {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(name = "name")
private String name;
#Column(name = "historical")
private Boolean historical;
#Column(name = "religious")
private Boolean religious;
#Column(name = "beaches")
private Boolean beaches;
#Column(name = "animal_sanc")
private Boolean animalSanc;
#Column(name = "hiking")
private Boolean hiking;
#Column(name = "forest")
private Boolean forest;
#Column(name = "parks")
private Boolean parks;
#Column(name = "lakes")
private Boolean lakes;
#ManyToOne
#JoinColumn(name = "bungalow_id")
private Bungalow bungalow;
#ManyToMany(cascade = {CascadeType.MERGE,CascadeType.REFRESH})
#JoinTable(
name = "visit_has_attraction",
joinColumns = #JoinColumn(name = "attraction_id"),
inverseJoinColumns = #JoinColumn(name = "visit_id")
)
private List<Visit> visitList;
//Constructer, Getters and Setters
}
Visit entity
This is the other end of the many to many relationship
#Entity
#Table(name = "visit")
public class Visit {
#Id
#Column(name = "id")
private int id;
#Column(name = "date")
private Date date;
#ManyToOne
#JoinColumn(name = "user_id")
private User user;
#ManyToMany(cascade = {CascadeType.MERGE,CascadeType.REFRESH})
#JoinTable(
name = "visit_has_attraction",
joinColumns = #JoinColumn(name = "visit_id"),
inverseJoinColumns = #JoinColumn(name = "attraction_id")
)
List<Attraction> attractions;
//Constructer, Getters and Setters
}
JPA Repository
public List<Attraction> findAttractionsByVisitList(Visit visit);
ER of the app
1
I added #JsonIgnore to one of the sides in many to many relationships and added #JsonBackReference to ManyToOne side and #JsonManagedReference to OneToMany side of all the one to many relationships.
#Entity
#Table(name = "attraction")
public class Attraction {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(name = "name")
private String name;
#Column(name = "historical")
private Boolean historical;
#Column(name = "religious")
private Boolean religious;
#Column(name = "beaches")
private Boolean beaches;
#Column(name = "animal_sanc")
private Boolean animalSanc;
#Column(name = "hiking")
private Boolean hiking;
#Column(name = "forest")
private Boolean forest;
#Column(name = "parks")
private Boolean parks;
#Column(name = "lakes")
private Boolean lakes;
#ManyToOne
#JoinColumn(name = "bungalow_id")
#JsonBackReference
private Bungalow bungalow;
#ManyToMany(cascade = {CascadeType.MERGE,CascadeType.REFRESH})
#JoinTable(
name = "visit_has_attraction",
joinColumns = #JoinColumn(name = "attraction_id"),
inverseJoinColumns = #JoinColumn(name = "visit_id")
)
#JsonIgnore
private List<Visit> visitList;
//Constructer, Getters and Setters
}
Visit entity
This is the other end of the many to many relationship
#Entity
#Table(name = "visit")
public class Visit {
#Id
#Column(name = "id")
private int id;
#Column(name = "date")
private Date date;
#ManyToOne
#JoinColumn(name = "user_id")
#JsonBackReference
private User user;
#ManyToMany(cascade = {CascadeType.MERGE,CascadeType.REFRESH})
#JoinTable(
name = "visit_has_attraction",
joinColumns = #JoinColumn(name = "visit_id"),
inverseJoinColumns = #JoinColumn(name = "attraction_id")
)
List<Attraction> attractions;
//Constructer, Getters and Setters
}

springboot jpa combine two tables

I want to query data from two tables,
location field in Translation is a foreign key from id field of Location
#Entity
#Table(name = "Translation")
#Data
public class Translation {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#NotNull private String language;
#NotNull private String name;
#NotNull private String description;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "location", nullable = false, insertable = false, updatable = false)
#Fetch(FetchMode.JOIN)
private Location location;
}
#Entity
#Table(name = "Location")
#Data
public class Location {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#NotNull private String code;
#NotNull private String type;
private Double longitude;
private Double latitude;
#Column(name = "parent_id")
private Integer parentId;
#OneToMany(targetEntity = Translation.class, mappedBy="id", fetch = FetchType.EAGER)
private Set<Translation> translations;
}
————————————————————————————————————————
But when I use a query
#Query(
"SELECT new com.afkl.travel.exercise.model.RetrieveLocationResponse("
+ "loc.code, tran.name, loc.type, loc.latitude, loc.longitude, tran.description, loc.parentId)"
+ "FROM Location loc LEFT JOIN loc.translation tran")
List<RetrieveLocationResponse> fetchLeftJoin();
All the fields related to Translation is null, having no idea what happened
UPDATE
The following ones work for me.
#OneToMany(mappedBy = "location", cascade = CascadeType.ALL)
#JsonIgnore
private Set<Translation> translations;
#ManyToOne
#JoinColumn(name = "location")
private Location location;
try
#OneToMany(mappedBy = "location", cascade = CascadeType.ALL)
#JsonIgnore
private Set<Translation> translations;
#ManyToOne
#JoinColumn(name = "location")
private Location location;

Spring OneToMany relation with composite key to another with a composite key

I want to have a ManyToOne relation between 2 classes (Chapter & Camera). A chapter object contains many Camera objects.
The problem is my parent class (Chapter) already has a composite key.
Chapter composite key:
#Embeddable
public class ChapterKey implements Serializable {
#Column(name = "Chapter_ID", nullable = false)
private int chapterID;
#Column(name = "Operation_FK", nullable = false)
private int operationFK;
}
Chapter class:
#Entity
public class Chapter implements Serializable
{
private static final long serialVersionUID = 1L;
#EmbeddedId
private ChapterKey chapterKey;
#Column(name="Chapter_Name")
private String chapterName;
#Column(name="Chapter_Description")
private String chapterDescription;
#Column(name="Chapter_View_Range")
private int chapterViewRangeInterval;
#Column(name="Chapter_Video_Length")
private int chapterVideoLength;
}
Camera key:
#Embeddable
public class CameraKey implements Serializable {
#Column(name = "Camera_ID", nullable = false)
private int cameraID;
#Column(name = "Chapter_FK", nullable = false)
private int chapterFK;
#Column(name = "Operation_FK", nullable = false)
private int operationFK;
}
Camera class:
#Entity
public class Camera implements Serializable
{
private static final long serialVersionUID = 1L;
#EmbeddedId
private CameraKey cameraKey;
#Column(name="Camera_Description")
private String cameraDescription;
#Column(name="Camera_Usage")
private int cameraUsage;
#Column(name="Video_URL")
private String videoURL;
}
My question is, how do i make a OneToMany relationship between those 2 classes?
This answer for chapter side pk(Chapter_ID, Operation_FK) and camera side pk(camera_id,chapter_fk,operation_fk)
ER for is below.
Chapter.class is
#Entity
public class Chapter implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected ChapterPK chapterPK;
#Basic(optional = false)
#Column(name = "chapter_name", nullable = false, length = 12)
private String chapterName;
#Basic(optional = false)
#Column(name = "chapter_description", nullable = false, length = 12)
private String chapterDescription;
#Basic(optional = false)
#Column(name = "chapter_Vvew_range", nullable = false)
private int chapterVvewrange;
#Basic(optional = false)
#Column(name = "chapter_video_length", nullable = false)
private int chapterVideoLength;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "chapter")
private Collection<Camera> cameraCollection;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "chapter1")
private Collection<Camera> cameraCollection1;
}
ChapterPK.class
#Embeddable
public class ChapterPK implements Serializable {
#Basic(optional = false)
#Column(name = "chapter_id", nullable = false)
private int chapterId;
#Basic(optional = false)
#Column(name = "operation_fk", nullable = false)
private int operationFk;
}
Camera.class
#Entity
public class Camera implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected CameraPK cameraPK;
#Basic(optional = false)
#Column(name = "camera_description", nullable = false, length = 12)
private String cameraDescription;
#Basic(optional = false)
#Column(name = "camera_usage", nullable = false)
private int cameraUsage;
#Basic(optional = false)
#Column(name = "video_url", nullable = false)
private int videoUrl;
#JoinColumn(name = "chapter_fk", referencedColumnName = "chapter_id", nullable = false, insertable = false, updatable = false)
#ManyToOne(optional = false)
private Chapter chapter;
#JoinColumn(name = "operation_fk", referencedColumnName = "operation_fk", nullable = false, insertable = false, updatable = false)
#ManyToOne(optional = false)
private Chapter chapter1;
}
CameraPK.class
#Embeddable
public class CameraPK implements Serializable {
#Basic(optional = false)
#Column(name = "camera_id", nullable = false)
private int cameraId;
#Basic(optional = false)
#Column(name = "chapter_fk", nullable = false)
private int chapterFk;
#Basic(optional = false)
#Column(name = "operation_fk", nullable = false)
private int operationFk;
}
In here both side has two way binding.
This is ER for pk(camera_id) & pk(chapter_id,operation_fk) problem
This is a Chapter class.
#Entity
public class Camera implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#Column(name = "camera_id", nullable = false)
private Integer cameraId;
#Basic(optional = false)
#Column(name = "camera_description", nullable = false, length = 12)
private String cameraDescription;
#Basic(optional = false)
#Column(name = "camera_usage", nullable = false)
private int cameraUsage;
#Basic(optional = false)
#Column(name = "video_url", nullable = false)
private int videoUrl;
#JoinColumn(name = "chapter_fk", referencedColumnName = "chapter_id", nullable = false)
#ManyToOne(optional = false, fetch = FetchType.EAGER)
private Chapter chapterFk;
#JoinColumn(name = "operation_fk", referencedColumnName = "operation_fk", nullable = false)
#ManyToOne(optional = false, fetch = FetchType.EAGER)
private Chapter operationFk;
}
this is ChapterPK.class that define primary key of your chapter class. it has composite primary key.
#Embeddable
public class ChapterPK implements Serializable {
#Basic(optional = false)
#Column(name = "chapter_id", nullable = false)
private int chapterId;
#Basic(optional = false)
#Column(name = "operation_fk", nullable = false)
private int operationFk;
}
finally camera.class
#Entity
public class Chapter implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected ChapterPK chapterPK;
#Basic(optional = false)
#Column(name = "chapter_name", nullable = false, length = 12)
private String chapterName;
#Basic(optional = false)
#Column(name = "chapter_description", nullable = false, length = 12)
private String chapterDescription;
#Basic(optional = false)
#Column(name = "chapter_Vvew_range", nullable = false)
private int chapterVvewrange;
#Basic(optional = false)
#Column(name = "chapter_video_length", nullable = false)
private int chapterVideoLength;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "chapterFk", fetch = FetchType.EAGER)
private Collection<Camera> cameraCollection;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "operationFk", fetch = FetchType.EAGER)
private Collection<Camera> cameraCollection1;
}
In here I use two way binding in both chapter and camera classes. if you are using composite primary key. you have to manage additional embedded primary key object.

Resources