2016-08-04 10 views
4

SpringMVCとJPAを通じて多対1の関係を維持しようとしています。JPAでSpringで多対1リレーションを永続化できません(新しい親エンティティを新しく追加)

私の見解は以下の通りです:

WordPair

<form:form modelAttribute="wordpair" action="addWordPair" method="post"> 
     <label for="semanticUnitOne">Enter word one: </label> 
     <form:input path="semanticUnitOne"/> 
     <br/> 

     <label for="semanticUnitTwo">Enter word two: </label> 
     <form:input path="semanticUnitTwo"/> 
     <br/> 

     <div class="form-group"> 
      <label for="dictionary">Dictionary</label> 
      <form:select path="dictionary" cssClass="selectpicker" items="${dictionaries}" itemLabel="name" itemValue="id"> 
       <%--<form:options items="${dictionaries}" itemValue="id" itemLabel="name"/>--%> 
      </form:select> 
     </div> 

     <input type="submit" class="btn" value="Add word pair"/> 

    </form:form> 

    <div class="control-group"> 
    </div> 
</div> 

コントローラは以下の通りです追加:辞書用

@Controller 
public class WordPairController { 

@Autowired 
WordPairService wordPairService; 

@Autowired 
DictionaryService dictionaryService; 

@RequestMapping(value = "createWordPair", method = RequestMethod.GET) 
public String createWordPair(Model model) { 

    model.addAttribute("wordpair", new WordPair()); 
    model.addAttribute("dictionaries", this.dictionaryService.findAll()); 
    return "addWordPair"; 
} 

@RequestMapping(value = "addWordPair", method = RequestMethod.POST) 
public String addWordPair(@ModelAttribute("wordpair") WordPair wordPair, BindingResult result, Dictionary dictionary) { 

    wordPair.setDictionary(dictionary); 
    wordPairService.save(wordPair); 
    return "addWordPair"; 
} 

@RequestMapping(value = "wordPairGet", method = RequestMethod.GET) 
public String wordPairGet(Model model) { 
    model.addAttribute("wordPair", wordPairService.findAllWordPairs()); 

    return "wordPairGet"; 
} 

} 

Entitiyは以下の通りです:

