修正できない休止状態の問題があります。
セットアップ: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の初心者なので、おそらく間違っています。助けてください!グーグルで検索してみましたが、まったく役に立ちませんでした。
これが私の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>
ここに私の2つのマッピングファイルがあります:
<?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>
さらに情報が必要な場合はお知らせください。喜んで対応させていただきます。
(注:これはこの質問の複製ではありません。シナリオは同じではありません 「指定された識別子を持つ行は存在しません」が存在しますが )
[〜#〜] edit [〜#〜]:要求に応じて、Java code:
オブジェクトを保存するコード
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;
}
これは、外部キーを意図しているものの、何も参照していないものを挿入したために発生します。そのキーが存在するかどうかをデータベースで確認します(他のテーブルのデータベースにある場合でも)。
すべてのマッピングとデータベース設定を確認してください。データベースでnullable = "true"と表示されている場合、外部キー関係にnot-null = "true"を設定している可能性があります。 1番目はINNER JOINを引き起こし、2番目はLEFT JOINを引き起こします。
ログレベルをTRACEに設定して、すべてのステップを確認し、オブジェクトを取得するときに生成されたSQLを探します。
特定のテーブルでid 73が使用可能かどうかをデータベースで確認してください
多対1の関係では、マップされた行が見つからない場合に何を行う必要があるかを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"/>
さて、ここで理論を捨てます。最初に画像をロードしようとしている可能性がありますbeforeトランザクションがコミットされましたか?
トランザクションはまだコミットされていないため、画像の読み取りに使用しているトランザクションには行が表示されません(使用しているトランザクション分離レベルによって異なります)。
次に、hib_session.close()
はfinally
ブロック内にないため、実行されず、スレッドにバインドされたセッションにはまだ開いているトランザクションがあります。後続のリクエストは、同じオープントランザクションでsame Hibernateセッションを取得し、発行するselectから同じ結果を取得します(ここでも、トランザクション分離レベルに依存します- こちらのドキュメントを参照 、特にREPEATABLE_READの場合)。
flush()
がflush()
よりも早く発生する場合、競合状態が発生する可能性が低くなるため、これはcommit()
がそれをわずかに改善する理由も説明できます。
最終ブロックでセッションを閉じて、後続のリクエストで動作が変わるかどうかを確認することをお勧めします。
私はこの問題に直面し、ここで何が起こったのか、どうやって解決したのかを説明します。あなたもおそらく同じことが起こっているでしょう。
POSTおよびUSERオブジェクト。それらはOneToMany関係にあります(ユーザーは多くの投稿を持つことができます)。双方向にすることで、ManyToOne関係にもなります(1つの投稿は1人のユーザーのみに属します) 。
ポストクラスの外観
_@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)に永続化されていました。そして、各ユーザーのPostテーブル1への3つのエントリ。 (結合列または外部キーは1、2、3でした)
次に、ユーザーオブジェクトのテーブル名のみを変更し、@Table(name = "AUTO_USER2")
という名前を付けました。このテーブルにはid 1のユーザーが1人しかいませんでした。
私のコードでは、各投稿を反復処理し、どの投稿がどのユーザーに属しているかを特定し、現在ログインしているユーザーに属する投稿を表示します。
投稿テーブル名を変更した後、この例外が発生しました
_org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.tadtab.core.authentication.AutoUser#2
_
これは、id 2のユーザーオブジェクトが新しいユーザーテーブルで使用できないことを示しています。
次に、ID 2でもう1人のユーザーを登録し、後でこれを取得しました
_org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.tadtab.core.authentication.AutoUser#3
_
今回は、ID 3のユーザーが見つかりませんでした
最後に第三のユーザーを登録し、例外はありませんでした。
ご覧のように、外部キーはpostテーブルに存在しますが、userテーブルを変更したため、それらに一致するものがなかったため、この問題に直面していました。
その状況を避けるために、私は両方のオブジェクトに新しいテーブル名を作成し、新たに始めました
これが役立つことを願って
別のIDを使用して、探しているエンティティに1対1の関係がある可能性があります。ID列ではなく、マッピングテーブルのIDでエンティティをロードしてみてください。
コードの例外に関連する実際の問題は表示されません。試してみてください。
flush()
を呼び出します。load()
に渡されるかどうか、および正しいIDがデバッガーを介して渡されるかどうかを確認する挿入前トリガーがあり、シーケンスにNEXTVALがある場合、トリガーをチェックして、そのエラーを引き起こします。
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;
リストを取得し、少なくとも1つがある場合はFamiliaresBajaを検索します。
createQuery("from FamiliaresBaja where familiares.id="+ id).uniqueResult() // should return a single result or null not throw a Exception
これはHibernateのバグでなければなりません
Mysqlサーバーのlower_case_table_namesの値を確認してください。値が0の場合、hibernateによって生成されたSQLを確認し、テーブル名の大文字と小文字がmysqlの実際のテーブル名と一致していることを確認してください。
この問題を解決する正しい方法は、session.get()
メソッドを使用することです。エンティティが見つからない場合、Getメソッドはnull
を返します。