Spring Boot : lazy fetch not working for getById() - java

In my spring application , Lazy fetch is not working which is making fetch operation from db heavy. So,
when I fetch students using getStudentByRollNo() It is fetching fields EAGERLY which are even marked as Lazy. but when I am using findBySimpleNaturalId() it is loading lazy.
My classes are
Student.class
#Entity
#Builder
#ToString
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#FieldDefaults(level = AccessLevel.PRIVATE)
class Student{
#Id
Long id;
#NaturalId
String rollNo;
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, optional = false)
#JoinColumn(name = "tutor_fk", nullable = false)
Tutor tutor;
#OneToMany(fetch = FetchType.LAZY, mappedBy = Courses.student, cascade = CascadeType.ALL)
Set<Courses> courses = new HashSet<>();
}
Courses.class
#Entity
#Getter
#Setter
#Builder
#ToString
#NoArgsConstructor
#AllArgsConstructor
#FieldDefaults(level = AccessLevel.PRIVATE)
class Courses{
Long id;
String create_date_time;
#ManyToOne
#JoinColumn(name = "student_fk")
Student student;
}
Tutor.class
#Entity
#Getter
#Setter
#Builder
#ToString
#NoArgsConstructor
#AllArgsConstructor
#FieldDefaults(level = AccessLevel.PRIVATE)
class Tutor{
Long id;
String name;
}
studentService.class
#Transactional
class studentService{
Students getStudent(String rollNo ){
return studentRepository.findOneByRollNO(rollNo);
} }
when I run my code on org.hibernate.SQL: DEBUG.
querys hit are
select course0_.id as id1_43_0_, course0_.create_date_time as create_date_time2_43_0_
from course course0_ where course0_.id=?
select tutor0_.id as id1_43_0_, tutor0_.name as name2_43_0_
from tutor tutor0_ where tutor0_.id=?
it is hitting above query as eager when these fields are marked LAZY
But when I am running getByNaturalId it is fetching lazy
#Transactional
class studentService{
Students getStudent(String rollNo){
Map<String, Object> filter = new HashMap<>();
filter.put("rollNo",rollNo);
return studentRepository.findBySimpleNaturalId(rollNo);
} }
I want to know why is it fetching eager for getByRollNo() and fetching lazy for findBySimpleNaturalId() ?

Related

Map id contained in a json to the entity field of a class

Say I have a column books in table authors that contains a list of book ids and some description in jsonb type.
I've managed to deserialize this and place it in an Author instance by defining the following classes:
#Entity
#Table(name = "authors")
#Data
#Builder
#NoArgsConstructor
#AllArgsConstructor
#TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
public class Author {
#Id
#Column(name = "id")
private Long id;
#Type(type = "jsonb")
#Column(name = "books", columnDefinition = "jsonb")
private List<TestObject> testObjectList;
}
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
public class TestObject {
#JsonProperty("book_id")
private Long id;
#JsonProperty("book_description")
private String bookDescription;
}
However, instead of the Long id field, I'd like to fetch the whole Book entity inside TestBook class. How can I achieve this? This would be easier if the book_id field was inside the Author class, but here it is nested.

How can I update an entity instead of inserting it into database using Hibernate?

