12

I have had a problem since Hibernate 4.1.8 resulting in the following exception:

org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [test.hibernate.TestPrepravkaOsobaSAdresou$Uvazek#2]

I have a simple OneToMany association between two entities:

@Entity(name = "Ppv")
@Table(name = "PPV")
public static class Ppv {

  @Id
  Long ppvId;

  @OneToMany(fetch = FetchType.EAGER, mappedBy = "ppv")
  Set<Uvazek> uvazeks = new HashSet<Uvazek>(0);
}


@Entity(name = "Uvazek")
@Table(name = "UVAZEK")
public static class Uvazek {

  @Id
  Long uvazekId;

  @ManyToOne
  @JoinColumn(name = "PPV_FXID")
  Ppv ppv;

}

and a test case where I have one Ppv and two Uvazek. When I load and detach a Ppv, delete one Uvazek associated with loaded Ppv and merge Ppv I get an exception.

jdbcTemplate.execute("insert into PPV values(1)");
jdbcTemplate.execute("insert into UVAZEK values(2, 1)");
jdbcTemplate.execute("insert into UVAZEK values(3, 1)");

Ppv ppv = (Ppv) getSession().get(Ppv.class, 1l);
getSession().clear();

getSession().delete(getSession().get(Uvazek.class, 2l));
getSession().flush();
getSession().merge(ppv);
getSession().flush();             //Causes the exception

During the Ppv merge, Hibernate tries to load the deleted Uvazek. Even though Uvazek is deleted, Hibernate still has information about it in

org.hibernate.collection.internal.AbstractPersistentCollection.storedSnapshot

on uvazek's set on the detached Ppv. In a previous version (<4.1.8) this works. In this simple example I can repair it by adding orphanRemoval=true on uvazeks set on Ppv and instead of deleting uvazek remove it from uvazeks set on Ppv.

So my question is: Is this a Hibernate bug or my bad practice?

Tiny
  • 27,221
  • 105
  • 339
  • 599
user3206615
  • 121
  • 1
  • 1
  • 5

3 Answers3

12

The problem is that the Uvazek with id = 2 is attempted to be merged. Hibernate sees that it has a key, but it does not know if the object is dirty, so it's not clear if an SQL update should be made.

But because the key is 2, Hibernate knows that the object has to exist on the database, so it tries to load the object in order to compare it to the version it just received in memory, to see if the object has some pending modifications to be synchronized to the database.

But the select returns no results, so Hibernate has contradictory information: on one hand the database says the object does not exist. On the other hand, the object in memory says the object must exist with key 2. There is no way to decide which is correct, so the ObjectNotFoundException is thrown.

What happened is that before this version the code was accidentally basing itself on a bug that meanwhile got fixed, so this no longer works.

The best practice is to avoid clear and use it only if needed as a memory optimization, by clearing only objects that you know won't be modified or needed in the same session anymore, have a look at Is Session clear() considered harmful.

Community
  • 1
  • 1
Angular University
  • 42,341
  • 15
  • 74
  • 81
  • But why hibernate tries to merge Uvazek? There is no merge cascade on uvazeks collection. Is it because i try to merge Ppv and I have fetch = FetchType.EAGER on uvazeks collection? Hibernate needs to have whole entity tree to be persistent after I marge Ppv in this situation? And this is only an exapmle. I use clear() only as simulaton of client server comunication. In practise it is a little bit complicated. – user3206615 May 12 '14 at 20:04
  • a life savior. i had an empty value in my table accidentally. – Saif Jan 07 '15 at 17:13
3

You also need to remove the reference to Uvazek from Ppv. Otherwise Hibernate tries to restore the relation when you merge it back and fails, because you deleted the referenced Uvazek.

This is also why adding orphan removal works for you.

sorencito
  • 2,517
  • 20
  • 21
1

I had the same Hibernate exception.

After debugging for sometime, i realized that the issue is caused by the Orphan child records.

As many are complaining, when they search the record it exists. What i realized is that the issue is not because of the existence of the record but hibernate not finding it in the table, rather it is due to the Orphan child records.

The records which have reference to the non-existing parents!

What i did is, find the Foreign Key references corresponding to the Table linked to the Bean.

To find foreign key references in SQL developer

1.Save the below XML code into a file (fk_reference.xml)

<items>
<item type="editor" node="TableNode" vertical="true">
<title><![CDATA[FK References]]></title>
<query>
    <sql>
        <![CDATA[select a.owner,
                        a.table_name,
                        a.constraint_name,
                        a.status
                 from   all_constraints a
                 where  a.constraint_type = 'R'
                        and exists(
                           select 1
                           from   all_constraints
                           where  constraint_name=a.r_constraint_name
                                  and constraint_type in ('P', 'U')
                                  and table_name = :OBJECT_NAME
                                  and owner = :OBJECT_OWNER)
                           order by table_name, constraint_name]]>
    </sql>
</query>
</item></items>

2.Add the USER DEFINED extension to SQL Developer

To find the Orphan records in all referred tables

select * from CHILD_TABLE where FOREIGNKEY not in (select PRIMARYKEY from PARENT_TABLE);

Delete these Orphan records, Commit the changes and restart the server if required.

This solved my exception. You may try the same.

Nagaraja JB
  • 729
  • 8
  • 18