@Entity 
public class Dictionary { 

@Id 
@GeneratedValue 
private Long id; 

private String name; 
private String comment; 

@OneToMany(mappedBy = "dictionary", cascade = CascadeType.All, fetch=FetchType.EAGER) 
private List<WordPair> wordPairs; 

とwordpairエンティティ:

@Entity 
@Table 
public class WordPair { 

@Id 
@GeneratedValue 
private Long id; 

private String semanticUnitOne; 
private String semanticUnitTwo; 
private int rating; 

@ManyToOne(fetch = FetchType.EAGER, cascade = javax.persistence.CascadeType.All) 
private Dictionary dictionary; 

はまた、サービスやDAO、

@Repository("dictionaryDao") 
public class DictionaryDaoImpl implements DictionaryDao { 
@PersistenceContext 
private EntityManager em; 

public Dictionary save(Dictionary dictionary) { 
    em.persist(dictionary); 
    em.flush(); 

    return dictionary; 
} 


public List<Dictionary> findAllDictionaries() { 
    List<Dictionary> result = em.createQuery("SELECT d FROM Dictionary d", Dictionary.class).getResultList(); 
    return result; 
} 

}

@Repository("wordPairRepository") 
public class WordPairDaoImpl implements WordPairDao { 

@PersistenceContext 
private EntityManager em; 


public List<WordPair> findAllWordPairs() { 
    List<WordPair> result = em.createQuery("SELECT p FROM WordPair p", WordPair.class).getResultList(); 
    return result; 
} 

public WordPair save(WordPair wordPair) { 
    em.persist(wordPair); 
    em.flush(); 
    return wordPair; 
} 

がある私はWordPairとリンクDictionaryを持続しようとすると問題がありますそれに対してエンティティは、hibernateは新しい辞書エンティティを維持し、その後新しいwordPairエンティティそれに新しい辞書を添付して。どのように私はフォームで選択した既存の辞書エンティティを添付する:ビュー内の選択項目ですか? org.hibernate.TransientPropertyValueException::私はか何かをマージにWordPairで

@ManyToOne(fetch = FetchType.EAGER, cascade = javax.persistence.CascadeType.All) 

オプションを変更した場合 、それは

java.lang.IllegalStateException与えオブジェクト参照 保存されていない一時的なインスタンスを - フラッシングの前に一時インスタンスを保存します。

+0

あなたは辞書の前に辞書オブジェクトのwordPairsリストを設定しようとしましたか? – duardito

+0

実際に辞書を永続化しようとすると、すべて正常です。私は既存の辞書と単語のペアを永続させたいが、それは持続するが、新しい辞書の空の辞書のエンティティ(idのみ) – ILya

+0

すでに永続化しているエンティティを「持続」することはできない。 'merge'を使う必要があります。 – JimmyB

答えて

-1

fi最初に、wordPairsフィールドから@ManyToOneを削除することができます.Dictoryで関係を定義するだけで済みます。そして@JoinColumn(name = "dict_id")を追加して、その列が参考のためにwordPairの表にあることを伝えます。

問題を解決できない場合は、idフィールドに値があるかどうかを確認する必要があります。wordPairsのデクトリのデータを確認してください。

コードをチェックしてください:

@Entity 
public class Dictionary { 

@Id 
@GeneratedValue 
private Long id; 

private String name; 
private String comment; 

@OneToMany(mappedBy = "dictionary", cascade = CascadeType.All,  fetch=FetchType.EAGER) 
@JoinColumn(name = "dict_id")// the column name in WorPair table to refer Dictory. 
private List<WordPair> wordPairs; 
+0

@ManyToOneアノテーションを削除しようとすると、展開中に次のエラーが発生します。原因:org.hibernate.MappingException:型を判別できませんでした:com.masterwork.model.Dictionary、テーブル:WordPair、列:[org .hibernate.mapping.Column(辞書)]をクリックします。以前の記事で読んだとおり、cascadeTypeの調整には問題がありますが、何が間違っているのかを定義することはできません。 – ILya

+0

更新を確認し、 'JoinColumn'を追加して参照列を設定します。 – Mavlarn

+0

少し混乱しているので、コードで表示してください。 – ILya

2

私は、Hibernate 5で春JPAを使用しています、私はテーブルを作成休止しましょう。

私は実体があります

@Entity(name = "DICTIONARY") 
public class Dictionary { 

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

    private String name; 
    private String comment; 

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) 
    @JoinColumn(name="DICTIONARY_ID") 
    private List<WordPair> wordPairs; 

@Entity(name = "WORDPAIR") 
public class WordPair { 

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

    private String semanticUnitOne; 
    private String semanticUnitTwo; 
    private int rating; 

    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER) 
    private Dictionary dictionary; 

私はJPA Repostoriesを持っているが、@Transactionが重要

@Repository 
@Transactional 
public interface DictionaryRepository extends CrudRepository<Dictionary, Long> { 
} 

@Repository 
@Transactional 
public interface WordPairRepository extends CrudRepository<WordPair, Long> { 
} 
であることに注意作成の

表には、次のようになります。

DICTIONARY 
    ID 
    COMMENT 
    NAME 
WORDPAIR 
    ID 
    RATING 
    SEMANTICUNITONE 
    SEMANTICUNITTWO 
    DICTIONARY_ID 

次のテストは、私は両方の方向で更新を行うことができます示しています。

Dictionary dictionary = makeDictionary("comment", "dictionary 1"); 
    dictionary.setWordPairs(new ArrayList<WordPair>()); 
    dictionary.getWordPairs().add(makeWordPair("George", "Unit 3", "Unit 4", 65)); 
    dictionary.getWordPairs().add(makeWordPair("Greg", "Unit 2", "Unit 1", 25)); 

    dictionaryRepository.save(dictionary); 

    dictionary = dictionaryRepository.findOne(1l); 
    assertEquals("dictionary 1", dictionary.getName()); 

    WordPair wordPair = wordPairRepository.findOne(dictionary.getWordPairs().get(0).getId()); 
    assertEquals("dictionary 1", wordPair.getDictionary().getName()); 

    wordPair.getDictionary().setName("dictionary 2"); 
    wordPairRepository.save(wordPair); 

    wordPair = wordPairRepository.findOne(dictionary.getWordPairs().get(0).getId()); 
    assertEquals("dictionary 2", wordPair.getDictionary().getName()); 

    dictionary = dictionaryRepository.findOne(1l); 
    assertEquals("dictionary 2", dictionary.getName()); 
関連する問題