例外'このクラスのIDは、save()を呼び出す前に手動で割り当てる必要があります'は、'Assigned'の識別子生成戦略を使用していることを意味します。
割り当て済み save()が呼び出される前に、アプリケーションがオブジェクトに識別子を割り当てられるようにします。これは、要素が指定されていない場合のデフォルトの戦略です。
ストラテジーを定義しない場合、休止状態のデフォルトは「割り当て済み」です。 「割り当てられた」戦略は、休止状態がアプリケーションが独自のIDを提供することを期待していることを意味します。
OracleでシーケンスIDジェネレータを使用する場合は、次の構成で使用できます-
xmlを使用している場合-
<id name="countryId" type="java.lang.Integer">
<column name="Country_Id" />
<generator class="sequence">
<param name="sequence">Country_Id_Seq</param>
</generator>
</id>
注釈を使用している場合-
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="Country_Id_Seq")
@SequenceGenerator(name="Country_Id_Seq", sequenceName="Country_Id_Seq" )
private Integer sequence;
そして、あなたのコードはそのように見えるはずです-
Country c=new Country();
c.setCountryName(request.getParameter("txtCountryName"));
c.setCountryCode(request.getParameter("txtCountryCode"));
Zone z=(Zone) session.get(Zone.class, new BigDecimal(request.getParameter("zoneId")));
c.setZone(z);
session.save(c);
session.flush();
System.out.println(c.getCountryId());
'session.save(c)'が実行されると、hibernateはOracleに対して次のSQL呼び出しを行い、IDを取得してCountryオブジェクトに設定します。
select Country_Id_Seq.nextVal from dual;
トリガーの問題
行が挿入されたときにトリガーを使用してIDをインクリメントしているため、休止状態のシーケンスで問題が発生します。 Hibernateはシーケンスを使用してIDを生成し、データベースはトリガーを使用してIDをインクリメントしています。これにより、IDが2回インクリメントされます。
これを解決するには、3つのオプションがあります。
-
トリガーは不要なので削除してください。
-
テーブルがアプリケーションの外部で更新される可能性があるためにトリガーが必要な場合は、シーケンスからIDを生成するためのOracleTriggerのinsertstatementHIbernateの問題でIDが設定されていない場合にのみIDが生成されるようにトリガーを更新できます。
-
データがdbに保存される前に、トリガーを使用してデータにIDを設定するカスタムIDジェネレーターを作成します。次のリンクを確認してください-https://forum.hibernate.org/viewtopic.php?t=973262