Save Child Objects Automatically Using JPA Hibernate

Save child objects automatically using JPA Hibernate

I tried the above but I'm getting a database error complaining that the foreign key field in the Child table can not be NULL. Is there a way to tell JPA to automatically set this foreign key into the Child object so it can automatically save children objects?

Well, there are two things here.

First, you need to cascade the save operation (but my understanding is that you are doing this or you wouldn't get a FK constraint violation during inserts in the "child" table)

Second, you probably have a bidirectional association and I think that you're not setting "both sides of the link" correctly. You are supposed to do something like this:

Parent parent = new Parent();
...
Child c1 = new Child();
...
c1.setParent(parent);

List<Child> children = new ArrayList<Child>();
children.add(c1);
parent.setChildren(children);

session.save(parent);

A common pattern is to use link management methods:

@Entity
public class Parent {
@Id private Long id;

@OneToMany(mappedBy="parent")
private List<Child> children = new ArrayList<Child>();

...

protected void setChildren(List<Child> children) {
this.children = children;
}

public void addToChildren(Child child) {
child.setParent(this);
this.children.add(child);
}
}

And the code becomes:

Parent parent = new Parent();
...
Child c1 = new Child();
...

parent.addToChildren(c1);

session.save(parent);
References

  • Hibernate Core Reference Guide

    • 1.2.6. Working bi-directional links

Save child objects automatically after saving parent

The JPA CascadeType that you configured (DETACH,MERGE,PERSIST,REFRESH) only has cascading effect when using with Session 's evict() , merge() , persist() , refresh(). (See this)

But you are using session.save() for saving the objects .That 's why it does not any the cascading effect. Change to either one of the following should solve the problem:

(1) Change all CascadeType to ALL.

(2) Use session.persist() to insert the record:

  session.persist(insDet1);

How to save child object automatically using a parent object using Hibernate and JPA?

You are using spring form so in controller you will get your ethnicity object in model attribute.

you can go like as below :

childDTO.setNationality(user.getEthnicity().getNationality());

If you are using servlet you can get value with

childDTO.setNationality(request.getParameter("nationality"));

And in Spring controller there are other ways as well to get your jsp input:

   @Transactional
public void add(ParentDTO parentDTO) {
//your child object should have all the property set here so that all values will be automatically inserted.
parentDTO.setChild(child);
child.setParent(parentDTO);
Parent parent = mapper.map(parentDTO, Parent.class);
parentRepository.save(parent);
//Even you can set property here

}

Save child objects in order using Jpa Repository

With JPA2 you can use the annotation @OrderColumn to specify a column in your database table, which is used for the ordering. If you update your database manually, you have to add that column to your table and init it with the wanted order of the pages.

How to save parent and child in one call (Hibernate, JPA)

you have to manually set each and every ExchangeRate object with ExchangeRatesTable object, as you have ExchangeRatesTable setter method. then it will not be empty and get save in the DB as well.

Parent parent = new Parent();
Child child1 = new Child();
child1.setParent(parent);
parent.setChildren(Arrays.asList(child1));
jpa.save(parent);

in your code you can iterate ExchangeRateList and set ExchangeRatesTable obj to all elements.

What is the correct way to save Hibernate JPA child entity

As you said, you can use cascade on the OneToMany side.

If you don't want to use cascade, the other option is to:

//persist eventPersonRegister
eventPersonRegister.setEventUserRolesByPersonRegisterId(new ArrayList<>());
entityManager.persist(eventPersonRegister);

//persist eventUserRole
EventUserRole eventUserRole = new EventUserRole();
eventUserRole.setUserRole("ROLE_USER");
entityManager.persist(eventUserRole);

//set the relation between eventUserRole and eventPersonRegister
eventUserRole.setEventPersonRegisterByUserRoleLinkPersonId(eventPersonRegister);
eventPersonRegister.getEventUserRolesByPersonRegisterId().add(eventUserRole);

Spring Data Jpa OneToMany save child and parent entities at the same time?

Yes, you simply need to cascade the changes from the parent to the child:

@Entity
public class Board {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String title;

@OneToMany(mappedBy = "board", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private Set<Story> stories = new HashSet<>();
}

Now whenever you save the parent (Board), the changes will cascade to the child table. You can also use CascadeType.ALL instead of {CascadeType.PERSIST, CascadeType.MERGE} to cascade any changes, like removal (when you remove the child from the collection on the parent entity, the joining id in the child table will be removed).

How to prevent saving child object with JPA?

When I try to save school object like below it also updates my student objects but I don't want them to be updated but only jointable. Is there any way?

I think you mean that you want the association itself to be managed -- i.e. which students are associated with the school -- but not the student details. This does not make much sense, I'm afraid, for both conceptual and practical reasons.

Conceptually, the "owning" side of a one-to-many relationship is always the "many". This is a bit arbitrary (but nevertheless still true) when you manage the association via a join table, but it is important when the association is managed directly via entity attributes. Updating the association requires managing the entities on the owning side, which in this case is your Students.

As a practical matter, managing the association from the School side only would raise some difficulties. For example, what if a new Student is added to a School? That student needs to be persisted before the association can be persisted, but you want to avoid that happening. There is a similar, but lesser, problem when you move a Student from one School to a different one.

Now, you can indeed avoid cascading persistence operations from Schools to their Students, but I would expect the result of doing so to be failure to manage the association between them in conjunction with managing Schools. If that's what you want to do, then you would omit any cascade attribute from the @OneToMany annotation, or else explicitly specify an empty list of cascade types.

Note also, however, that changes to all persistent entities are saved when you commit changes to your persistence context. If you want to modify Student entities without having those changes be saved to the database, then your best alternative is probably to detach those entities, or else to make detached copies of them.

Update:

As has been clarified in comments, the essential problem is how to modify the relationship between School and Student entities when the application does not have permission to update the base table of Student, but does have sufficient permissions on the join table by which the relationship is represented. You cannot do this automatically in conjunction with persisting changes to Schools, because School is not -- and cannot be -- the owning side of the relationship.

To clarify: JPA is attempting to save your Student entities when you move them to different Schools because for its purposes, the association between a Student and his particular School is part of the state of the Student. If the Student entity is attached to the persistence context and is dirty (e.g. because it was assigned to a different School), then it will be updated when changes to the PC are committed. This has nothing in particular to do with cascading or with the state of the School, except that you modify the states of your Students indirectly by moving them to different Schools' students lists.

Since you are using a join table, you could modify your object model to represent each student / school association as an entity in its own right. That would make sense if those associations had attributes of their own, such as enrollment dates, but otherwise I wouldn't recommend it.

The alternative is to write native queries (via JPA); you'll find lots of information about that around the net, such as https://blogs.oracle.com/JPQL01/entry/native_query_in_java_persistence. This does introduce some problems, however. In particular, it invalidates the EntityManager's cache, which can produce serious problems if not dealt with. It may also be significant to you that it produces entity changes without triggering the entity lifecycle methods that would fire if you performed the update normally.

With respect to the cache, the solution is to detach the affected Student and School (both old and new) entities. You can do that selectively with EntityManager.detach(), or en masse with EntityManager.clear(). Afterward, you'll need to re-query or merge the entities you want to continue using, and that could make for some messy problems, depending on how pervasively they are used and on what assumptions other code makes about them.

As for the lifecycle methods, if you need to ensure they fire, then you have the alternative of invoking them yourself.

This article provides a few more details on what you might need to do.

How to reference children id when save parent in spring data

You can save a child record without knowing the child primary id, but make sure the result should be unique if you fetching other than the primary key column.

Employee employee = new Employee();
employee.setStaffNumber("123);

You can find an address by other columns also like below.

Address officeAddress = addressRepository.findAddressByCity(city); // Office Address
Address homeAddress = addressRepository.findAddressByCity(city); // Home Address

// Setting child objects in parent object
employee.setHomeAddress(homeAddress);
employee.setOfficeAddress(officeAddress);

And finally, save the parent object it will save employee detail with home and office address.

employeeRepository.save(employee);


Related Topics



Leave a reply



Submit