2016-11-16 2 views
6

IDと他のオブジェクトのコレクションだけを含むオブジェクトを永続化またはマージできないという問題があります。別のフィールドを追加すると、トランザクションは正常にコミットされます。また、私がID生成戦略をAUTOに変更すると、同様に動作します。コレクションとIDのみを含むエンティティを永続化する方法はありますか?

私のチームの残りの人は "AUTO"の代わりに "IDENTITY"を使用していますので、私はそれらと一貫していたいと思います。それらのエンティティは単なるID +コレクション以上のものなので、それらはうまく機能します。以下は、私が仕事をしたいものです。

@Entity 
public class Filter implements Serializable { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id; 

    @OneToMany(fetch = FetchType.EAGER, orphanRemoval = true, cascade = { CascadeType.ALL }) 
    private ArrayList<Rule> rules = new ArrayList<>(); 

    public Filter() { 

    } 

} 

にErrorMessage:基本的に

org.apache.openjpa.persistence.PersistenceException: ERROR: syntax error at or near ")" 
    Position: 25 {prepstmnt 693640431 INSERT INTO Filter() VALUES()} [code=0, state=42601] 
FailedObject: [email protected] 

、それだけでIDと参加表だからフィルターを持続またはマージしようとしたとき、それは死にますフィールドなし。

回避策

  • GenerationType.AUTOに変更GenerationType.IDENTITYを。

    -Theは唯一のconが、それは

    - これは何AUTOであるように思わ表に1

  • 変更GenerationTypeずつ増加し始め、初期起動主キーが50で周りにジャンプすることのようです拾った

  • エンティティに任意のフィールドを追加します(つまり、String test = "test")。

    - 単純にエンティティにもう1つのフィールドがあると、それが維持されます。しかし、私はこのフィールドを必要としません。コレクションがほしいだけです

  • リレーションシップを双方向にします。

    - 双方向の関係を持たせることで、テーブルは(idではなく)戻ってくるIDを持ちます。これは、Filterが別のレコードによって所有されているためにのみ機能します。

+0

JPAプロバイダが列を持たないINSERT文をサポートしていない場合、そのJPAプロバイダでBUGを発生させます。私は使用しているプロバイダ(DataNucleus)で正しいSQLを生成します。 –

+0

AUTOを使用するのは本当に答えではありません。なぜなら、AUTOはプロバイダにどのような戦略を任せているのかということで、同じ問題で終わるカバーの下でIDENTITYを使うだけです。 –

+0

投稿者から削除 – garfield

答えて

0

良い解決策は、すでに指摘したように、コードの双方向を行い、「ルール」オブジェクトへのidを設定するには、「@PrePersist」注釈を使用することでしょう。ような何か:

Rule.java

@Entity 
public class Rule implements Serializable { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id; 

    private String description; 

    @ManyToOne 
    private Filter filter; 

    // getters, setters, equals, hashcode, toString... 
} 

Filter.java

@Entity 
public class Filter implements Serializable { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id; 

    @OneToMany(fetch = FetchType.EAGER, orphanRemoval = true, cascade = { CascadeType.ALL }, mappedBy="filter") 
    private List<Rule> rules = new ArrayList<>(); 

    @PrePersist 
    public void prePersist() { 
     if (rules != null) { 
      rules.forEach(item -> item.setFilter(this)); 
     } 
    } 

    // getters, setters, equals, hashcode, toString... 
} 

FilterRepository.java

@Repository 
public interface FilterRepository extends JpaRepository<Filter, Integer> { } 

AnUnitTest.java

@RunWith(SpringRunner.class) 
@SpringBootTest 
public class AnUnitTest { 
    @Autowired 
    private FilterRepository filterRepository; 

    @After 
    public void clearDatabase() { 
     bodyPartRespository.deleteAll(); 

     filterRepository.deleteAll(); 
    } 

    @Test 
    public void testFilterRules() { 
     Rule aRule = Rule.builder() 
       .description("A") 
       .build(); 
     Rule anotherRule = Rule.builder() 
       .description("B") 
       .build(); 

     Filter filter = Filter.builder() 
       .rules(Arrays.asList(aRule, anotherRule)) 
       .build(); 

     filterRepository.saveAndFlush(filter); 

     List<Filter> all = filterRepository.findAll(); 

     all.forEach(System.out::println); 
    } 
} 

上記のコードはうまく動作します。

これがあなたの問題を解決することを願っています。

乾杯、Nikolas。

0

Iは、4つの異なる実施例を使用して、問題を実装:ちょうどID

@Entity パブリッククラスケース1は= 1Lシリアライズ{

プライベート静的最終長いserialVersionUIDのを実装

  1. @ @GeneratedValue(strategy = GenerationType.IDENTITY) プライベートLong ID。

    // ...}

  • ID + 1つの文字列

    @Entity パブリッククラスケース2は、シリアライズ{のserialVersionUID = 1L

    プライベート静的最終長いを実装します;

    @ @GeneratedValue(strategy = GenerationType.IDENTITY) プライベートLong ID。 プライベート文字列名。

    // ...}

  • ID + 1 OneToMany関連
  • 。カスケード= {CascadeType.ALL}

    > @Entity 
    > public class Case3 implements Serializable { 
    >   
    > private static final long serialVersionUID = 1L; 
    >    
    > @Id 
    > @GeneratedValue(strategy = GenerationType.IDENTITY) 
    > private Long id; 
    > @OneToMany(fetch = FetchType.EAGER, orphanRemoval = true, cascade = { CascadeType.ALL }) 
    > private ArrayList<AdminUtilisateur> users = new ArrayList<>();   
    > // ... 
    >} 
    

    bです。カスケードなし= {CascadeType.ALL}

    > @Entity 
    > public class Case4 implements Serializable { 
    >   
    > private static final long serialVersionUID = 1L; 
    >    
    > @Id 
    > @GeneratedValue(strategy = GenerationType.IDENTITY) 
    > private Long id; 
    > 
    > @OneToMany(fetch = FetchType.EAGER, orphanRemoval = true) 
    > private ArrayList<AdminUtilisateur> users = new ArrayList<>();  
    > // ... 
    >} 
    

    結果は、SQLクエリ(PostgreSQLの9.3でテスト)と微細でした。 しかしのjavax.persistenceと、私は異なる結果を持っている:

    1. ケース1:例外説明:テーブルに挿入するフィールドのリスト[DatabaseTable(CASE1)]は空です。このテーブルに少なくとも1つのマッピングを定義する必要があります( )。
    2. ケース2:正常に動作します。
    3. ケース3:ローカル例外スタック:例外[EclipseLinkの-4002](Eclipseの永続性サービス - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.DatabaseException内部 例外:org.postgresql.util。PSQLException:ERREUR:la valeur d'une 固有のルールを無効にする«rule_code_key»
    4. ケース4:例外説明:[DatabaseTable(case4)]テーブルに挿入するフィールドのリストが空です。このテーブルに少なくとも1つのマッピングを定義する必要があります( )。

    例1のエラーの解明、3 & 4簡単です。ケース3の場合

    1. 、あなたがカスケード= {CascadeType.ALL}を持っている場合ORMはフィルターを永続化する前ルールを持続しようとすると、すべてが必要に依存し、私の場合のためのルールそれもう存在している。ケース1 & 4については

    2. 、あなたはテーブルN°1とルールのID + 結合テーブル上のフィルタのIDフィルターだけのIDを保持しようとしています。 これは、フィルタにはIDがあることを意味します設計上の問題の同義語 =このテーブルに少なくとも1つのマッピングを定義する必要があります。

    関連する問題