分离的实体传递给持久化:一对一的关系

时间:2017-10-30 07:54:54

标签: java spring spring-boot

我有这样的实体调查:

@Entity
public class SurveyData {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "SURVEY_ID")
private Long Id;

@ManyToOne
@JsonBackReference
@JoinColumn(name = "client_id")
public Client client;

@OneToOne
@JsonManagedReference
@JoinColumn(name = "surveyresult_id")
private SurveyDataResults surveyDataResults;

private Character unit;
..and other fields

另一个实体SurveyDataResults如下:

 @Entity
 @Table(name = "surveydataresults")
public class SurveyDataResults {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "SURVEYRESULT_ID")
private Long Id;
..and other fields

SurveyData从POST表单中填充,然后保存,然后用这些字段进行一些计算,然后保存在SurveyDataResult上。 当我第一次提交表单时,它会保存在SurveyData上,它保存对第一个SurveyDataResults的引用,其中id为1,其中包含所有结果。 当我第二次用值填写表单时,我得到一个错误:传递给持久化的分离实体:SurveyDataResults

我看到的问题是,如果我一个接一个地填写表单,提交的第二个表单的结果将保存在ID = 1的SurveyDataResults上。因此分离的实体问题,因为它已经保存了一次。 如何在每个表单提交之后将映射设置为相应的?

编辑:

我的帖子控制器:

@RequestMapping(value = "/user/calculate", method = RequestMethod.POST)
public ModelAndView createNewSurvey(@Valid SurveyData survey_data, BindingResult bindingResult) {

    long clientId = survey_data.client.getId();
    SurveyData newSurvey = surveyService.saveSurvey(survey_data);
    Long surveyId = newSurvey.getId();
    calculateService.CalculateFirst(surveyId);
    calculateService.CalculateSecond(surveyId);
    calculateService.CalculateThird(surveyId);
    =
    return new ModelAndView("redirect:/user/surveys?getId=" + clientId);
}

在calculateService中,我使用.save保存每个字段,如下所示: surveyServiceResults.saveSurveyResults(surveyresults);

 @Service("calculateService")
public class CalculateServiceImpl implements CalculateService {
@Autowired
private SurveyDataRepository surveyDataRepository;
SurveyDataResults surveyresults = new SurveyDataResults();
@Autowired
private SurveyServiceResults surveyServiceResults;

 public void CalculateFirst(Long id){
    SurveyData survey = surveyDataRepository.findOne(id);
    Integer c=survey.getA()+survey.getB();
    surveyResults.setC(c);
    surveyServiceResults.saveSurveyResults(surveyresults);
}
 public void CalculateSecond(Long id){
    SurveyData survey = surveyDataRepository.findOne(id);
    Integer D=survey.getB()+survey.getM();
    surveyResults.setD(D);
    surveyServiceResults.saveSurveyResults(surveyresults);
}

服务:

public interface SurveyServiceResults {

public void saveSurveyResults(SurveyDataResults surveyresults);

}

实现:

@Service("surveyServiceResults")

公共类SurveyServiceResultsImpl实现了SurveyServiceResults {

@Autowired
private SurveyDataResultsRepository surveyDataResultsRepository;

@Override
public void saveSurveyResults(SurveyDataResults surveyresults) {
    surveyDataResultsRepository.save(surveyresults);
}
}

存储库:

@Repository("surveyDataResults")
public interface SurveyDataResultsRepository  extends 
JpaRepository<SurveyDataResults, Long>{}

这是我得到的错误:

detached entity passed to persist: com.test.test1.model.SurveyDataResults; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.test.test1.model.SurveyDataResults

1 个答案:

答案 0 :(得分:1)

CalculateServiceImpl类中肯定存在错误,您将surveryresults声明为类成员字段。这在服务和存储库这样的类中是错误的,您应该尽量不在这些类中保存state信息。一旦服务实例化(来自Spring),surveyresults通过对CalculateXXX的所有调用都是相同的,这就是为什么你得到分离的实体错误。

SurveyDataResults surveyresults = new SurveyDataResults();

从那里删除此行,然后从SurveyDataResults方法

中加载并使用CalculateXXX

示例可以是以下内容,但是我不知道它是否会按预期工作,因为您尚未发布所有代码(例如,请参阅我的内联注释)

public void CalculateFirst(Long id){
    SurveyData survey = surveyDataRepository.findOne(id);
    Integer c=survey.getA()+survey.getB();
    SurveyDataResults  surveyResults = survey.getSurveyresults();
    if (surveyResults == null) {
        surveyResults = new SurveyDataResults();
        surveyResults.setSurvey(survey); //not present in your code but I assume it exists
    }
    surveyResults.setC(c);
    surveyServiceResults.saveSurveyResults(surveyresults);
}

<强>更新

另一点是通过SurveyDataResultsRepository保存surveyResults的方式。如果您没有通过survey中的setter方法设置SurveyDataResults,就像我上面的代码示例中那样,那么SurveyDataSurveyDataResults就没有关系。如果您在SurveyData实体中没有SurveyDataResults字段,则应将SurveyDataResults设置为SurveyData并通过调用保存SurveyData SurveyDataRepository.save而不是SurveyDataResultsRepository

e.g。

public void CalculateFirst(Long id){
    SurveyData survey = surveyDataRepository.findOne(id);
    Integer c=survey.getA()+survey.getB();
    SurveyDataResults  surveyResults = survey.getSurveyresults();
    if (surveyResults == null) {
        surveyResults = new SurveyDataResults();
        survey.setSurveyDataResults(surveyResults);
    }
    surveyResults.setC(c);
    surveyDataRepository.save(survey);
}