result time of answer is very long, how to reduce it while using jpa? - spring-data-jpa

#Entity
#Table(name = "demo")
public class DemoEntity {
#ElementCollection
#Column(name = "demo_type_id", nullable = false)
#CollectionTable(name = "demo_entity_record_type", joinColumns = #JoinColumn(name =
"demo_entity_id"))
private Set<RecordType> recordTypes = new HashSet<>();
#ElementCollection
#Column(name = "demo_type_id", nullable = false)
#CollectionTable(name = "demo_entity_record_type1", joinColumns = #JoinColumn(name =
"demo_entity_id"))
private Set<DemoType> demoTypes1 = new HashSet<>();
#ElementCollection
#Column(name = "demo_type_id", nullable = false)
#CollectionTable(name = "demo_entity_record_type2", joinColumns = #JoinColumn(name =
"demo_entity_id"))
private Set<RecorType> recordTypes2 = new HashSet<>();
}
I have 3000 records of entity in DB. When I try to get 3000 entities I see in logs:
3000 select to entity table
3000 select to test_entity_record_type table by test_entity_id
3000 select to test_entity_record_type1 table by test_entity_id
3000 select to test_entity_record_type2 table by test_entity_id
As result time of answer is very long. How to reduce it?

You can use #BatchSize annotation:
#BatchSize(size = 1000)
private Set<RecordType> recordTypes = new HashSet<>();
Let me know if this works.

Related

How to save a copy of a entity

I use spring boot 3, I have this entity structure
#Data
#Entity
#Table
public class Repo {
#Id
#NotNull
private Long repoId;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "repo", cascade = {CascadeType.ALL})
private List<Pub> pubs = new ArrayList<>(0);
...
}
#Data
#Entity
#Table
public class Pub {
#Id
#Column
#NotNull
protected Long pubId;
#ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.ALL})
#JoinColumn(name = "type_id")
protected TypeDoc typeDoc;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "pub", cascade = {CascadeType.ALL}, orphanRemoval = true)
protected List<Person> persons = new ArrayList<>(0)
#ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL})
#JoinTable(name = "pub_cat", schema = "", joinColumns = { #JoinColumn(name = "pub_id", nullable = true, updatable = false) }, inverseJoinColumns = { #JoinColumn(name = "cat_pub_id", nullable = true, updatable = false) })
private List<CatPub> catPub = new ArrayList<>(0);
}
A repo has a lit of pub, in reality they can have only 2.
So I feed a Pub object..... put it it the list of depot, and i need to create exactly the same and put it in the list of depot.
what is the most effective way to do it?

Using Named Entity Graphs in Eclipselink not work

