When I issue a Postman Get request, it returns duplicate result. Even when I had only three records in my database, Postman returns hundreds of same record duplicated.
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example.resource</groupId>
<artifactId>akademiks</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>akademiks</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Entity class:
@Entity
@Table(name = "Chemistry")
public class Chemistry {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "date")
private Date date;
@Column(name = "question_no")
private Integer questionNo;
@Column(name = "question")
private String question;
@OneToOne(mappedBy = "question",cascade = CascadeType.ALL)
private ChemistryAnswer answer = new ChemistryAnswer();
public Chemistry() {}
public Chemistry(Date date, Integer questionNo, String question) {
this.date = date;
this.questionNo = questionNo;
this.question = question;
this.answer.setDate(date);
this.answer.setQuestionNo(questionNo);
this.answer.setQuestion(this);
}//accessors
Entity class:
@Entity
@Table(name = "Chemistryanswer")
public class ChemistryAnswer {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "date")
private Date date;
@Column(name = "question_no")
private Integer questionNo;
@Column(name = "solution")
private String solution;
@Column(name = "solution_url")
private String solutionUrl;
@OneToOne
@JoinColumn(name = "question_id")
private Chemistry question;
public ChemistryAnswer() {}
public ChemistryAnswer(Integer questionNo, String solution, String solutionUrl) {
this.questionNo = questionNo;
this.solution = solution;
this.solutionUrl = solutionUrl;
}
public ChemistryAnswer(Date date, Integer questionNo) {
this.date = date;
this.questionNo = questionNo;
}
public Date getDate() {
return date;
}//accessors
jpaRepository:
@RepositoryRestResource(collectionResourceRel = "chemistry", path = "chemistry")
public interface ChemistryRepo extends JpaRepository<Chemistry, Integer> {
}
Service class:
public interface ChemistryService {
public List<Chemistry>findAll();
public void save(Chemistry chemistry);
}
Service implementation:
@Service
public class ChemistryServiceImpl implements ChemistryService {
private ChemistryRepo repo;
public ChemistryServiceImpl() {}
@Autowired
public ChemistryServiceImpl(ChemistryRepo repo) {
this.repo = repo;
}
@Override
public List<Chemistry> findAll() {
return repo.findAll();
}
@Override
public void save(Chemistry chemistry) {
Chemistry tempChemistry = new Chemistry(chemistry.getDate(),
chemistry.getQuestionNo(), chemistry.getQuestion());
ChemistryAnswer answer = tempChemistry.getAnswer();
tempChemistry.setAnswer(answer);
repo.save(tempChemistry);
}
}
RestController class:
@RestController
public class ChemistryController {
private ChemistryService service;
@Autowired
public ChemistryController(ChemistryService service) {
this.service = service;
}
@GetMapping("/chemistries")
public ResponseEntity<Object>findAll(){
return new ResponseEntity<Object>(service.findAll(), HttpStatus.OK);
}
@PostMapping("/chemistry")
public void save(@RequestBody Chemistry chemistry,
HttpServletResponse response) throws IOException {
service.save(chemistry);
response.sendRedirect("/chemistries");
}
}
Stacktrace Get request:
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178) ~[jackson-databind-2.12.5.jar:2.12.5]
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.12.5.jar:2.12.5]
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:770) ~[jackson-databind-2.12.5.jar:2.12.5]
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178) ~[jackson-databind-2.12.5.jar:2.12.5]
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.12.5.jar:2.12.5]
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:770) ~[jackson-databind-2.12.5.jar:2.12.5]
CodePudding user response:
The issue you are facing is quite abstract. "Postman returns hundreds of same record duplicated." does not tell us much. Still, I guess that the issue is your bi-directional relationship. Try adding @JsonManagedReference
and @JsonBackReference
to your bi-directional relationship in your model as follows:
@JsonManagedReference
@OneToOne(mappedBy = "question",cascade = CascadeType.ALL)
private ChemistryAnswer answer = new ChemistryAnswer();
@OneToOne
@JsonBackReference
@JoinColumn(name = "question_id")
private Chemistry question;