Search code examples
javahibernatemany-to-manyhibernate-cascade

hibernate - cascading type persist for many to many relationship


I have two classes Policy and Acl. They have a ManyToMany relationship in them.

// Policy

public class PolicyEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(name = "POLICY_ID")
    private int policyId;   
    @Column(name = "POLICY_NAME")
    private String policyName;
    @ManyToMany(cascade = CascadeType.PERSIST)
    @JoinTable(name = "POLICY_ACL",joinColumns=@JoinColumn(name = "POLICY_ID"),
                                    inverseJoinColumns=@JoinColumn(name = "ACL_ID"))
    private List<AclEntity> aclList = new ArrayList<AclEntity>();
}

// Acl

public class AclEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(name = "ACL_ID")
    private int aclId;  
    @Column(name = "ACL_NAME")
    private String aclName;
    @ManyToMany(mappedBy = "aclList")
    private List<PolicyEntity> policyList = new ArrayList<PolicyEntity>();
}

Now when I use Cascade type as persist then I got the following error :

Hibernate: insert into POLICY (POLICY_NAME, POLICY_ID) values (?, ?)
Hibernate: insert into POLICY_ACL (POLICY_ID, ACL_ID) values (?, ?)
Exception in thread "main" org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: hibernate.AclEntity

Whereas when I use cascade type as all then it saves the policy entity and acl entity successfully.I am unable to understand how that is happening. Note : I am just performing the save operation.

Here is the main code :

public static void main(String[] args) {

        PolicyEntity policyEntity = new PolicyEntity();
        AclEntity aclEntity = new AclEntity();

        //policyEntity.setPolicyId(1);
        policyEntity.setPolicyName("Policy 3");
        //aclEntity.setAclId(1);
        aclEntity.setAclName("Acl 3");

        policyEntity.getAclList().add(aclEntity);

        Configuration configuration = new Configuration().configure();
        StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().
        applySettings(configuration.getProperties());
        SessionFactory sessionFactory = configuration.buildSessionFactory(builder.build());
        Session session = sessionFactory.openSession();
        session.beginTransaction();

        session.save(policyEntity);

        session.getTransaction().commit();
        session.close();
    }

Solution

  • Use session.persist() instead of session.save()

    Refer to hibernate docs for clear details:

    1) Session.persist():

    Make a transient instance persistent. This operation cascades to associated instances if the association is mapped with cascade="persist"

    2) Session.save():

    Persist the given transient instance, first assigning a generated identifier. (Or using the current value of the identifier property if the assigned generator is used.) This operation cascades to associated instances if the association is mapped with cascade="save-update"