java - 无法在 Spring 中使用 JPA 保持多对一关系(改为添加新的父实体)

标签 java spring hibernate jpa

我尝试通过 SpringMVC 和 JPA 保持多对一关系。

我的观点如下:

添加词对

  <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 如下:

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

和词对实体:

@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 保留新的 Dictionary 实体,然后保留新的 WordPair 实体并将新字典附加到它.如何附加现有的字典实体,我选择了 form:select item in view? 如果我改变

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

WordPair 中的Merge 选项,它给出了

java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing:

最佳答案

我将 Spring JPA 与 Hibernate 5 结合使用,我让 Hibernate 创建表。

我有实体:

@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 存储库,请注意@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());

关于java - 无法在 Spring 中使用 JPA 保持多对一关系(改为添加新的父实体),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38759768/

相关文章:

java - 如何编写这个集成测试

java - 如何实现每个节点都是一个类的堆?

java - 安装 Ant ;明显误解了JAVA_HOME

Java-JUnit怎么办?

java - Hibernate:禁用为 C3P0 创建自动测试表

JBoss EAP 5.1.2 上的 Hibernate4 日志记录错误

java - 如何更改 NetBeans 中的方法代码格式

java - 获取名称为 DAO 类的 Bean 创建异常

java - Spring 数据 REST HATEOAS : not lazy loading

java - 在 OpenLiberty 上使用 Hibernate Envers 设置自定义修订信息