web-dev-qa-db-ja.com

JPA-単方向の1対多の関係の永続化がEclipseLinkで失敗する

非常に単純な一方向の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ではない制約があります(ある必要があります)。

これはバグですか、コードに問題がありますか?

24
gamliela

パラメータテーブルのservice_idフィールドの非null制約を削除してみてください。 Eclipselinkは、単方向の1:m結合列の外部キーを別のステートメントで更新するため、制約チェックを無効にするか遅延させる必要があります。双方向にすることで、fpフィールドを残りのパラメーターデータで更新できます。

14
Chris

使用する nullable = false、 オン @JoinColumn

@JoinColumn(name = "service_id", nullable = false)
31

延期可能な外部キーを使用して、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
1
jc12

Hibernateバージョン<4.0の永続性を変更すると、コードは適切に実行されます。「よくある」とは、「1対多の関係の保存/永続的な親のみで、別のタスクによる子のコレクションの保存/永続化ではない」

1
Alexander

デフォルトでは、@ JoinColumnのnullableはtrueですが、1対多の関係でデータを永続化しながら、実行時に発生するデータ違反例外を回避するために、nullableをfalseとして作成する必要があります。

0
SreeNath

私が知ったように、そのような場合、外部キーは別のステートメントに入力されます。私の例では、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, ...)を使用できます。

0
kolobok