Search code examples
javahibernatejpajpa-2.1

JPA Entity - How to update a child entity field based on its parent field


I am currently stuck on an issue of updating a parent entity field and getting the update to cascade to all its children's fields.

Here is an example of what I am trying to accomplish:

User.java

@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(nullable = false, columnDefinition = "TINYINT(1) default false")
    private Boolean archived = Boolean.FALSE;

    @OneToMany(mappedBy = "user")
    private Set<Invoice> invoices = new HashSet<Invoice>();

    // Setters & Getters
}

Invoice.java

@Entity
public class Invoice{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(nullable = false, columnDefinition = "TINYINT(1) default false")
    private Boolean archived = Boolean.FALSE;

    @ManyToOne(mappedBy = "invoices")
    @JoinColumn(nullable = false)
    private User user;

    // Setters & Getters
}

When I update the archived value to true. I want all the invoices to also be updated to true as well.

I.E

    public Boolean archiveUserById(Integer id) {

        User user= entity_manager.find(User.class, id);

        Boolean result = false;

        if(auction != null) {
            // This should cascade to all the invoices as well and update their archived fields to true as well
            user.setArchived(true);

            try {
                entity_manager.getTransaction().begin();
                entity_manager.merge(auction);
                entity_manager.getTransaction().commit();
                result = true;
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }

I've tried using cascade = CascadeType.PERSIST and @JoinTable(....) with all the referenced columns, but they are still failing to update the fields correctly.

To clarify is there a way to update a child's field through its parents' update with a Cascade effect?

Thank-you for the help.

EDIT

To clarify my question, I am trying to add a constraint cascade effect when a field on the parent entity is updated to reflect on the child entity's same field. I am trying to avoid any logic within the Entity itself. Is there a way to do this through annotations only?

Something to the same effect as this:

ALTER TABLE `child` ADD CONSTRAINT `childs-archived-mirrors-parent`
FOREIGN KEY (`archived`, `parentId`)
REFERENCES `parent`(`archived`, `id`)
ON DELETE RESTRICT ON UPDATE CASCADE;

Solution

  • Thanks for all your help.

    I ended up finding a solution. I created a custom foreign key definition that will cascade any update on the archived field to its child entities.

    Below is how I accomplished that.

    @Entity
    public class Invoice{
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;
    
        @Column(nullable = false, columnDefinition = "TINYINT(1) default false")
        private Boolean archived = Boolean.FALSE;
    
        @ManyToOne(mappedBy = "invoices")
        @JoinColumn(nullable = false, foreignKey = @ForeignKey(foreignKeyDefinition = "FOREIGN KEY (archived, user_id) REFERENCES user(archived, id) ON DELETE RESTRICT ON UPDATE CASCADE"))
        private User user;
    
        // Setters & Getters
    }