For example, I have a Job entity and a worker entity.
when I add new job I want to assign workers to it but instead of adding it's users to
the database again ( and create duplicates ) I want to just update workers
( add jobs to them when I create a new job with worker list )
example :
#Entity
#Table(name = "job")
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
public class Job{
#Id
#Column(name = "id")
private Long id;
#OneToMany(mappedBy = "job", fetch = FetchType.EAGER)
private Set<Worker> workers;
}
#Entity
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#Table(name = "workers")
public class User extends DataAudit {
#Id
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "job_id", referencedColumnName = "id")
private Job job;
}
Worker worker1 = workerService.getWorkerById(1);
Job job = new Job(1,worker1)
jobRepo.save(job)
The entities should be using bidirectional OneToMany association with #JoinTable:
#Entity
#Table(name = "job")
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
public class Job{
#Id
#Column(name = "id")
private Long id;
#OneToMany(fetch=FetchType.LAZY)
#JoinTable(name="job_workers",
joinColumns={#JoinColumn(name="job_id")},
inverseJoinColumns={#JoinColumn(name="worker_id")}
)
#Cascade(org.hibernate.annotations.CascadeType.ALL)
private Set<Worker> workers;
}
////////////////////////////////////////////////////////
#Entity
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#Table(name = "workers")
public class User extends DataAudit {
#Id
private Long id;
#ManyToOne
#JoinTable(name="job_workers",
joinColumns={#JoinColumn(name="worker_id", insertable=false,updatable=false)},
inverseJoinColumns={#JoinColumn(name="job_id", insertable=false,updatable=false)})
private Job job;
}

Composite primary key table not populating in related entity

My database contains a table with a composite-primary-key such that one of the keys is a foreign key, and the other is supposed to be used to get an entity from an external service. The code looks somewhat like this:
#AllArgsConstructor
#NoArgsConstructor
#Getter
#Setter
#Embeddable
#EqualsAndHashCode
public class PrimaryKey implements Serializable {
#Column(name = "A_ID")
private Long aId;
#Column(name = "F_ID")
private Long fId;
}
#Entity
#Table(name = "JOIN_ENTITY")
#Getter
#Setter
#EqualsAndHashCode
#AllArgsConstructor
#NoArgsConstructor
public class JoinEntity {
#EmbeddedId
private PrimaryKey pk;
#MapsId("aId")
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "A_ID")
private EntityA a;
public getFId() { return pk.getFId(); }
}
#Entity
#Table(name = "ENTITY_A")
#Getter
#Setter
#EqualsAndHashCode
#AllArgsConstructor
#NoArgsConstructor
public class EntityA implements Serializable {
....
#OneToMany(mappedBy = "a", cascade = CascadeType.ALL, orphanRemoval = true)
List<JoinEntity> list = new ArrayList<>();
}
When I get a JoinEntity saved and try to get EntityA from the database the list is not being populated, but if I get some JoinEntity from the database the related EntityA is recovered correctly. What do I do to get the JoinEntity list to be recovered with the EntityA?
You need to use FetchType.EAGER on the #OneToMany association in the EntityA class:
#OneToMany(mappedBy = "a", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
List<JoinEntity> list = new ArrayList<>();
This way when you retrieve a EntityA from the database, its JoinEntitys will be automatically retrieved.
Solved the problem adding an ENTITY_F table with the id and switching to a simple ManyToMany relationship.

Infinity loop with many to many in kotlin with subtable

I have a problem with a Many to Many relation.
Here I'll paste a code
User.kt
#Entity
#Getter
#Setter
#Builder
#Inheritance(strategy = InheritanceType.JOINED)
#NoArgsConstructor
#AllArgsConstructor
#Table(name = "USER", schema = "public")
data class User(
#JsonView(Views.Base::class)
var username: String,
#JsonView(Views.UserExtended::class)
#OneToMany(mappedBy = "user", cascade = [CascadeType.ALL], orphanRemoval = true)
#JsonManagedReference
var projects: List<UserProject>? = mutableListOf()
UserProject.kt
#Entity
#Getter
#Setter
#Builder
#Inheritance(strategy = InheritanceType.JOINED)
#Table(name = "USER_PROJECT", schema = "public")
data class UserProject(
#JsonView(Views.ProjectExtended::class)
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "user_id")
val user: User?,
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "project_id")
val project: Project?,
#JsonView(Views.ProjectExtended::class)
val projectRole: String
) : BaseEntity() {}
Project.kt
#Entity
#Getter
#Setter
#Builder
#NoArgsConstructor
#Inheritance(strategy = InheritanceType.JOINED)
#Table(name = "PROJECT", schema = "public")
data class Project (
#JsonView(Views.Base::class)
val name: String?,
#OneToMany(mappedBy = "project", cascade = [CascadeType.ALL], orphanRemoval = true)
#JsonView(Views.ProjectExtended::class)
var users: List<UserProject>?
) : BaseEntity() {}
And i'm Going throught infinity loop.
What I've done is simply doing a Views to overcome a problem. But I'm also using QueryDSL on #RepositoryRestResource which give me auto predicate on url's
And the problem is, I cannot simply add a #Jsonview To RepositoryRestResource interface.
I've tried doing a Projection but it gave me the result of Infinity loop cuz the #JsonView doesnt work on Projection and interface
Does someone have a suggestion how could I overcome this problem?

Hibernate delete orphan on replacing OneToOne relationship

I have the following entity:
#Entity
#Getter
#Setter
#ToString
public class Team extends EntityBase {
......
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY,
orphanRemoval = true, optional = false)
#JoinColumn(name = "auth_id")
private TeamAuthentication auth;
......
}
so it has a TeamAuthentication table reference. The latter entity looks as follows:
#Entity
#Getter
#Setter
#ToString
public class TeamAuthentication {
#Id
#GeneratedValue
private Long id;
#Column(nullable = false)
private String accessToken;
}
What I want is that when I fetch existing Team entity from the table and replace a reference to TeamAuthentication table there for field auth, then persist this Team entity with teamRepository.save(), I want that old TeamAuthentication would be deleted from its table. At the moment it stays in the table and becomes sort of a loitering entry that won't be ever used or queried.
How can I leverage Hibernate cascade in deleting OneToOne reference on change?

Categories