When are Entities-Classes enhanced and what for? jpa, spring, hibernate, javassist - spring

I am using spring 3.0.6, jpa 2.0, hibernate 3.6.8.
My question is, in which situations is javassist used to create "proxy" for a EntityClass? And what is reason of this proxy?
I have the following Entity:
#Entity
public MyEntity{
..
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "adresseID")
private Adresse adresse;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "myEntity")
private List<Parameter> parameters;
..
}
When I load a MyEntity from db, the class of entity is something like MyEntity__$$_javassist. Why is it done? What for? I think that just regular class MyEntity can be used here .
To implement lazy loading, we can:
for #OneToMany - PersistenceBag can be used here
for #ManyToOne - here should be used "enchancedClass" like Adress_$$_javassist
So what is reason for enchancing MyEntity? Where I can read something more about it? Which book/article/blog can you recommend me?

The primary reason why entity classes are enhanced is that JPA (or Hibernate) need to track entity objects state.
In particular JPA must be aware if given entity field is "dirty" - it was modified by user, but this change is not yet reflected in database, so JPA must synchronize it with database when transaction is commited.
The other case is "loaded" state of the entity field. Any field can be assigned to be lazy loaded. When such field is about to be used, JPA must be aware that database query has to be performed to initialize value of that field.
Hibernate's default is to use runtime enhacement - the proxy is just a subclass of the entity with extra stuff added.
Some general ideas are outlined here.

Related

Spring Data findById vs Join Query performance

I have a #OneToMany relation between an Entity say Class with Student. Now for each class there can be atleast 100 students. This is how my relationship with Student is defined in Class entity
#OneToMany(mappedBy = "classDataEntity", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<StudentDataEntity> studentDataEntities;
Just to check the performance of fetching class by ID (PK) we use two methods
Optional findById(ID id); // with fetchType Eager with Students
create a new method in repository with #Query joining the two tables in classId
We are calling both methods from the same service class method , e.g
#Transactional
public ClassDataEntity fetchClassEntity(Long classId){
ClassDataEntity classDataEntityJOined = repo.fetchClassWithStudents(id);
ClassDataEntity classDataEntity = repo.findById(id);
}
My understanding is with lot of Students , the join should perform better since its less call to DB , hence less network calls. But in the above case we are seeing findById performing much better
Is it because the data with the id is already in session? Also when are Hibernate sessions created and destroyed when invoked via Crud Repositories
Yeah, it's because the data is already in the persistence context. If you remove #Transactional you should see that two queries are executed because then the persistence context would not be shared (unless you have open-session-in-view enabled in spring).

Pattern for accessing data outside of transaction

I have a Spring Boot App with Spring Data JPA with hibernate and MySQL as the data store.
I have 3 layers in my application:
API Service
Application Service
Domain Service ( with Repository)
The role of Application Service is to convert hibernate-backed POJOs to DTOs given some business logic.
POJO
SchoolClass.java
#Column
Long id;
#Column
String name;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "schoolClass")
List<Book> books;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "schoolClass")
List<Student> students;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "schoolClass")
List<Schedule> schedules;
Domain Service - My transaction boundary is at the Domain Service layer.
SchoolClassService.java
#Autowired
private SchoolClassRepository repository;
#Transactional(readOnly = true)
public SchoolClass getClassById(Long id) {
return repository.findById(id);
}
Application Service
SchoolClassAppService.java
#Autowired
private SchoolClassService domainService;
public SchoolClassDto getClassById(Long id) {
SchoolClass schoolClass = domainService.getClassById(id);
// convert POJO to DTO;
return SchoolClassDto;
}
My problem is that at times the child entities on SchoolClass are empty when I try to access them in SchoolClassAppService. Not all of them, but out of the three, two would work fine but the third one would be empty. I tried to mark the children lists to be eagerly fetched, but apparently only two collections can be eagerly fetched before Hibernate starts throwing exceptions and it also does not sound like good practice to always load all the objects. I do not get LazyInitializationException, just the list is empty.
I have tried to just call the getter on all lists in the domain service method before returning it just to load all data for the POJO but that does not seem like a clean practice.
Are there any patterns available which keep the transaction boundaries as close to the persistence layer as possible while still make it viable to process the data even after the transaction has been closed?
Not sure why your collections are sometimes empty, but maybe that just how the data is?
I created Blaze-Persistence Entity Views for exactly that use case. You essentially define DTOs for JPA entities as interfaces and apply them on a query. It supports mapping nested DTOs, collection etc., essentially everything you'd expect and on top of that, it will improve your query performance as it will generate queries fetching just the data that you actually require for the DTOs.
The entity views for your example could look like this
#EntityView(SchoolClass.class)
interface SchoolClassDto {
String getName();
List<BookDto> getBooks();
}
#EntityView(Book.class)
interface BookDto {
// Whatever data you need from Book
}
Querying could look like this
List<SchoolClassDto> dtos = entityViewManager.applySetting(
EntityViewSetting.create(SchoolClassDto.class),
criteriaBuilderFactory.create(em, SchoolClass.class)
).getResultList();
Just keep in mind that DTOs shouldn't just be copies your entities but should be designed to fit your specific use case.

