2016-08-04 25 views
4

Ich versuche, viele zu einer Beziehung durch SpringMVC und JPA zu bestehen.Kann nicht viele zu einer Relation in Spring mit JPA beibehalten (stattdessen neue übergeordnete Entität hinzufügen)

Meine Ansicht ist die folgende:

hinzufügen 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 ist die folgende:

@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 für Wörterbuch ist folgende:

und wordpair Einheit:

@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; 

Auch gibt es ein Service und 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; 
} 

Das Problem ist, wenn ich versuche, WordPair und Link Dictionary anhalten Entity zu ihm, hält Hibernate neue Dictionary-Entität und dann persistent neue WordPair-Entität mit dem Hinzufügen eines neuen Wörterbuchs. So hängen Sie eine vorhandene Wörterbuch-Entity an, die ich mit dem Formular ausgewählt habe: Objekt in der Ansicht auswählen? Wenn ich

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

Option in WordPair zu oder etwas Merge zu ändern, gibt es

java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: Objekt eine nicht gespeicherte transiente Instanz verweist - speichern Sie die vorübergehende Instanz vor spülen:

+0

haben Sie versucht, die WordPairs-Liste im Dictionary-Objekt vor persist Dictionary zu setzen? – duardito

+0

eigentlich, wenn ich versuche, Wörterbuch zu persistieren, ist alles in Ordnung. Ich möchte Wortpaar mit vorhandenem Wörterbuch persistieren, und es bleibt bestehen, aber mit neuem Wörterbuch leere Wörterbucheinheit (nur mit ID) – ILya

+0

Sie können eine Entität nicht persistieren, die bereits persistent ist; muss 'merge' verwenden. – JimmyB

Antwort

-1

At fi Zunächst können Sie @ManyToOne aus dem Feld wordPairs entfernen, Sie müssen nur die Beziehung in Dictionary definieren. Und fügen Sie @JoinColumn(name = "dict_id") hinzu, um die Spalte in wordPair Tabelle als Referenz zu sagen.

Wenn es Ihr Problem nicht beheben kann, sollten Sie die wordPairs Daten des Diktats überprüfen, ob das id Feld Wert hat.

Überprüfen Sie den Code:

@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

wenn ich versuche, @ManyToOne Annotation zu entfernen, habe ich den folgenden Fehler während der Bereitstellung: verursacht von: org.hibernate.MappingException: Konnte Typ für nicht bestimmen: com.masterwork.model.Dictionary, bei Tabelle: WordPair, für Spalten: [org .hibernate.mapping.Column (Wörterbuch)]. Wie ich in früheren Posts gelesen habe, stimmt etwas nicht mit den Kaskadentyp-Anpassungen, aber ich kann nicht definieren, was falsch ist. – ILya

+0

Überprüfen Sie mein Update, fügen Sie JoinColumn hinzu, um die Referenzspalte festzulegen. – Mavlarn

+0

können Sie bitte im Code anzeigen, weil ich ein wenig verwirrt bin – ILya

2

Ich bin mit Spring JPA mit Hibernate 5, ich überwintern lassen die Tabellen erstellen.

Ich habe Entitäten:

@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; 

und

@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; 

I JPA Repostories haben, beachten Sie die @Transaction ist wichtig

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

und

@Repository 
@Transactional 
public interface WordPairRepository extends CrudRepository<WordPair, Long> { 
} 

Die Tabellen erstellt wie folgt aussehen:

DICTIONARY 
    ID 
    COMMENT 
    NAME 
WORDPAIR 
    ID 
    RATING 
    SEMANTICUNITONE 
    SEMANTICUNITTWO 
    DICTIONARY_ID 

Die folgenden Tests zeigt, dass ich Updates in beide Richtungen tun.

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());