Lets say I Have two entities with a one to one relationship, a person entity and a person detail entity. Are there any advantages to using cascade when I want to save as oppose to making a separate save for each entity?
Would it be different if it was not a one to one relationship?
To get started, one difference would be, if NOT cascade, there will be multiple network calls (N+1 effect). Based on size data, there are lot of other implications you need to worry about too.
Related
I am getting data with 50 fields. How to map into two tables in jpa, in which I required only three fields and rest of fields I need to only pass to downstream?
This is for a new spring data jpa, running H2 db project. In the past, I’ve tried to map all 50 fields in one entity table. But I require only 3 essential fields from those 50 fields to process of last 5000 records from db.
#Entity
class SingleCustomer{
//ID field
// 3 fields only these fields I am using to process my data from db
//47 fields just to pass to another service without any process
}
To improve performance of my application which approach I should take?
Are there any other ways to improve application performance like split into two entities and join on one to one when needs to send another service.
As you said you can split all the fields into two entities and join on one-to-one relationShip. But you should notice that field with one-to-one relationShip is loaded eagerly by default, you should mark it as lazy-loaded to improve performance.
Using a separate entity for fields you don't need together with a #OneToOne association is one way of doing that, as #Lebecca pointed out.
However, if you'd rather keep all the properties in one entity, you could turn on Hibernate bytecode enhancement, which enables support for #Basic(fetch = LAZY). If you want, you should also be able to combine such an approach with using a #SecondaryTable to store the properties you don't usually need.
See here for more info, including info on how to fine-tune the lazy loading behavior with enhancement enabled.
I've been using JPA 2.0 for a while but, sad to admit, I haven't had enough time to learn it properly. It seems like I lack the basics of how to work with Entity Manager.
Moving one step at a time, I'd like to first ask you about maintaining relationships between mapped entities. Of course I know how to create mappings between entities, different types of available associations (OneToOne, etc.) and how databases work in general. I'm purely focused on maintaining it via Entity Manager, so please do not send me to any kind of general knowledge tutorial :-).
The questions are:
Am I right that as a programmer I'm responsible for maintaining (creating/updating/removing) relationships between instances of entities?
Do I have to always update (set to null, remove from collection, etc.) instances by hand?
Plain SQL can set entities to NULL on deleting, but it seems like JPA can't do such a simple thing. It also seems like a burden to do it manually. Is there a way to achieve that with JPA?
If I have OneToMany relationship and set to NULL the entity on the Many side of the relationship. Then I persist the changes in a Set by saving the entity on the One side. Do I then have to update the entities in the Many side and set association to NULL in each instance? Seems pure silliness for one-directional bindings!
Thanks in advance!
The main thing you need to investigate is the different options you have when mapping on entity. For example in the next piece of code the cascade all option will instruct jpa to delete the child list when the parent is deleted.
#OneToMany(fetch = FetchType.LAZY, cascade = { CascadeType.ALL }, mappedBy = "parent")
private Set<Child> events = new HashSet<Child>();
Yes. You maintain the object tree and modify it to look like what
you want.
Yes and no. If you want the entity to reference null, then yes.
For instance, if you are removing one Entity, then you should clean
up any references to it held by other entities that you are not
removing. A practical example: its good practice to let an Employee
know his/her Manager has been let go. If the Employee is going to
stay, it should either have its manager reference nulled out or set
to a different manager, before the current manager can be removed.
If the employee is going to be removed as well, then cascade remove
can cascade to all the Manager's subordinates, in which case you do
not need to clean up their references to the manager - as they are
going away too.
I don't quite understand what SQL is setting to null. Deleting
removes the row in the database, so there isn't anything to set to
null. Cleaning up a reference shouldn't be that difficult in the
object model, as JPA has a number of events to help such as
preremove preupdate etc. In the end though, the problem is with
your java objects. They are just java objects, so if you want
something done, your application will need to do it for the most
part. JPA handles building them and pushing them to the database,
not changing the state for you.
Yes and no. If you set up a bidirectional relationship, you must
maintain both sides as mentioned above. If you set the child's
parent reference to null, you should let the parent know it no
longer has a child, wouldn't you? Your parent will continue to
reference its child for as long as that Parent instance exists. So
even though the database is updated/controlled through the side that
owns a relationship, the object model will be out of synch with the
database until it is refreshed or somehow reloaded. JPA allows for
multiple levels of caching, so it all depends on your provider setup
how long that Parent instance will exist referencing a Child that no
longer exists in the database.
in my code, I have an Employee and Task entities, related with ManyToMany relation. When creating new Employee object, I can assign him to existing tasks with empToBePersisted.getTasks().add(existingTask). However, when I persist it, the relation is persisted in databse but only seen from the Employee side. The Task sees it after restarting the app. How can I make it visible immediately after persisting?
Described behaviour is normal. You need to handle both sides when working with bidirectional associations.
Bidirectional relationships between managed entities will be persisted
based on references held by the owning side of the relationship. It is
the developer’s responsibility to keep the in-memory references held
on the owning side and those held on the inverse side consistent with
each other when they change.
In this case, you will need to call existingTask.setEmployee(empToBePersisted) manually.
You can also see this answer for more details.
Following situation: Using EJB on Glassfish, I have two entity classes: A and B. They are linked by a #ManyToMany relationship so I have an additional table A_B.
Now I'd like to work on an instance of A, i.e. also change some relations to class B. More precisely, I alter values in A from time to time, later (and in a different invocation of a Bean's method from the client) I want to submit the changes.
Therefor, I thought of using an optimistic lock on A's instance. The problem is: as the #ManyToMany relationship is stored in table A_B, A's entry in the DB would not alter, the version field would not get incremented, so summarized that approach does not work for me.
Locking entities in A_B would not work either as in a #ManyToMany new rows could be inserted that affect my two classes. I'd need some kind of range-based lock to achieve that no links between my instances of A and B are altered, added or deleted. Unfortunately, I did not find a proper solution for that problem.
What would be the best way to lock entities of A including all relationships to other entities?
I'm trying to make an application that keeps an object model in sync with a database by observing all changes and then immediately persisting the objects in questions. Many of the object in the model have children in large lists or trees.
When I load an object from the database, I rely on a one-way cascading relationship to also retrieve all of its children and include them in the application.
However, it is possible to alter a field in the parent object which requires persistence and I can determine that none of the children are affected. So I would like to persist the parent, without hitting the database with all the cascaded child persists.
eg
#Entity
public class Parent {
#OneToMany(cascade=CascadeType.ALL)
public List children;
}
How can I override the cascade option when I persist a Parent object? Or should I just set it to REFRESH and make sure I never need a cascading persist?
Reading the objects from the database and persisting them rely upon two different annotations.
When you load an object, it will also get the other end of any eager (FetchType.EAGER) relationships, as defined by the fetch property on the relationship.
Depending on your JPA provider, you may have options to override this behaviour. EclipseLink, via the incredibly useful QueryHint.BATCH, certainly does.
When you persist, delete or refresh, the cascade type is what's relevant.
So, lose the cascade, keep the fetch and problem solved.
Personally I think cascade all is asking for trouble but opinions will vary.
A decent JPA provider will have a pretty sophisticated (configurable) caching scheme already. Perhaps you should be asking why you're reinventing that particular wheel?
Is it an issue of asynchronous updates purely for performance? Or is something else the reason?