Spring Hibernate - Does it support nested objects?

I recently asked this question : Spring Mongodb - Insert Nested document?
And found out that Spring-Data-MongoDB does not support such behavior - so now I need a working alternative.
Now - to avoid having you look at the code on another page, I am going to paste it here from the other question... Here are my two POJOs :
#Document
public class PersonWrapper {
#Id
private ObjectId _Id;
#DBRef
private Person leader;
#DBRef
List<Person> delegates;
// Getters and setters removed for brevity.
}
public class Person
{
#Id
private ObjectId _Id;
private String name;
// Getters and setters removed for brevity.
}
Now, what I want to be able to do here - is send up a JSON object in my POST request as follows :
{
"personWrapper":
{
"_Id":"<ID HERE (MIGHT WANT SQL TO GENERATE THIS DURING CREATE>",
"leader":{
"_Id":"<ID HERE (MIGHT WANT SQL TO GENERATE THIS DURING CREATE>",
"name":"Leader McLeaderFace"
},
delegates:[{...},{...},{...}]
}
}
At this point - I would like the SQL side of this to create the individual records needed - and then insert the PersonWrapper record, with all of the right foreign keys to the desired records, in the most efficient way possible.
To be honest, if one of you thinks I am wrong about the Spring-Data-MongoDB approach to this, I would still be interested in the answer - because it would save me the hassle of migrating my database setup. So I will still tag the spring-data-mongodb community here, too.
If I understand well you want to cascade the save of your objects ?
ex : you save a PersonWrapper with some Person in the delegates property and spring data will save PersonneWrapper in a collection and save also the list of Person in another Collection.
It is possible to do that with Spring DATA JPA if you annotate your POJO with the JPA annotation #OneToMany and setup cascade property of this annotation. See this post
However the cascade feature is not available for Spring DATA mongoDB. See documentation .First you have to save the list of Person and then you save PersonWrapper.

Update/Save data in Spring JPA

I hope someone can help me solve this problem
I am using spring and JPA to save data.
When I try to save calling my DAO, not all the data gets saved.
Consider the following structure
class User
var name
var surname
#OneToMany(mappedBy = "rule",cascade = CascadeType.PERSIST)
#Fetch(FetchMode.SUBSELECT)
set<Address> address;
#OneToMany(mappedBy = "rule",cascade = CascadeType.PERSIST)
#Fetch(FetchMode.SUBSELECT)
set<Job>job;
class Address
List<AddressList>addressList;
class Job
List<JobList>jobList;
What basically happens is that name and surname changes but if I make any change related to the address or job class, these aren't committed.
However, if I delete the user, it works,if I retrieve the user information(addresses,jobs),these are retrieved correctly.
Any advice on what could be the issue?
You're only cascading the persist operation. When you update an already persisted entity, a merge operation will be performed. So, I suggest to cascade merge operation as well: CascadeType.MERGE if you want to save the related entities on update, too.
Try cascade type all --- CascadeType.ALL.
For orphan removals you should use :
CascadeType.DELETE_ORPHAN - if you are using hibernate
orphanRemoval = true - if you are using jpa 2.0
manual removal - if none of the above apply
Have decalre your transient object #Transient ? ok BTw --
follw below steps:
declare your teansient objects as #Transient
Use cascade type all --- CascadeType.ALL.
try to flush your entitymanager by using entityManager.flush() then perform persist() or merge() operation.

Spring, JPA -- integration test of CRUD of entity which has many transitive dependencies of other entities

I have entity e.g. Product which aggregates other entities such as Category. Those entities can also aggregate other entities and so on. Now I need to test my queries to database.
For simple CRUD I would create mock of EntityManager. But what if I have more complex query which I need to test for correct functionality. Then I probably need to persist entity (or more of them) and try to retrieve/update, whatever. I would also need to persist all entities on which my Product depends.
I don't like such approach. What is the best way to test such queries?
Thanks for replies.
Update -- example
Lets assume following entity structure
This structure is maintained by JPA implementation. For example Product class would look like this
#Entity
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
#ManyToOne
private Category category;
#ManyToOne
private Entity1 something;
}
So now if I want to test any query used in DAO I need to create Product in database, but it is dependent on Category and Entity1 and there is #ManyToOne annotation so values cannot be null. So I need to persist those entities too, but they have also dependencies.
I'm considering pre-creating entities such Category, Entity1 and Entity2 before test using SQL script or dbunit (mentioned by #chalimartines) which would save large amount of code, but I don't know whether it is good solution. I would like to know some best practices for such testing.
you can use #TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true) as
#ContextConfiguration(locations={"classpath:/path/to/your/applicationContextTest.xml"})
#RunWith( SpringJUnit4ClassRunner.class)
#TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
public class YourClassTest {
#Test
public void test() {
//your crud
}
}
update
You cant set the dependecies to null in order to avoid to persist them
I don't know other way, but for persisting Product and its dependencies you can use testing framework DBunit that helps you setup database data.

Resources