org.hibernate.ObjectNotFoundException: ни одна строка с данным идентификатором не существует, но она ДЕЛАЕТ - PullRequest
25 голосов
/ 24 января 2012

У меня проблема гибернации, которую я не могу исправить.

Настройка: Java EE, веб-приложение, Hibernate 3.2, Tomcat 6, Struts 2.

По сути, я сохраняю объект с помощью серверной логики (действие Struts), затем пытаюсь извлечь эти данные для следующей страницы и отобразить их.

Я проверяю базу данных после сохранения объекта и, конечно же, вижу строку со всеми данными.

Но когда я пытаюсь получить его, я получаю это:

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

Чтобы сделать ситуацию еще хуже, когда я перезагружаю Tomcat и пытаюсь получить доступ к тому же объекту, я не получаю сообщение об ошибке - Hibernate находит строку просто отлично.

Hibernate также сможет видеть строку, если я выполню некоторые другие операции - возможно, добавлю строку здесь и там в базу данных, даже не в той же таблице.

Из всего этого я подозреваю ошибку в Hibernate, но я новичок в Hibernate, так что я, вероятно, ошибаюсь. Пожалуйста помоги! Я гуглил и гуглил безрезультатно.

Вот мой конфиг Hibernate:

<?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>

Вот мои два файла сопоставления:

<?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>

и

<?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>

Пожалуйста, дайте мне знать, если вам нужна дополнительная информация, я с радостью вам помогу.

(примечание: это не дубликат этого вопроса, сценарий не тот же самый «Строка с указанным идентификатором не существует», хотя она существует )

РЕДАКТИРОВАТЬ : по запросу, отправив код Java:

Код для сохранения объекта

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

hib_ses.beginTransaction();

hib_ses.save(user);

hib_ses.getTransaction().commit(); 

Код для отображения данных (в данном случае изображение)

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;
    }

Ответы [ 11 ]

16 голосов
/ 27 ноября 2013

Это происходит потому, что вы вставили что-то, что должно быть внешним ключом, но ни на что не ссылаетесь. Проверьте свою базу данных, существует ли этот ключ (даже если он находится в базе данных в других таблицах).

16 голосов
/ 24 января 2012

Проверьте все ваши сопоставления и настройки базы данных.Возможно, вы задаете not-null = "true" в отношениях внешнего ключа, когда ваша база данных сообщает nullable = "true".Первое вызывает INNER JOIN, а второе вызывает LEFT JOIN.

Установите уровень журнала TRACE, чтобы увидеть все шаги и искать сгенерированный SQL при получении объектов.

5 голосов
/ 23 мая 2014

Просто проверьте свою базу данных, доступен ли идентификатор 73 в вашей конкретной таблице

3 голосов
/ 02 января 2017

Во многих отношениях к одному вам нужно сообщить Hibernate, что нужно сделать, если сопоставленная строка не найдена. Вы можете настроить его следующими способами:

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"/>
2 голосов
/ 24 января 2012

Хорошо, я собираюсь выбросить здесь теорию. Может быть, вы пытаетесь загрузить картинку в первый раз до транзакции была совершена?

Поскольку транзакция еще не зафиксирована, строка не видна для транзакции, которую вы используете для чтения рисунка (зависит от того, какой уровень изоляции транзакции у вас есть).

Тогда, поскольку hib_session.close() не находится внутри блока finally, он не будет выполнен, и в привязанном к потоку сеансе все равно будет открытая транзакция. Последующий запрос получает такой же Hibernate-сеанс с той же открытой транзакцией, и вы получаете тот же результат от выбора, который он выдает (опять же, в зависимости от уровня изоляции транзакции - см. Документацию здесь в частности для REPEATABLE_READ).

Это также может объяснить, почему flush() делает его немного лучше, потому что, если flush() наступает раньше, чем commit(), вероятность возникновения условия гонки будет меньше.

Я предлагаю вам попробовать закрыть сеанс в блоке finally и посмотреть, не изменится ли поведение для последующих запросов.

1 голос
/ 14 февраля 2018

Я столкнулся с этой проблемой, и вот что случилось и как я решил ее.Скорее всего, у вас тоже самое происходит.

У меня были объекты POST и USER.Они находятся в отношениях OneToMany (пользователь может иметь много сообщений).Делая это двунаправленным, они также находятся в отношениях ManyToOne (одно сообщение принадлежит только одному пользователю).

Класс сообщений выглядит

@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

Класс пользователя

@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

Первые имена таблиц были Post и AUTO_USER. У меня было 3 пользователя, сохраненных в таблице AUTO_USER (с идентификаторами 1, 2, 3). И 3 записи в таблицу Post 1 для каждого пользователя.(столбцы соединения или внешний ключ были 1, 2, 3)

Затем я изменил только имя таблицы только для объекта пользователя и назвал его @Table(name = "AUTO_USER2").и у меня был только один пользователь в этой таблице с идентификатором 1.

В своем коде я перебираю каждое сообщение и определяю, какое сообщение принадлежит какому-либо пользователю, и отображаю их, принадлежащие текущему вошедшему в систему пользователю.

После изменения имени таблицы записей я получил это исключение

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

, которое говорит мне, что пользовательский объект с идентификатором 2 недоступен в новой таблице пользователя.

, тогда язарегистрировал еще одного пользователя с идентификатором 2, и позже я получил это

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

На этот раз он не смог найти пользователя с идентификатором 3

Наконец-то зарегистрирован третий пользователь и не было исключений.

Как видите, внешний ключ существует в таблице записей, но поскольку я изменил таблицу пользователей, для них не может быть совпадений, и именно поэтому я столкнулся с этой проблемой.

КомуЧтобы избежать этой ситуации, я создал новые имена таблиц для обоих объектов и начал заново

Надеюсь, это поможет

0 голосов
/ 25 апреля 2019

Вы можете иметь отношение один-к-одному в объекте, который вы ищете, с другим идентификатором, попробуйте загрузить объект с идентификатором в сопоставляемой таблице, а не в столбце идентификаторов.

0 голосов
/ 04 марта 2019

Проверьте триггеры, если у вас есть триггер до вставки и наличие NEXTVAL в последовательности, вызывает эту ошибку.

0 голосов
/ 19 марта 2014

Пожалуйста, проверьте значение lower_case_table_names вашего сервера mysql. Если его значение равно 0, проверьте SQL, сгенерированный hibernate, убедитесь, что регистр имени таблицы соответствует фактическому имени таблицы в mysql.

0 голосов
/ 24 апреля 2013

У меня похожая проблема с hibernate 3.6.10, хотя я просто ищу и выбираю (если существует).

Аннотация:

@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;

, затем я получаю список ис их поиском в FamiliaresBaja, если есть хотя бы один.

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

Это должно быть ошибка Hibernate

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...