39

I've got a hibernate problem that I can't fix.

The setup: Java EE, web app, Hibernate 3.2, Tomcat 6, Struts 2.

Basically, I persist an object with my server logic (a struts action), then try and pull that data out for the next page and display it.

I check the database after I save the object, and sure enough, I can see the row there with all the data.

But when I try and retrieve it I get this:

org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [msc.model.Picture#73]

To make things even muddier, when I restart Tomcat and try and access the same object, I don't get the error - Hibernate finds the row just fine.

Hibernate will also be able to see the row if I do some other operations - maybe add a row here and there to the database, not even on the same table.

From all this I suspect a Hibernate bug, but I'm a Hibernate newbie so I am probably wrong. Please help! I've googled and googled to no avail.

Here is my Hibernate config:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/msc</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">-------</property>
        <!-- JDBC connection pool (use the built-in) -->
        <property name="connection.pool_size">80</property>
        <property name="current_session_context_class">thread</property>
        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>
        <mapping resource="msc/model/Picture.hbm.xml"/>
        <mapping resource="msc/model/Comment.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

Here are my two mapping files:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
  <class name="msc.model.Picture" table="PICTURE">
    <id column="PICTURE_ID" name="id">
      <generator class="native"/>
    </id>
    <property name="story"/>
    <property name="email"/>
    <property name="category"/>
    <property name="state"/>
    <property name="ratings"/>
    <property name="views"/>
    <property name="timestamp"/>
    <property name="title"/>
    <property lazy="true" name="image" type="blob">
      <column name="IMAGE"/>
    </property>
    <property lazy="true" name="refinedImage" type="blob">
      <column name="REFINEDIMAGE"/>
    </property>
    <property lazy="true" name="thumbnail" type="blob">
      <column name="THUMBNAIL"/>
    </property>
    <bag cascade="save-update" lazy="true" name="comments" table="COMMENT">
      <key column="PICTURE"/>
      <one-to-many class="msc.model.Comment"/>
    </bag>
  </class>
</hibernate-mapping>

and

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
  <class name="msc.model.User" table="USER">
    <id column="USER_ID" name="id">
      <generator class="native"/>
    </id>
    <property name="username"/>
    <property name="email"/>
    <bag cascade="save-update" lazy="true" name="pictures" table="PICTURE">
      <key column="USER"/>
      <one-to-many class="msc.model.Picture"/>
    </bag>
    <bag cascade="save-update" lazy="true" name="comments" table="COMMENT">
      <key column="USER"/>
      <one-to-many class="msc.model.Comment"/>
    </bag>
  </class>
</hibernate-mapping>

Please let me know if you need more info, I'm happy to oblige.

(note: this is not a duplicate of this question, the scenario is not the same "No row with the given identifier exists" although it DOES exist)

EDIT: as requested, posting Java code:

Code to save object

Session hib_ses = HibernateUtil.getSessionFactory().getCurrentSession();

hib_ses.beginTransaction();

hib_ses.save(user);

hib_ses.getTransaction().commit(); 

Code to display data (an image in this case)

public class ImageAction extends ActionSupport implements ServletResponseAware, SessionAware {

    private HttpServletResponse response;
    Map session;
    private Long id;
    private int thumbnail;
    private InputStream inputStream;

    @Override
    public String execute() throws Exception {
        response.setContentType("image/jpeg");
        Session hib_session = HibernateUtil.getSessionFactory().getCurrentSession();
        hib_session.beginTransaction();

        //what is the ID now?
        Picture pic = (Picture) hib_session.load(Picture.class, getId());

        if (thumbnail == 1) {
            inputStream = (ByteArrayInputStream) pic.getThumbnail().getBinaryStream();
        } else {
            inputStream = (ByteArrayInputStream) pic.getRefinedImage().getBinaryStream();
        }

        hib_session.close();
        return SUCCESS;
    }
Community
  • 1
  • 1
nasty pasty
  • 6,584
  • 7
  • 24
  • 26

14 Answers14

28

This happens because you have inserted something which is meant to be a foreign key but do not reference anything. Check out you database whether that key exist or not(even though it is in database in other tables).

Amit Kumar
  • 2,685
  • 2
  • 37
  • 72
  • 4
    I confirm that, at least in my case, that was the problem. – borjab Jul 11 '14 at 16:05
  • 3
    This is so important to check, my database had this issue and would have stalled us if we didn't realize this issue – Uriel Arvizu Jun 27 '16 at 17:05
  • 1
    In my case it happened because I had commented session.flush(). So I was trying to keep in persistence an entity (with java generated primary key etc) that didn't really exists in database – veritas Feb 02 '21 at 04:26
  • In my case, I was using @DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING) and some of the JsonSubTypes classes were not having any attributes, and your answer was like a hint. Thankyou – Talha Akbar Mar 03 '22 at 18:46
18

Check all your mappings and database settings. It may be possible you are setting some not-null="true" in foreign key relations when your database says nullable="true". The first causes an INNER JOIN and the second causes LEFT JOIN.

Set log level to TRACE to see all steps and look for generated SQL when retrieving the objects.

Esteve Camps
  • 1,113
  • 1
  • 10
  • 20
11

In many to one relationship you need to tell Hibernate what needs to be done if the mapped row is not found. You can configure it in the following ways:

Annotation:
@NotFound(action = NotFoundAction.IGNORE)
Mapping XML:
<many-to-one name="user" column="user_id" class="com.xyz.User" cascade="save-update, evict" not-found="ignore"/>
Rakesh
  • 4,004
  • 2
  • 19
  • 31
6

Just check your database whether id 73 is available or not in your particular table

Hardik Gajjar
  • 1,024
  • 12
  • 27
  • There is no relationship exists in the picture table henceforth record of 73 is not available. possible cases are deleted manually from DB end. Manually delete the record of 73 from other tables which are mapped with the picture table and give it a try. – Ajay Takur Sep 19 '22 at 07:38
4

Okay, I am going to throw out a theory here. Could it be that you are trying to load the picture the first time before the transaction has been committed?

Since the transaction is not yet committed, the row is not visible to the transaction you are using for reading the picture (depends on what transaction isolation level you have).

Then, since hib_session.close() is not inside a finally block, it will not be executed, and the thread-bound session will still have an open transaction. The subsequent request gets the same Hibernate session, with the same open transaction, and you get the same result from the select it issues (again, dependent on transaction isolation level - see documentation here, in particular for REPEATABLE_READ).

This could also explain why flush() makes it slightly better, because if the flush() occurs earlier than the commit(), there's a smaller chance for the race condition to occur.

I suggest you try closing the session in a finally block and see if the behavior changes for subsequent requests.

waxwing
  • 18,547
  • 8
  • 66
  • 82
  • Theory seems promising, when I apply debug point in my code all working fine. This means hibernate getting time to commit the transaction (I think) !! – Not a bug Jan 25 '16 at 10:12
  • Thank you! For me that was the issue. I used entityManager.refresh(entity) within a @Transactional, so obviously it couldn't find it – Olav Kokovkin Mar 20 '22 at 19:42
2

I Faced this issue and here is What happened and How i resolved it. You most probably have the same thing going on too.

I had POST and USER objects. They are in a OneToMany relationship(A user can have many posts). Making it bidirectional they are in a ManyToOne relationship too (one post belongs to only one user).

Post class looks

@Entity
@Table(name="Post")
public class Post {

@Id
@GeneratedValue(strategy=GenerationType.TABLE)
private long postId;
private String title;
private String body;

@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name = "postUserId")
private AutoUser autoUser;
// getter and setters

User class is

@Entity
@Table(name = "AUTO_USER")
public class AutoUser implements UserDetails {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long autoUserId;

@Column(name = "USERNAME")
private String username;

@OneToMany
private List<Post> postList = new ArrayList<>();
  // getter and setters

The first table names were Post and AUTO_USER I had 3 users persisted to a AUTO_USER table(with id 1, 2, 3).. And 3 entry to the Post table 1 for each user. (the join columns or foreign key were 1, 2, 3)

Then I changed only the table name for the user object only and named it @Table(name = "AUTO_USER2"). and I had only one user in this table with id 1.

In my code I iterate over each post and identify which post belongs to which user and display them those belonging to the current logged in user.

After changing the post table name I got this exception

org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.tadtab.core.authentication.AutoUser#2

Which is telling me that the user object with id 2 is not available in the new user Table.

then I registered one more user with id 2 and later I got this

org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.tadtab.core.authentication.AutoUser#3

This time it could not find user with id 3

Finally registered a third user and had not exception.

As you can see, the foreign key exists in the post table but since I changed the user table, there could not be a match for them and that is the reason I was facing this issue.

To avoid that situation I created new table names for both objects and started fresh

Hope this will help

Tadele Ayelegn
  • 4,126
  • 1
  • 35
  • 30
0

I have a similar problem with hibernate 3.6.10, while I'm just searching and selecting (if exist).

Annotation:

@Entity
public class Familiares {
@OneToMany(mappedBy = "familiares")
private List<FamiliaresBaja> bajas;

@Entity
@Table(name = "familiares_baja")
public class FamiliaresBaja implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    @JoinColumn(name = "familiares_id")
    @ManyToOne(optional = false)
    private Familiares familiares;

then i retrieve a List and with these looking in FamiliaresBaja if there is at least one.

createQuery("from FamiliaresBaja where familiares.id="+ id).uniqueResult() // should return a single result or null not throw a Exception

This must be a Hibernate bug

FiruzzZ
  • 661
  • 1
  • 6
  • 21
0

Please check the value of lower_case_table_names of your mysql server. If its value is 0, check the SQL generated by hibernate, make sure the table name's case is consistent with the actual table name in mysql.

stinghu
  • 63
  • 4
0

Check triggers, if you have a before insert trigger, and having NEXTVAL in the sequence, cause that error.

Carlos UCR
  • 299
  • 3
  • 6
0

You may have a one-to-one relationship in the entity you are looking for with a different ID, try to load the entity with the ID in the mapped table rather then the identity column.

0

The correct way to solve this problem is to use session.get() method. Get method will return null if entity is not found.

ross
  • 2,684
  • 2
  • 13
  • 22
0
Caused by: org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.emmanuel.Entity.Classe#17]
at org.hibernate.boot.internal.StandardEntityNotFoundDelegate.handleEntityNotFound(StandardEntityNotFoundDelegate.java:28)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:216)
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:327)
at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:108)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:74)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:118)
at org.hibernate.internal.SessionImpl.fireLoadNoChecks(SessionImpl.java:1215)
at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:1080)
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:697)
at org.hibernate.type.EntityType.resolve(EntityType.java:464)
at org.hibernate.type.ManyToOneType.resolve(ManyToOneType.java:240)
at org.hibernate.engine.internal.TwoPhaseLoad$EntityResolver.lambda$static$0(TwoPhaseLoad.java:576)
at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntityEntryLoadedState(TwoPhaseLoad.java:221)
at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:155)
at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:126)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:1201)
at org.hibernate.loader.Loader.processResultSet(Loader.java:1009)
at org.hibernate.loader.Loader.doQuery(Loader.java:967)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:357)
at org.hibernate.loader.Loader.doList(Loader.java:2868)
at org.hibernate.loader.Loader.doList(Loader.java:2850)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2682)
at org.hibernate.loader.Loader.list(Loader.java:2677)
at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:109)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1906)
at org.hibernate.internal.CriteriaImpl.list(CriteriaImpl.java:370)

