JPA many-to-one relationship CascadeType behavior

DimaSan

I have 2 tables: User and Loan. User have 3 fields: id (PK), first_name and last_name. Loan table have field user_id that is foreign key to User table: enter image description here

The logic of my application: when I create new Loan object and set there a corresponding user it should create a new one for unique user or set a id of a user into user_id for existing user.

For that purpose my database have a unique index on first_name, last_name.

The Loan class uses User with @ManyToOne relationship:

public class Loan {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinColumn(name = "user_id")
    private User user;
... methods ...

When I add new user, everything is fine, it persists to db with new PK. But when I try to add an existing one I got and exception:

javax.servlet.ServletException: org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: The statement was aborted because it would have caused a duplicate key value in a unique or primary key constraint or unique index identified by 'FIRST_LAST_NAME' defined on 'USER'.
Error Code: 20000

Again when I put @ManyToOne(cascade = CascadeType.MERGE) I'm able only to enter existing users, as only I pass a new one that is not persisted in DB I got an exception:

javax.servlet.ServletException: org.springframework.dao.InvalidDataAccessApiUsageException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: User{id=null, firstName='a', lastName='a'}.;

@ManyToOne(cascade = CascadeType.ALL) didn't work as well.

UPDATE

the code for insertion new Loan is:

user = userService.findByName(firstName, lastName);
        if (user == null) {
            user = new User(firstName, lastName);
        }
        loan.setUser(user);
        loanService.save(loan);

findByName() and save() methods are:

private EntityManager em;    
public User findByName(String firstName, String lastName) {
            TypedQuery<User> query = em.createQuery(
                    "SELECT u FROM User u WHERE u.firstName = :firstName " +
                            "AND u.lastName = :lastName", User.class)
                    .setParameter("firstName", firstName).setParameter("lastName", lastName);
            List<User> users = query.getResultList();
            if (!users.isEmpty()) {
                return users.iterator().next();
            } else {
                return null;
            }
        }

     public void save(User user) {
            if (user.getId() == null) {
                em.persist(user);
            } else {
                em.merge(user);
            }
        }
Chris

If you call Persist on Loan a) with cascade.Persist set on the user relationship and the referenced user exists, set you will get an exception if the User instance was not read in from the same EntityManager instance/context - You are reading it through the userService and then saving the loan in the loanService, so the context would have to be container managed and within the same transaction to work.

b) If cascade.PERSIST (or cascade.ALL) is not set and the reference user is new, you will get the "new object was found" exception.

If you cannot perform the read of the user in the same EntityManager you are going to save the loan in, switching to using merge may help, as JPA should then check referenced entities and merge as appropriate. You will then need to have the cascade.MERGE option set on the relationships for the merge to be applied to the User instance.

Note that using merge is different from Persist in that what you passed in does not become managed by the context. That means after the transaction commits, the entities passed in will still not have any primary key values set. You may want to pass back the entity returned from Merge if you are going to continue to use the entities for any other operations.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

JPA one to many relationship query

From Dev

many to one relationship in spring hibernate jpa

From Dev

JPA update list of one to many relationship

From Dev

How to describe one to many relationship (JPA/HIbernate)

From Dev

Spring JPA - Inheritance in One-to-Many relationship

From Dev

Spring Data JPA Specification using CriteriaBuilder with a one to many relationship

From Dev

hql select query on one to many relationship in spring jpa

From Dev

One To Many Relationship In Firebase

From Dev

Doctrine One to Many relationship

From Dev

Seeding one to many relationship

From Dev

Themeing a one to many relationship

From Dev

One to many relationship table

From Dev

Paginate a One to Many Relationship

From Dev

Laravel: one to many relationship

From Dev

Accessing a one to many relationship

From Dev

Displaying one to many relationship

From Dev

Implementing one to many relationship

From Dev

MagicalRecord: one to many relationship

From Dev

Paginate a One to Many Relationship

From Dev

Seeding one to many relationship

From Dev

One to many relationship with NSfetchedresultscontroller

From Dev

one to many relationship in laravel

From Dev

EntityFramework - One to many relationship

From Dev

One to many relationship in springboot

From Dev

How to save multiple entity in one action related in Many to Many Relationship [Spring Boot 2, JPA, Hibernate, PostgreSQL]

From Dev

One to many + one relationship in SQLAlchemy?

From Dev

JPA criteria query in a many-to-many relationship

From Dev

JPA, NetBeans and Many to Many relationship to self

From Dev

jpa - How to create a many to many relationship with an IdClass?

Related Related

HotTag

Archive