非常に単純な一方向の1対多の関係を維持しようとしていますが、EclipseLink(2.3.1)は失敗します。
サービスクラス(親):
@Entity
@Table(name = "tbl_service2")
public class Service implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="service_id")
public long serviceID;
@Column(name="name")
public String name;
@OneToMany(cascade={CascadeType.ALL})
@JoinColumn(name="service_id", referencedColumnName="service_id")
public Set<Parameter> parameters;
}
パラメータクラス(子):
(もちろん、データベースには「service_id」の外部キーフィールドがあり、単方向の関係であるため、クラスには表されません)。
@Entity
@Table(name = "tbl_service_parameters2")
public class Parameter implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="param_id")
public long parameterID;
@Column(name="name")
public String name;
}
そして、これはエンティティの永続化のためのコードです:
Service service = new Service();
service.parameters = new HashSet<Parameter>();
service.name = "test";
Parameter param = new Parameter();
param.name = "test";
service.parameters.add(param);
em.persist(service);
em.flush();
私はこの例外を受け取ります:
Internal Exception: Java.sql.SQLException: Field 'service_id' doesn't have a default value
Error Code: 1364
Call: INSERT INTO tbl_service_parameters2 (name) VALUES (?)
bind => [test]
編集:データベースフィールドservice_id
データの性質上、nullではない制約があります(ある必要があります)。
これはバグですか、コードに問題がありますか?
パラメータテーブルのservice_idフィールドの非null制約を削除してみてください。 Eclipselinkは、単方向の1:m結合列の外部キーを別のステートメントで更新するため、制約チェックを無効にするか遅延させる必要があります。双方向にすることで、fpフィールドを残りのパラメーターデータで更新できます。
使用する nullable = false
、 オン @JoinColumn
:
@JoinColumn(name = "service_id", nullable = false)
延期可能な外部キーを使用して、Oracleで機能させることができました。
例:
ALTER TABLE my_table ADD CONSTRAINT my_constraint_name FOREIGN KEY (my_table_column) REFERENCES foreign_key_table (foreign_key_table_column) DEFERRABLE INITIALLY DEFERRED
Hibernateバージョン<4.0の永続性を変更すると、コードは適切に実行されます。「よくある」とは、「1対多の関係の保存/永続的な親のみで、別のタスクによる子のコレクションの保存/永続化ではない」
デフォルトでは、@ JoinColumnのnullableはtrueですが、1対多の関係でデータを永続化しながら、実行時に発生するデータ違反例外を回避するために、nullableをfalseとして作成する必要があります。
私が知ったように、そのような場合、外部キーは別のステートメントに入力されます。私の例では、Address
エンティティと_customer_id
_を外部キーとして使用しました。
_2014-07-08T20:51:12.752+0300|FINE: INSERT INTO ADDRESS (address_id, street, city, region) VALUES (?, ?, ?, ?)
bind => [10, foo, foo, foo]
2014-07-08T20:51:12.753+0300|FINEST: Execute query InsertObjectQuery(ua.test.customer.Address@28cef39d)
2014-07-08T20:51:12.757+0300|FINEST: Execute query DataModifyQuery(sql="UPDATE ADDRESS SET customer_id = ? WHERE (address_id = ?)")
2014-07-08T20:51:12.757+0300|FINE: UPDATE ADDRESS SET customer_id = ? WHERE (address_id = ?)
bind => [151, 10]
_
したがって、_@JoinColumn
_に_nullable=true
_を指定すると、エラーが発生します。
別の方法として、@OneToMany (..., orphanRemoval = true, ...)
を使用できます。