I had this same problem, I had previously deleted an object which was referenced in another table and when I loaded the objects I had a foreign key in the table which did not refer to anything hence this exception.

[com.emmanuel.Entity.Classe#17] specifies that the object which is referenced with id 17 in the table whose objects I want to load does not exist.

0

My issue was that the child in the relation had a FK which didn't map to the PK of the parent so I had to change the JoinColumn to include referencedColumnName

@Entity
@Table(name = "child")
class Child {
    @ManyToOne
    @JoinColumn(name = "child_id", referencedColumnName = "non_pk_parent_id")
    var iabCategory: IabCategory
}

Note that this caused another issue because of a bug in Hibernate. Here's a stackoverflow post on it: Jpa Repository got error cannot not serializable when get data from database

and the link to the Hibernate bug: https://hibernate.atlassian.net/browse/HHH-7668

This bug forced me to mark the parent Serializable

@Entity
@Table(name = "parent")
class Parent : Serializable {
    
}

The bug would cause a ClassCastException to be thrown if the parent didn't implement Serializable

Archmede
  • 1,592
  • 2
  • 20
  • 37
0

I don't see any real problems pertaining to the exception in the code, you might wanna try:

  • Checking that the transaction is flushed or calling flush() manually after committing;
  • Checking whether the ID is passed to load() and whether the right ID is passed to it via debugger
  • Enabling Hibernate to print the generated SQL and/or enabling logging
TC1
  • 1
  • 3
  • 20
  • 31
  • I tried all 3 suggestions and none of them helped, although flush() made it occur less frequently (i.e. it would sometimes work! Very strange). Any other ideas? – nasty pasty Jan 24 '12 at 13:08
  • @nastypasty Well that's weird, to say the least. Best I can think of is setting the Hibernate logging configuration up & checking the TRACE level logs, that should show you the problem & they should be readable for an INSERT that small. You're gonna need a logging backend to go with that, I'd suggest `logback`, but slf4j supports quite a bunch of others. If you tell me which one you choose I suppose I could help you set it up if you run into any problems... – TC1 Jan 24 '12 at 15:33