Org.hibernate.ObjectNotFoundException: не существует строки с указанным идентификатором, но она
У меня проблема спящего режима, которую я не могу исправить.
Настройка: 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, поэтому я, вероятно, ошибаюсь. Пожалуйста помоги! Я googled и googled безрезультатно.
Вот моя конфигурация 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;
}
Ответы
Ответ 1
Проверьте все ваши сопоставления и настройки базы данных. Возможно, вы устанавливаете значение не-null = "true" в отношении внешних ключей, когда в базе данных указано значение nullable = "true". Первый вызывает INNER JOIN, а второй вызывает LEFT JOIN.
Установите уровень журнала в TRACE, чтобы увидеть все шаги и искать сгенерированный SQL при извлечении объектов.
Ответ 2
Это происходит потому, что вы вставили что-то, что предназначено для внешнего ключа, но ничего не ссылается.
Проверьте свою базу данных, существует ли этот ключ или нет (даже если он находится в базе данных в других таблицах).
Ответ 3
Просто проверьте свою базу данных, доступен ли идентификатор 73 или нет в вашей конкретной таблице.
Ответ 4
Хорошо, я собираюсь выкинуть теорию здесь. Может быть, вы пытаетесь загрузить изображение в первый раз до совершения транзакции?
Поскольку транзакция еще не выполнена, строка не отображается для транзакции, которую вы используете для чтения изображения (зависит от того, какой уровень изоляции транзакции у вас есть).
Тогда, поскольку hib_session.close()
не находится внутри блока finally
, он не будет выполнен, и сеанс, связанный с потоком, все равно будет иметь открытую транзакцию. Следующий запрос получает тот же сеанс Hibernate, с той же открытой транзакцией, и вы получаете тот же результат от выбора, который он выдает (опять же, в зависимости от уровня изоляции транзакции - см. здесь, в частности для REPEATABLE_READ).
Это также может объяснить, почему flush()
делает его немного лучше, потому что, если flush()
встречается раньше, чем commit()
, существует меньшая вероятность возникновения условия гонки.
Я предлагаю вам попробовать закрыть сеанс в блоке finally и посмотреть, изменится ли поведение для последующих запросов.
Ответ 5
Во многих отношениях вам нужно сообщить 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"/>
Ответ 6
Я не вижу никаких реальных проблем, связанных с исключением в коде, вы можете попробовать:
- Проверка того, что транзакция сбрасывается или вызов
flush()
вручную после совершения транзакции;
- Проверка того, передан ли идентификатор в
load()
и передан ли ему правильный идентификатор через отладчик
- Включение Hibernate для печати созданного SQL и/или включения ведения журнала
Ответ 7
У меня есть аналогичная проблема с 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
Ответ 8
Пожалуйста, проверьте значение lower_case_table_names вашего сервера mysql. Если его значение равно 0, проверьте SQL, сгенерированный с помощью hibernate, убедитесь, что регистр имени таблицы соответствует фактическому имени таблицы в mysql.
Ответ 9
Я столкнулся с этой проблемой, и вот что случилось и как я решил ее. Скорее всего, у вас тоже самое происходит.
У меня были объекты 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
Наконец-то зарегистрировался третий пользователь и не стал исключением.
Как видите, внешний ключ существует в таблице записей, но, поскольку я изменил таблицу пользователей, для них не может быть совпадений, и именно поэтому я столкнулся с этой проблемой.
Чтобы избежать этой ситуации, я создал новые имена таблиц для обоих объектов и начал заново
Надеюсь, это поможет
Ответ 10
Это исключение возникает, когда Session.load() не может выбрать строку с заданным первичным ключом (значение идентификатора). Это исключение может не возникать при вызове load(), даже если в базе данных не было строк, поскольку load() возвращает прокси-сервер, если это возможно. Приложения должны использовать Session.get(), чтобы проверить, существует ли строка или конкретная запись в базе данных для определенного первичного ключа.
В этой статье мы обсуждаем hibernate org.hibernate. ObjectNotFoundException: строка с указанным идентификатором не существует.
Причина Это исключение выдается, когда вы пытаетесь загрузить сущность в режиме гибернации с помощью метода session.load(), и сущность не найдена, что означает, что экземпляр конкретной сущности не найден в текущем контексте перехода в режим гибернации.
Трассировка исключения выглядит так:
Hibernate: select employee0_.ID as ID0_0_, employee0_.NAME as NAME0_0_ from employee employee0_ where employee0_.ID=?
org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [hibernate.test.dto.EmployeeEntity#11]
at org.hibernate.impl.SessionFactoryImpl$1.handleEntityNotFound(SessionFactoryImpl.java:375)
at org.hibernate.proxy.AbstractLazyInitializer.checkTargetState(AbstractLazyInitializer.java:79)
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:68)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:111)
at org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.invoke(CGLIBLazyInitializer.java:140)
at hibernate.test.dto.EmployeeEntity$$EnhancerByCGLIB$$deac2c14.getName()
at hibernate.test.TestHibernateEhcache.main(TestHibernateEhcache.java:17)
Решение Правильный способ решить эту проблему - использовать метод session.get(). Метод Get вернет значение NULL, если для этой сущности нет записи повторно или если запись не найдена.
Employee emp = (Employee) session.get(Employee.class, new Integer(11));
//This will throw NullPointerException if entity is not found.
System.out.println(emp.getName());
Еще одно решение состоит в том, чтобы вызвать session.load() в блоке try catch и обработать исключение соответственно. Для получения более подробной информации нажмите на ссылку: https://www.quora.com/How-can-I-do-to-automatics-reset-auto-increment-values-in-MySQL-table/answer/Shadab-Kazi- 17