首页 > 解决方案 > 在使用子表值中的@JoinColumn 的 OneToMany 关系中更新而不是插入 saveAll() 方法?

问题描述

我已经在人和信用卡之间创建了 OneToMany 关系,一个人可以有很多信用卡,当我在信用卡表中为信用卡表中的人添加新信用卡时,当时使用 Person id 作为外键,它会更新现有的信用卡而不是新的信用卡该信用卡的条目。

我有如下关系:人员类::

package com.example.model;

import java.util.List;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "persondb")
public class Person {

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

     @Column(name = "firstname")
     private String firstName;

     @Column(name = "lastname")
     private String lastName;

     @Column(name = "money")
     private Double money;

     @OneToMany(mappedBy="person")//,cascade=CascadeType.PERSIST,fetch=FetchType.LAZY)
     private List<CreditCard> creditCard;

    public Person() {
        super();
    }

    public Person(Integer id, String firstName, String lastName, Double money, List<CreditCard> creditCard) {
        super();
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.money = money;
        this.creditCard = creditCard;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public Double getMoney() {
        return money;
    }

    public void setMoney(Double money) {
        this.money = money;
    }

    public List<CreditCard> getCreditCard() {
        return creditCard;
    }

    public void setCreditCard(List<CreditCard> creditCard) {
        this.creditCard = creditCard;
    }



}

我创建了两张表,一张是Person,另一张是CreditCard,person 是Parent 表Creditcard 是 child 表CreditCard 具有作为 person_id 的foregin key,它具有 Person 类 Primary key 的引用

信用卡类 ::

package com.example.model;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = "creditcarddb")
public class CreditCard {

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

     @Column(name = "type")
     private String type;

     @Column(name = "number")
     private String number;

     @ManyToOne(cascade = CascadeType.PERSIST,fetch=FetchType.LAZY)//(cascade = CascadeType.ALL,fetch=FetchType.LAZY)
     @JoinColumn(name="person_id", nullable=false)
     private Person person;

    public CreditCard() {
        super();
    }

    public CreditCard(Integer id, String type, String number, Person person) {
        super();
        this.id = id;
        this.type = type;
        this.number = number;
        this.person = person;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getNumber() {
        return number;
    }
    public void setNumber(String number) {
        this.number = number;
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }
}

我在这里使用休息控制器

个人控制器 ::

package com.example.controller;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import com.example.model.Person;
import com.example.service.CreditCardService;
import com.example.service.PersonService;

@RestController
//@Controller
public class PersonController {


    private static final Logger logger = LoggerFactory.getLogger(PersonController.class);

    ModelAndView models = new ModelAndView();

    @Autowired
    private PersonService personService;

    @Autowired
    private CreditCardService creditCardService;

    @RequestMapping(value = "/PersonList", method = RequestMethod.GET)
    public ModelAndView getRecords(Model model) {
        logger.debug("Received request to show records page");
        List<Person> persons = personService.getAll();

        List<Person> person = new ArrayList<Person>();
        for(Person per : persons) {
            Person p = new Person();
            p.setId(per.getId());
            p.setFirstName(per.getFirstName());
            p.setMoney(per.getMoney());
            p.setLastName(per.getLastName());
            p.setCreditCard(creditCardService.getAll(per.getId()));
            person.add(p);
        }
        return new ModelAndView("list","persons",person);
    }

    @RequestMapping(value = "/add", method = RequestMethod.GET)
    public ModelAndView getAdd(Model model) {
        logger.debug("Received request to show add page");
        models.setViewName("AddPerson");
        return models;
    }

    @RequestMapping(value = "/personEntry", method = RequestMethod.POST)
    public ModelAndView postAdd(@ModelAttribute("personAttribute") Person person) {
        logger.debug("Received request to add new record");
        personService.add(person);
        return new ModelAndView("redirect:/PersonList");
    }   

}

在 CreditCard Controller 中为当时的人添加新 CreditCard 时,我首先获取其现有卡的所有列表,然后通过使用 saveAll 方法,我将现有的以及新的 CreditCard 保存到 DB但相反保存新的信用卡它将替换现有的信用卡。 我该如何解决这个问题。

信用卡控制器 ::

package com.example.controller;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import com.example.model.CreditCard;
import com.example.model.Person;
import com.example.repository.PersonRepository;
import com.example.service.CreditCardService;

@RestController
//@Controller
@RequestMapping(("/main/creditcard"))
public class CreditCardController {

    private static final Logger logger = LoggerFactory.getLogger(CreditCardController.class);

    @Autowired
    CreditCardService creditCardService;

