org.hibernate.ObjectNotFoundException:不存在具有给定标识符的行,但它确实存在

时间:2012-01-24 09:59:09

标签: java sql hibernate java-ee

我遇到了一个无法修复的休眠问题。

设置:Java EE,Web应用程序,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新手,所以我可能错了。请帮忙!我用Google搜索并用Google搜索无效。

这是我的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>

如果您需要更多信息,请告诉我,我很乐意帮忙。

(注意:这不是这个问题的重复,情景不一样"No row with the given identifier exists" although it DOES exist

编辑:根据要求发布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;
    }

12 个答案:

答案 0 :(得分:16)

检查所有映射和数据库设置。当您的数据库显示nullable =“true”时,您可能在外键关系中设置了一些not-null =“true”。第一个引起INNER JOIN,第二个引起LEFT JOIN。

将日志级别设置为TRACE以查看所有步骤,并在检索对象时查找生成的SQL。

答案 1 :(得分:15)

这是因为您插入了一些外键但不引用任何内容。 检查数据库是否存在该密钥(即使它存在于其他表中的数据库中)。

答案 2 :(得分:5)

只需检查您的数据库是否在您的特定表格中提供了ID 73

答案 3 :(得分:3)

在多对一关系中,如果找不到映射的行,您需要告诉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"/>

答案 4 :(得分:2)

好的,我要在这里抛出一个理论。可能是你在提交交易之前第一次尝试加载图片吗?

由于事务尚未提交,因此用于读取图片的事务对该行不可见(取决于您具有的事务隔离级别)。

然后,由于hib_session.close()不在finally块内,因此不会执行,并且线程绑定会话仍将具有打开的事务。后续请求获得相同 Hibernate会话,具有相同的打开事务,并且您从select it问题中获得相同的结果(再次,取决于事务隔离级别 - 请参阅documentation here,in特别是REPEATABLE_READ)。

这也可以解释为什么flush()会稍微好一点,因为如果flush()早于commit(),则竞争条件发生的可能性就会更小。

我建议你尝试在finally块中关闭会话,看看后续请求的行为是否发生了变化。

答案 5 :(得分:0)

我没有看到任何与代码中的异常有关的实际问题,您可能想尝试:

  • 检查事务是否已刷新或在提交后手动调用flush();
  • 检查ID是否传递给load()以及是否通过调试器传递了正确的ID
  • 启用Hibernate以打印生成的SQL和/或启用日志记录

答案 6 :(得分:0)

我对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;

然后我检索一个List,如果有至少一个,请查看FamiliaresBaja。

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

这必须是Hibernate错误

答案 7 :(得分:0)

请检查mysql服务器的lower_case_table_names的值。如果它的值为0,检查hibernate生成的SQL,确保表名的大小写与mysql中的实际表名一致。

答案 8 :(得分:0)

我面对这个问题,这里发生了什么以及我如何解决它。你很可能也有同样的事情发生。

我有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表(id为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

这告诉我,新用户表中没有id为2的用户对象。

然后我再注册了一个id为2的用户,后来我得到了这个

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

这次找不到ID为3的用户

最后注册了第三个用户并且没有例外。

正如您所看到的,外键存在于post表中,但由于我更改了用户表,因此无法与它们匹配,这就是我遇到此问题的原因。

为了避免这种情况,我为两个对象创建了新的表名并开始新的

希望这会有所帮助

答案 9 :(得分:0)

检查触发器,如果​​您有插入前触发器,并且序列中有NEXTVAL,则会导致该错误。

答案 10 :(得分:0)

您要查找的实体中可能具有一对一的关系,且具有不同的ID,请尝试将具有ID的实体(而不是标识列)加载到映射表中。

答案 11 :(得分:0)

解决此问题的正确方法是使用session.get()方法。如果找不到实体,则get方法将返回null