Hibernate Not Deleting the orphan Child Entites - java

I am beginner in JPA/Hibernate so this code could be fundamentally wrong but i want to basically delete the keySkills by leveraging orphan Removal. I have tried the following ways, please guide me on what i am doing wrong
Job Entity
public class Job extends AuditableBaseObject implements Serializable {
#ManyToOne
#JoinColumn(name = "EMPLOYER_ID")
private Employer employer;
#OneToMany(mappedBy = "job", orphanRemoval = true,fetch = FetchType.LAZY)
#JsonIgnoreProperties("job")
#Where(clause = "RETIRED=0")
private List<JobAcceptableWorkStatus> jobAcceptWork;
#OneToMany(mappedBy = "job", orphanRemoval = true,fetch = FetchType.LAZY)
#JsonIgnoreProperties("job")
#Where(clause = "RETIRED=0")
private List<JobKeySkills> jobKeySkills;
#Column(name = "TITLE")
private String title;
#Column(name = "DESCRIPTION")
private String description;
#Column(name = "MIN_YEARS_OF_EXPERIENCE")
private int minYearsOfExperience;
}
KeySkills Entity
public class JobKeySkills extends BaseObject implements Serializable {
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "JOB_ID")
#JsonIgnore
private Job job;
#ManyToOne
#JoinColumn(name = "KEY_SKILL_ID")
private ReferenceData keySkill;
#Column(name = "SKILL_LEVEL")
private String skillLevel;
#Column(name = "SKILL_PRIORITY")
private String skillPriority;
}
I am trying to delete the jobSkills by setting
job.setRetired(false);
job.setKeySkills(null);
jobRepository.save(job);
And also tried
jobkeySkillsToBeAdded.setRetired(false);
jobkeySkillsToBeAdded.setJob(null);
jobKeySkillsRepository.save(jobkeySkillsToBeAdded);

Try adding the cascade type to #OneToMany annotations in Job as follows:
public class Job extends AuditableBaseObject implements Serializable {
#ManyToOne
#JoinColumn(name = "EMPLOYER_ID")
private Employer employer;
#OneToMany(mappedBy = "job", cascade = { CascadeType.REMOVE, CascadeType.PERSIST },
orphanRemoval = true,fetch = FetchType.LAZY)
#JsonIgnoreProperties("job")
#Where(clause = "RETIRED=0")
private List<JobAcceptableWorkStatus> jobAcceptWork;
#OneToMany(mappedBy = "job", cascade = { CascadeType.REMOVE, CascadeType.PERSIST },
orphanRemoval = true,fetch = FetchType.LAZY)
#JsonIgnoreProperties("job")
#Where(clause = "RETIRED=0")
private List<JobKeySkills> jobKeySkills;
#Column(name = "TITLE")
private String title;
#Column(name = "DESCRIPTION")
private String description;
#Column(name = "MIN_YEARS_OF_EXPERIENCE")
private int minYearsOfExperience;
}

Related

Hibernate JPA #OneToMany join on 2 columns with OR statement in Entity

I have the following class:
public class Nomenclature extends BaseEntity {
#Id
#Column(name = "NOMENCLATURE_CODE")
private String nomenclatureCode;
#OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL}, mappedBy = "nomenclatureCode", orphanRemoval = true)
private List<Cumul> cumuls = new ArrayList<>();
}
I want to join the following Cumul class on 2 columns WHERE cumul.nomenclatureCode = nomenclature.nomenclatureCode OR cumul.nomenclatureCodeAllowedCumul = nomenclature.nomenclatureCode
public class Cumul extends BaseEntity {
#Id
#Column(columnDefinition = "NUMERIC")
#GeneratedValue(generator = "CUMUL", strategy = GenerationType.SEQUENCE)
private Long id;
#Column(name = "NOMENCLATURE_CODE")
private String nomenclatureCode;
#Column(name = "NOMENCLATURE_CODE_ALLOWED_CUMUL")
private String nomenclatureCodeAllowedCumul;
#OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL},orphanRemoval = true)
#JoinColumns(
{
#JoinColumn(name = "nomenclature_code", referencedColumnName = "nomenclature_code"),
#JoinColumn(name = "nomenclature_code_allowed_cumul", referencedColumnName = "nomenclature_code")
})
private List<Cumul> cumuls = new ArrayList<>();
Worked but this an AND statement not an OR what I was looking for

