虽然在Spring中使用JPA保持多对一的关系,但它增加了额外的不必要的父实体

时间:2016-08-04 08:43:25

标签: java spring hibernate jpa

问题是,当我尝试持久化WordPair并将Dictionary实体链接到它时,hibernate会持久保存新的Dictionary实体,然后通过附加新词典来保留新的WordPair实体。如何附加我用表单选择的现有字典实体:在视图中选择项目?如果我改变

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

选项可以合并等等,它提供了

java.lang.IllegalStateException:org.hibernate.TransientPropertyValueException:object引用未保存的瞬态实例 - 在刷新之前保存瞬态实例:

我的观点如下:

<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";
}

}

字典的实体如下:

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

2 个答案:

答案 0 :(得分:2)

在WordPair类中使用@joinColumn作为Wordpair表ID,如下面的wordpairId

@Entity
@Table
public class WordPair {

@Id
@GeneratedValue
private Long id;

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

@ManyToOne(fetch = FetchType.LAZY, cascade =javax.persistence.CascadeType.All)
@JoinColumn(name = "WordPairId")
private Dictionary dictionary;

将下面的Dictionary Class targetEntity视为WordPair.class

@Entity
public class Dictionary {

@Id
@GeneratedValue
private Long id;

private String name;
private String comment;

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

答案 1 :(得分:0)

问题实际上是控制器而不是JPA。有必要在选择(“选择”)选项的基础上获得Dictionary。只有将其添加到wordpair:

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

        Dictionary specificDictionary = dictionaryService.getById(dictId);
        wordPair.setDictionary(specificDictionary);
        wordPairService.save(wordPair);

        return "addWordPair";
    }