    @Autowired
     PersonRepository personRepository;

    ModelAndView models = new ModelAndView();

    @RequestMapping(value = "/add/{id}", method = RequestMethod.GET)
    public ModelAndView getAdd(@PathVariable(value = "id") Integer personId,Model model) {
        logger.debug("Received request to show add page");
        model.addAttribute("creditCardAttribute", new CreditCard());
        model.addAttribute("personId", personId);
        return new ModelAndView("AddCard","personId",personId);
        //return "AddCard";
    }

    //@Transactional
    @RequestMapping(value = "/addCard", method = RequestMethod.POST)
    //@PostMapping(value = "/addCard")
    public ModelAndView postAdd(@RequestParam("personId") Integer personId,@ModelAttribute("creditCardAttribute") CreditCard creditCard,BindingResult binding) { //@RequestBody  CreditCard creditCard @ModelAttribute("creditCard") CreditCard creditCard
        //@RequestParam("personId") Integer personId
        //@PathVariable(value = "id") Integer personId
        logger.debug("Received request to add new credit card");
        logger.debug("-------------------->-------------------->------------------->");
        logger.debug("Integer Value Received Is" + " " + personId);

        List<CreditCard> cc =  creditCardService.get(personId);
        List<CreditCard> list = new ArrayList<CreditCard>();
        list.addAll(cc);
        Person p = personRepository.findById(personId).get();
        logger.debug("The Value Printed in the Person Object" + " "+p.getId());

        creditCard.setPerson(p);
        cc.add(creditCard);
        list.add(creditCard);
        creditCardService.addAll(list);
        //creditCardService.add(creditCard);
        //return "Success";
        return new ModelAndView("redirect:/PersonList");
    }

}

个人服务 ::

package com.example.service;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.model.Person;
import com.example.repository.CreditCardRepository;
import com.example.repository.PersonRepository;

@Service
public class PersonService {

    @Autowired
    PersonRepository personRepository;

    @Autowired
    CreditCardRepository creditCardRepository;

    private static final Logger logger = LoggerFactory.getLogger(PersonService.class);


    public List<Person> getAll() {
        logger.debug("Retrieving all persons");
        List<Person> person = personRepository.findAll();
        return person;
    }

    public void add(Person person) {
        logger.debug("Adding new person");
        personRepository.save(person);
    }
}

信用卡服务 ::

package com.example.service;

import java.util.List;
import java.util.Set;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.example.model.CreditCard;
import com.example.repository.CreditCardRepository;
import com.example.repository.PersonRepository;

@Service
public class CreditCardService {

    private static final Logger logger = LoggerFactory.getLogger(CreditCardService.class);

    @Autowired
    CreditCardRepository creditCardRepository;

    @Autowired
    PersonRepository personRepository;

    @Autowired
    private PersonService personService;

    @Transactional
    public void add(CreditCard creditCard) {
        logger.debug("Adding new credit card");
//      String number = creditCard.getNumber();
//      String type = creditCard.getType();
//      Integer id = creditCard.getPerson().getId();
        creditCardRepository.save(creditCard);
        //creditCardRepository.insertData(number,type,id);
    }

    public List<CreditCard> getAll(Integer id) {
        List<CreditCard> credit = creditCardRepository.getAll(id);
        return credit;
    }

    public List<CreditCard> get(Integer id) {
        List<CreditCard> credit = creditCardRepository.get(id);
        return credit;
    }

    public void addAll(List<CreditCard> list) {
        // TODO Auto-generated method stub
        logger.debug("Adding new credit card With Old List");
        creditCardRepository.saveAll(list);
    }

}

信用卡存储库 ::

package com.example.repository;

import java.util.List;
import java.util.Set;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import com.example.model.CreditCard;

public interface CreditCardRepository extends JpaRepository<CreditCard,Integer>{

    @Query("SELECT v FROM Person u INNER JOIN  u.creditCard v  WHERE u.id = ?1")
     List<CreditCard>  getAll(Integer id);

//  @Query("insert into CreditCard  (number,type,person.id) VALUES (?1,?2,?3)")
//  void insertData(String number, String type, Integer id);

    @Query("SELECT c FROM CreditCard c WHERE c.person.id = ?1")
    List<CreditCard> get(Integer id);

}

我在这里使用 jsp 页面来添加人员和信用卡。

显示 Person 及其相关的信用卡。

列表.jsp

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<html>
<head>
    <title>Person Details</title>
</head>
<body>

        <h1>Person Credit Card Details</h1>
        <h2>
            <a href="add">Add New Person</a>
            &nbsp;&nbsp;&nbsp;
            <a href="PersonList">List All Person</a>
            &nbsp;&nbsp;&nbsp;
            <!--  <a href="benefits/beneficiary"></a> -->