JPA query take huge amount of time for basic select query?

I have created JPA entities class. But using basic query taking humongous amount of time for basic sql query having 100 records in database.
I have 4 tables. (Group/GroupA/GroupB/GroupC) having below structure.
#Table(name = "group")
public class Group implements Serializable {
#Id
#Column(name = "id")
private String id;
#Column(name = "publish_date")
private LocalDate publishDate;
#OneToOne(mappedBy = "group", cascade = CascadeType.ALL)
private GroupA groupA;
#OneToOne(mappedBy = "group", cascade = CascadeType.ALL)
private GroupB groupB;
#OneToOne(mappedBy = "group", cascade = CascadeType.ALL)
private GroupC groupC;
}
#Table(name = "groupA")
public class GroupA {
#Id
#Column(name = "group_id")
private Long groupID;
#Column(name = "name")
private String name;
#OneToOne
#JoinColumn(name = "id")
#JsonIgnore
private Group Group;
}
#Table(name = "groupB")
public class GroupB {
#Id
#Column(name = "group_id")
private Long groupID;
#Column(name = "name")
private String name;
#OneToOne
#JoinColumn(name = "id")
#JsonIgnore
private Group Group;
}
#Table(name = "groupC")
public class GroupC {
#Id
#Column(name = "group_id")
private Long groupID;
#Column(name = "name")
private String name;
#OneToOne
#JoinColumn(name = "id")
#JsonIgnore
private Group Group;
}
Repository class:
#Repository
public interface GroupRepository extends JpaRepository<Group, Long> {
#Query("select r from Group r WHERE r.publishDate = ?1")
List<Group> findAllGroupForDate(LocalDate businessDate);
}
The above basic query is taking 1 minute 30 seconds for around 100 rows in Main Group table.
Please help if I am making anything wrong in entity class.
THanks.
Try to use the Lazy loading concept.
#OneToOne(mappedBy = "group", cascade = CascadeType.ALL, fetch = FetchType.LAZY)

How to replace CriteriaBuilder with Spring JPA

I have next classes:
#Entity
#Table
public class Lesson implements ModelEntity {
#Id
#Column(name = "lesson_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "course_id")
private Course course;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "lesson_type_id")
private LessonType lessonType;
private LocalDate date;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "time_slot_id")
private TimeSlot timeSlot;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "auditorium_id")
private Auditorium auditorium;
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "lesson_teacher", joinColumns = #JoinColumn(name = "lesson_id"), inverseJoinColumns = #JoinColumn(name = "person_id"))
private Set<Teacher> teachers = new HashSet<>();;
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "lesson_group", joinColumns = #JoinColumn(name = "lesson_id"), inverseJoinColumns = #JoinColumn(name = "group_id"))
private Set<Group> groups = new HashSet<>();
}
#Entity
#Table(name = "groups")
public class Group implements ModelEntity {
#Id
#Column(name = "group_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(name = "group_name")
private String name;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "faculty_id")
private Faculty faculty;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "group")
private List<Student> students;
}
#Entity
#Table
public class TimeSlot implements ModelEntity {
#Id
#Column(name = "time_slot_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(name = "time_slot_number")
private Integer number;
#Column(name = "time_slot_name")
private String name;
#Column(name = "time_slot_start")
private LocalTime startTime;
#Column(name = "time_slot_end")
private LocalTime endTime;
}
I wrote method, that find all Groups_id by Date and TimeSlot_id not connected to Lesson with CriteriaBuilder API, it works perfect:
#Override
public Set<Integer> getBusyGroupsId(int lessonId, LocalDate date, int timeSlotId) {
logger.debug("getBusyGroupsId() with agruments {}, {}, {}.", lessonId, date, timeSlotId);
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Integer> query = criteriaBuilder.createQuery(Integer.class);
Root<Lesson> root = query.from(Lesson.class);
List<Predicate> predicates = new ArrayList<>();
Join<Lesson, TimeSlot> timeSlotJoin = root.join("timeSlot", JoinType.LEFT);
predicates.add(criteriaBuilder.equal(timeSlotJoin.get("id"), timeSlotId));
predicates.add(criteriaBuilder.equal(root.get("date"), date));
if (nonNull(lessonId)) {
predicates.add(criteriaBuilder.notEqual(root.get("id"), lessonId));
}
query.where(predicates.toArray(new Predicate[] {}));
SetJoin<Lesson, Group> joinGroup = root.joinSet("groups");
query.multiselect(joinGroup.get("id"));
TypedQuery<Integer> result = entityManager.createQuery(query);
return result.getResultStream().collect(Collectors.toSet());
}
But after that I think- what about JPA, can it be easier?
I tried something like that, but it doesnt work:
public Set<Integer> findGroupIdByIdNotAndDateEqualsAndTimeSlotIdEquals(Integer lessonId, LocalDate date, Integer timeSlotId);
How to fix it?
Also I stacked with writing method with JPA that should find all Lesson by Group_id and Date(or startDate-endDate) and sort it: first by date, second- by TimeSlot_number.
Can it be written with JPA?
Thanks in advance.
Don't throw stones, I'm just getting to know Spring JPA.