I have 2 classes
Collections
#Entity
#NamedEntityGraph(
name = "cars-graph",
attributeNodes = #NamedAttributeNode("cars"))
public class Collections {
#Id
#ReturnInsert(returnOnly=true)
private Long id;
#ManyToMany(cascade = ALL)
#JoinTable(name="CarsCollections",
joinColumns= #JoinColumn(name="COLLECTIONS_ID", referencedColumnName="ID"),
inverseJoinColumns=
{#JoinColumn(name = "MODELSRANGE_ID", referencedColumnName = "MODELSRANGE_ID"),
#JoinColumn(name = "MODELS_ID", referencedColumnName = "MODELS_ID"),
#JoinColumn(name = "TYPES_ID", referencedColumnName = "TYPES_ID")
}
)
public List<Cars> cars;
and Cars
#Entity(name = "Cars")
public class Cars {
#EmbeddedId
private CarsId id;
#ManyToOne(fetch = FetchType.EAGER)
#MapsId("modelsRangeid")
#JoinColumn(name = "MODELSRANGE_ID")
private ModelsRange modelsrange;
#ManyToOne(fetch = FetchType.EAGER)
#MapsId("modelsid")
#JoinColumn(name = "MODELS_ID")
private Models models;
#ManyToOne(fetch = FetchType.EAGER)
#MapsId("typesid")
#JoinColumn(name = "TYPES_ID")
private Types types;
#ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
#JoinColumn(name = "MAKE")
private Makes makes;
When i try to get Collections with Cars
EntityGraph entityGraph = em.getEntityGraph("cars-graph");
Collections collections = em.createQuery("select r from Collections r where r.id = :id", Collections.class)
.setParameter("id", 1L)
.setHint("javax.persistence.fetchgraph", entityGraph)
.getSingleResult();
System.out.println(collections.getCars());
I get {IndirectList: not instantiated}. Does not give errors, but Cars does not load.
If you add to the Collections entity for the Cars field "EAGER"
...
#ManyToMany(cascade = ALL, fetch = FetchType.EAGER)
#JoinTable(name="CarsCollections",
...
It works.
But then Cars will always load.
I use Jakarta EE9 and Eclipselink
Problem in javax name. In Jakarta EE need to use:
...
.setHint("jakarta.persistence.loadgraph", entityGraph)
...

How to delete entities in a chained one-to-many and many-to-many JPA relationship

I have a chain of entities as follows:
#Entity
#Table(name = "Patients")
public class Patient extends TimeStampedPersistable{
private static final long serialVersionUID = 1L;
#OneToMany(mappedBy="patient", cascade = CascadeType.ALL)
#PrivateOwned
private List<Insurance> insurances;
}
#Entity
#Table(name = "insurance")
public class Insurance extends PersistableEntity {
private static final long serialVersionUID = 1L;
#ManyToOne(optional=false)
#JoinColumn(name="patient_id", nullable=false)
private Patient patient;
#Column(name = "policy_number", unique = false, nullable = true)
private String policyNumber;
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
#JoinTable(name = "insurance_companycodes", joinColumns = {
#JoinColumn(name = "insurance_id", referencedColumnName = "id", nullable = false, updatable = false) }, inverseJoinColumns = {
#JoinColumn(name = "insuranceCompanyCode_id", referencedColumnName = "id", nullable = false, updatable = false) })
private Set<InsuranceCompanyCode> insuranceCompanyCodes = new HashSet<>();
}
#Entity
#Table(name = "insurance_company_codes")
public class InsuranceCompanyCode extends PersistableEntity {
private static final long serialVersionUID = 1L;
#Column(name = "identifier", unique = true, nullable = true)
private String identifier;
#ManyToMany(mappedBy = "insuranceCompanyCodes", fetch = FetchType.LAZY)
private Set<Insurance> insurances = new HashSet<>();
}
I need to remove insurance items from the Patient object. I am using the following code:
for (Iterator<Insurance> iterator = patient.getInsurances().iterator(); iterator.hasNext();) {
iterator.next();
iterator.remove();
}
This seems to work for child entities that don't have child entities, however in this situation the Insurance entity has child entities and is not actually removed (no exceptions are displayed). Note, I am using the EclipseLink specific annotation #PrivateOwned which I expected would have forced the removal of the Insurance entities.
Any guidance, suggestions appreciated!

JPARepository - sometimes create duplicate records

I have the following entity class.
#Data
#EqualsAndHashCode(callSuper=false)
#ToString(callSuper=true)
#Entity
#Table(name = "storeitem")
public class StoreItem extends SellableStoreItem {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private UUID id;
#EqualsAndHashCode.Exclude
#ToString.Exclude
#ManyToOne
#JoinColumn(name = "store_id")
private Store store;
#EqualsAndHashCode.Exclude
#ToString.Exclude
#ManyToOne
#JoinColumn(name = "storeitemcategory_id", nullable = true)
private StoreItemCategory storeItemCategory;
#EqualsAndHashCode.Exclude
#OneToMany(fetch = FetchType.EAGER, mappedBy = "storeItem")
private List<StoreItemTranslation> storeItemTranslationList = new ArrayList<>();
#EqualsAndHashCode.Exclude
#OneToMany(mappedBy = "storeItem",
cascade = CascadeType.ALL,
orphanRemoval = true)
private List<StoreItemOptionCollectionSelection> storeItemOptionCollectionSelections = new ArrayList<>();
#EqualsAndHashCode.Exclude
#Column(name = "uid")
private UUID uid = UUID.randomUUID();
#EqualsAndHashCode.Exclude
#CreationTimestamp
#Column(name = "createddate", nullable = false)
private LocalDateTime createdDate;
#EqualsAndHashCode.Exclude
#Column(name = "iscurrent", nullable = false)
private boolean isCurrent = true;
And in my service layer, I do the following.
private StoreItemResponse setStoreItemCreate(StoreItemDTO storeItemDTO, Store store, StoreItemCategory storeItemCategory) {
StoreItem storeItem = new StoreItem(storeItemDTO, store, storeItemCategory);
if(storeItemDTO.getUid() != null){
storeItem.setUid(storeItemDTO.getUid());
}
storeItem = storeItemRepository.save(storeItem);
// Create Translations for store Item
for (TranslationDTO translationDTO : storeItemDTO.getTranslationDTOs()) {
StoreItemTranslation translation = new StoreItemTranslation(translationDTO, storeItem);
storeItemTranslationRepository.save(translation);
}
return new StoreItemResponse(storeItem.getId(), DtoResponseStatus.OK);
}
However, when testing the code, I notice that there are times (not often but some cases) I see duplicate records (with different id) are being saved to database. And the duplicates are saved 2ms apart so I suspect storeItem = storeItemRepository.save(storeItem); created the duplicate records.
Why would this happen?

JPA cascade - deletion is not working when id is different in join table

I am using spring JPA to insert and delete the records in these tables. I can able to insert the record, but deletion is not happening due to different id's in emp_workstation table. If both employee_id and workstation_id were same then delete is working fine, but if both the id's were not same then delete not happening in employee table and emp_workstation table (cascade has set to 'ALL'). Does anybody face this problem before or know how to solve this issue?
Employee.java
#Setter
#Getter
#Builder(toBuilder = true)
#AllArgsConstructor(access = AccessLevel.PUBLIC)
#NoArgsConstructor(access = AccessLevel.PUBLIC)
#Entity
#Table(name = "employee")
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sq_employee_id")
#SequenceGenerator(name = "sq_employee_id", sequenceName = "sq_employee_id", allocationSize = 1)
private Long id;
#Column(name = "employee_name", length = 50)
private String name;
#OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinTable(name = "emp_workstation", joinColumns = {
#JoinColumn(name = "employee_id") }, inverseJoinColumns = { #JoinColumn(name = "workstation_id") })
private Workstation workstation;
}
Workstation.java
#Setter
#Getter
#Builder(toBuilder = true)
#AllArgsConstructor(access = AccessLevel.PUBLIC)
#NoArgsConstructor(access = AccessLevel.PUBLIC)
#Entity
#Table(name = "workstation")
public class Workstation {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sq_workstation_id")
#SequenceGenerator(name = "sq_workstation_id", sequenceName = "sq_workstation_id", allocationSize = 1)
private Long id;
#Column(name = "workstation_name", nullable = false, length = 100)
private String name;
#Column(name = "workstation_area", nullable = false, length = 100)
private String name;
#OneToOne(mappedBy = "workStation")
private Employee employee;
}
Example: In EMP_WORKSTATION table, if EMPLOYEE_ID and WORKSTATION_ID were same then deletion is working fine. but if both id were different then deletion is not working.
Thanks