        </h2>
    <div>
        <table>
            <tr>
                <th>PersonID</th>
                <th>FirstName</th>
                <th>LastName</th>
                <th>Money</th>
                <th>CC Type</th>
                <th>CC Number</th>
                <th colspan="1"></th>
            </tr>
         <c:forEach var="person" items="${persons}">
                <c:if test = "${!empty person.creditCard}">
                    <c:forEach items="${person.creditCard}" var = "creditCards">
                        <tr>
                            <td>${person.id}</td>
                            <td>${person.firstName}</td>
                            <td>${person.lastName}</td>
                            <td>${person.money}</td>
                            <td>${creditCards.type}</td>
                            <td>${creditCards.number}</td>
                            <!-- <c:url var="addcc" value="/main/creditcard/add?id=${person.id}" />
                            <td><a href = "${addcc}">Add Credit Card</a></td> -->
                             <td><a href="/main/creditcard/add/<c:out value='${person.id}' />">Add Credit Card</a></td> 

                        </tr>
                    </c:forEach>
                </c:if>
                <c:if test="${empty person.creditCard}">
                    <tr>
                        <td>${person.id}</td>
                        <td>${person.firstName}</td>
                        <td>${person.lastName}</td>
                        <td>${person.money}</td>
                        <td>N/A</td>
                        <td>N/A</td>
                        <td> <a href="/main/creditcard/add/<c:out value='${person.id}' />">Add Credit Card</a></td>
                        <!-- &nbsp;&nbsp;&nbsp;&nbsp; --> 
                        <!-- <td><a href="/delete/<c:out value='${employee.employeeId}' />">Delete</a> </td>  -->
                        <!-- &nbsp;&nbsp;&nbsp;&nbsp; -->
                        <!-- <td> <a href="benefits/show/<c:out value='${employee.employeeId}' />">Benefits</a> </td>   -->
                    </tr>
                </c:if>         
        </c:forEach>                     
        </table>
    </div>   
</body>
</html>

AddPerson.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
      <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> 

<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<form action="personEntry" method="post">
            <table style="with: 50%">
                <tr>
                    <td>FirstName</td>
                    <td><input type="text" name="firstName" /></td>
                </tr>
                    <tr>
                    <td>LastName</td>
                    <td><input type="text" name="lastName" /></td>
                </tr>
                <tr>
                    <td>Money</td>
                    <td><input type="text" name="money" /></td>
                </tr>
                <tr><td>
                <input type="submit" value="Submit" /></td>
                </tr>
            </table>

        </form>
</body>

</html>

AddCreditCard.jsp ::

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
      <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> 

<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<c:url var="addCcUrl" value="/main/creditcard/addCard?id=${personId}" />
<form:form action="${addCcUrl}" method="post" modelAttribute = "creditCardAttribute">
            <table style="with: 50%">
                <tr>
                    <td>PersonId</td>
                    <td><input type="text" value="${personId}" name = "personId" readonly/>
                </tr>
                    <tr>
                    <td>Card Type</td>
                    <td><form:input path="type" /></td>
                </tr>
                <tr>
                    <td>Number</td>
                    <td><form:input path="number" /></td>
                </tr>
                <tr>
                    <td>
                    <input type="submit" value="Submit" />
                    </td>
                </tr>
            </table>

        </form:form>
</body>

</html>

标签: spring-bootspring-mvcspring-data-jpa

解决方案


您是否尝试删除

(cascade = CascadeType.PERSIST,fetch=FetchType.LAZY)

CreditCard类?这就像你告诉hibernate每次持久化一张新信用卡时都要持久化一个人

只放注解

 @ManyToOne
 @JoinColumn(name="person_id", nullable=false)
 private Person person;

您可以尝试添加cascade = CascadeType.PERSISTPerson课程中吗?就这样

@OneToMany(mappedBy="person"cascade=CascadeType.PERSIST)
     private List<CreditCard> creditCard;

试试这个代码来添加一张新的信用卡

    @RequestMapping(value = "/addCard", method = RequestMethod.POST)
    public ModelAndView postAdd(@RequestParam("personId") Integer personId,@ModelAttribute("creditCardAttribute") CreditCard creditCard,BindingResult binding) { @ModelAttribute("creditCard") CreditCard creditCard

        Person p = personRepository.findById(personId).get();

        creditCard.setPerson(p);

        creditCardRepository.save(creditCard);

        return new ModelAndView("redirect:/PersonList");
    }

推荐阅读