Hibernate One to many mapping override

I am facing a hibernate problem in updainting the join table in one to many mapping with hibernate. Below are my two entity class and join table entity class.
ArticleCategoryMap.java
#Entity
#Table(name = "ARTICLECATEGORYMAP")
public class ArticleCategoryMap {
private static final long serialVersionUID = -5653708523600543988L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
#Column ( name = "id")
Long id;
#ManyToOne(targetEntity = Article.class, fetch = FetchType.EAGER, optional = true, cascade = CascadeType.PERSIST)
#JoinColumn(name = "ARTICLE_ID", nullable = true, insertable = true, updatable = true)
private Article article;
#ManyToOne(targetEntity = Category.class, fetch = FetchType.EAGER, optional = true, cascade = CascadeType.PERSIST)
#JoinColumn(name = "CATEGORY_ID", nullable = true, insertable = true, updatable = true)
private Category category;
//setter and getter
}
Article.java
#Entity
#Table(name = "ARTICLE")
public class Article {
private long id;
private String title;
private String description;
private String keywords;
private String content;
#Id
#GeneratedValue
#Column(name = "ARTICLE_ID")
public long getId() {
return id;
}
//setter and getter
}
Category.java
#Entity
#Table(name = "CATEGORY")
public class Category {
private long id;
private String name;
#OneToMany(cascade = CascadeType.ALL, fetch=FetchType.EAGER)
#JoinTable(
name = "ARTICLECATEGORYMAP",
joinColumns = #JoinColumn(name = "CATEGORY_ID"),
inverseJoinColumns = #JoinColumn(name = "ARTICLE_ID")
)
#CollectionId(
columns = #Column(name="id"),
type=#Type(type="long"),
generator = "sequence"
)
private Collection<Article> articles;
#Id
#GeneratedValue
#Column(name = "CATEGORY_ID")
public long getId() {
return id;
}
#OneToMany(cascade = CascadeType.ALL, fetch=FetchType.EAGER)
#JoinTable(
name = "ARTICLECATEGORYMAP",
joinColumns = #JoinColumn(name = "CATEGORY_ID"),
inverseJoinColumns = #JoinColumn(name = "ARTICLE_ID")
)
#CollectionId(
columns = #Column(name="id"),
type=#Type(type="long"),
generator = "sequence"
)
// setter an getter
}
Now suppose first time I have 2 elements in article table which is mapping to one entry of the category table. so the join table will look something like
Now due to some reason, I want to update the entry where the article entry will map to a new category ID. So the final DB should look like
So My problem Is how can I update this join table.
If you want one to many relationship (1 category have many articles and 1 article to 1 category) you dont need a join table.
The entity classes should look like that:
Category Entity:
Contains a Set of articles:
#Entity
#Table(name = "CATEGORY")
public class Category {
private long id;
private String name;
#OneToMany(mappedBy="category")
private Set<Article> articles;
......
}
Article Entity:
#Entity
#Table(name = "ARTICLE")
public class Article {
#ManyToOne
#JoinColumn(name="id", nullable=false)
private Category category;
private long id;
private String title;
private String description;
private String keywords;
private String content;
.......
}
For more details take a look at hibernate-one-to-many. Hope this helps.
Also move annotation from methods to fields. This:
private long id;
#Id
#GeneratedValue
#Column(name = "CATEGORY_ID")
public long getId() {
return id;
}
Should be:
#Id
#GeneratedValue
#Column(name = "CATEGORY_ID")
private long id;
public long getId() {
return id;
}
Many to many relationship:
At your database you have 3 tables:
CATEGORY
ARTICLE
ARTICLECATEGORYMAP (join table)
For many to many relationship entities would be:
Category Entity:
#Entity
#Table(name = "CATEGORY")
public class Category {
#Id
#GeneratedValue
#Column(name = "CATEGORY_ID")
private long id;
private String name;
#ManyToMany(cascade = { CascadeType.ALL })
#JoinTable(
name = "ARTICLECATEGORYMAP",
joinColumns = { #JoinColumn(name = "CATEGORY_ID") },
inverseJoinColumns = { #JoinColumn(name = "ARTICLE_ID") }
)
Set<Article > articles = new HashSet<>();
.....
}
Article Entity:
#Entity
#Table(name = "ARTICLE")
public class Article {
#Id
#GeneratedValue
#Column(name = "ARTICLE_ID")
private long id;
private String title;
private String description;
private String keywords;
private String content;
#ManyToMany(mappedBy = "articles")
private Set<Category> categories = new HashSet<>();
.......
}
For more info take a look at many-to-many ralationship

Hibernate is not persisting nested relationship

I have 4 entities: Play, Actor, Play-representation and Category.
Each play belongs to a category and play-representation associates a play with a theater and a number of actors at a given time.
Here are the entities:
#Entity
#Table(name = "category")
public class Category {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Column(name = "name")
private String name;
#OneToMany(mappedBy="category")
private List<Play> playList = new ArrayList<Play>();
#Entity
#Table(name = "actor")
public class Actor {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private long id;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "description")
private String description;
#Column(name = "profile_picture")
private String profilePicturePath;
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinTable(name = "play_representation_category",
joinColumns = {#JoinColumn(name = "actor_id")},
inverseJoinColumns = {#JoinColumn(name = "play_representation_id")})
private Set<PlayRepresentation> playRepresentations = new HashSet<>(0);
#Entity
#Table(name = "play")
public class Play {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#NotNull
#Column(name = "name")
private String name;
#NotNull
#Column(name = "description")
private String description;
#Column(name = "image_paths")
private String imagePaths;
#NotNull
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Category category;
#Entity
#Table(name = "play_representation")
public class PlayRepresentation {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "play_id")
private Play play;
#OneToOne
#JoinColumn(name = "theater_id")
private Theater theater;
#Column(name = "date")
private Timestamp airingDate;
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinTable(name = "play_representation_category",
joinColumns = {#JoinColumn(name = "play_representation_id", nullable=false)},
inverseJoinColumns = {#JoinColumn(name = "actor_id", nullable=false)})
private Set<Actor> actors = new HashSet<>(0);
The issue I'm having is that hibernate is trying to find a relationship between play_representation and category! I've been trying to persist the relationship for the plays but it seems I got that wrong and can't figure out the best way to do it...It's a postgresql db by the way.
I am still learning, so if you have any other tips regarding the code I've shared, please let me know!
Edit: error is:
org.postgresql.util.PSQLException: ERROR: relation "play_representation_category" does not exist
Position: 281
I didn't need a mappedBy, it was actually a typo - I wrote play_representation_category instead of play_representation_actors. Pretty stupid, huh? At least I finally found it :)

Categories

Resources