1 year ago

#82716

test-img

abdul mannan

Stackoverflow error when trying to delete parent entity using hibernate

I am using hibernate to check if it can be used for all operations I want to be able to do in my application. So this is a PoC stage that I am in right now.

The following is my persistence-mappings-asset.xml file:

<hibernate-mapping>
    <class entity-name="Asset">

        <id name="id"
            type="long"
            column="ID">
            <generator class="increment"/>
        </id>

        <property name="name"
                  column="NAME"
                  type="string"/>

        <set name="assetspec"
             inverse="true"
             lazy="true"
             cascade="all,delete-orphan"
             >
            <key column="asset_id"/>
            <one-to-many entity-name="Assetspec"/>
        </set>

    </class>

    <class entity-name="Assetspec">
        <!-- uuid may be used for generator -->
        <id name="id"
            type="long"
            column="ID">
            <generator class="increment"/>
        </id>

        <property name="attributeid"
                  column="attributeid"
                  type="string"/>

        <property name="description"
                  column="description"
                  type="string"/>

        <property name="alnvalue"
                  column="alnvalue"
                  type="string"/>

        <property name="numvalue"
                  column="numvalue"
                  type="string"/>

        <many-to-one name="asset"
                     column="asset_id"
                     entity-name="Asset"
                     update="true"/>

    </class>
</hibernate-mapping>

When I delete an Asset object, I want all of its associated child entities to also be deleted. I have tried 2 ways and both of them yield a different error.

package com.layerexchange.ams.persistence;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.transform.ResultTransformer;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.*;

import javax.persistence.Query;

@SpringBootApplication
@RequiredArgsConstructor
@Slf4j
public class PersistencePocApplication implements CommandLineRunner {

    public static void main(String[] args) {
        SpringApplication.run(PersistencePocApplication.class, args);
    }

    private final SessionFactory sessionFactory;

    @Override
    public void run(String... args) throws Exception {
        Session session = sessionFactory.openSession();
        Transaction transaction = session.beginTransaction();

        // we intialise with 2 diff Asset entities and 4 diff AssetSpec entities
        Map asset1 = new HashMap<>();
        Map asset2 = new HashMap<>();
        Map asset3 = new HashMap<>();

        asset1.put("name", "asset 1");
        asset2.put("name", "asset 2");
        asset3.put("name", "asset 3");

        session.save("Asset", asset1);
        session.save("Asset", asset2);
        session.save("Asset", asset3);

        Map assetSpec1 = new HashMap<>();
        Map assetSpec2 = new HashMap<>();
        Map assetSpec3 = new HashMap<>();
        Map assetSpec4 = new HashMap<>();

        assetSpec1.put("attributeid", "a101");
        assetSpec2.put("attributeid", "a102");
        assetSpec3.put("attributeid", "a103");
        assetSpec4.put("attributeid", "a104");

        assetSpec1.put("description", "This is asset spec 1 with attribute id a101");
        assetSpec2.put("description", "This is asset spec 2 with attribute id a102");
        assetSpec3.put("description", "This is asset spec 3 with attribute id a103");
        assetSpec4.put("description", "This is asset spec 4 with attribute id a104");

        assetSpec1.put("alnvalue", "b101");
        assetSpec2.put("alnvalue", "b102");
        assetSpec3.put("alnvalue", "b103");
        assetSpec4.put("alnvalue", "b104");

        assetSpec1.put("numvalue", "1");
        assetSpec2.put("numvalue", "2");
        assetSpec3.put("numvalue", "3");
        assetSpec4.put("numvalue", "4");

        assetSpec1.put("asset", asset1);
        assetSpec2.put("asset", asset2);
        assetSpec3.put("asset", asset1);
        assetSpec4.put("asset", asset2);

        session.save("Assetspec", assetSpec1);
        session.save("Assetspec", assetSpec2);
        session.save("Assetspec", assetSpec3);
        session.save("Assetspec", assetSpec4);

        transaction.commit();
        session.close();

        // testing crud operations and how they affect the child entities
        session = sessionFactory.openSession();
        transaction = session.beginTransaction();

        // test for deleting parent, and checking if child entities of it are also
        // deleted
        // Option 1
        Long id = (long) 2;
        Map asset1item = (Map) session.get("Asset", id);
        session.delete(asset1item);
        // Option 2
        Query q = session.createQuery("delete Asset where id = 2");
        q.executeUpdate();

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

When I try Option 1, I get a java.lang.StackOverflowError: null error. I assume this is because hibernate executes the following query hundreds of times:

Hibernate: select assetspec0_.asset_id as asset_id6_1_0_, assetspec0_.id as id1_1_0_, assetspec0_.id as id1_1_1_, assetspec0_.attributeid as attribut2_1_1_, assetspec0_.description as descript3_1_1_, assetspec0_.alnvalue as alnvalue4_1_1_, assetspec0_.numvalue as numvalue5_1_1_, assetspec0_.asset_id as asset_id6_1_1_ from assetspec assetspec0_ where assetspec0_.asset_id=?

When I try Option 2, I get the following error:

Caused by: org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Referential integrity constraint violation: "FKS0VRHCNJ2NBHKWLIN7GL8COTK: PUBLIC.ASSETSPEC FOREIGN KEY(ASSET_ID) REFERENCES PUBLIC.ASSET(ID) (2)"; SQL statement:
delete from asset where id=2 [23503-200]

I know that this operation should be possible but I have no idea where I may be going wrong so any help would be greatly appreciated.

spring

spring-boot

hibernate

spring-data-jpa

nhibernate-mapping

0 Answers

Your Answer

Accepted video resources