For this exam we are going to pretend that we are going to construct the back end for an application to create, give and manage surveys.
The application will feature four entity classes: User, Survey, Question, and Response.
Below is code for the initial structure for these classes.
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
private String password;
}
@Entity
public class Survey {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String title;
private String description;
private String prompt;
}
@Entity
public class Question {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String prompt;
private String options;
}
@Entity
public class Response {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String response;
}
For simplicity we will assume that all questions asked on these surveys will be multiple choice questions in which the possible responses are stored as a comma separated list in the options member variable. For example, we can create a Question object with prompt member "What is your favorite color?" and options member "Red,Green,Blue". When a survey taker answers a question we will store the option they selected in the response member of a Response object.
In the list of classes above I intentionally left out the relations between the entities. Write a out a list of the additional member variables you would add to these classes to capture the necessary relations between the entities. Add the appropriate annotations to each of these members.
Here are some important relations you will want to capture:
Solution
In User class add
@OneToMany(mappedBy = "author") List<Survey> surveys;
In Survey class add
@ManyToOne private User author; @OneToMany(mappedBy = "survey") private List<Question> questions;
In Question class add
@ManyToOne private Survey survey; @OneToMany(mappedBy = "question") private List<Response> responses;
In Response class add
@ManyToOne private Question question;
Problem two: save a question
One operation our system should support is the operation of adding a question to a survey. To support this operation we will need a method in a controller class and a method in a service class. Assuming that our application contains only a single service class, the SurveyService class, write the code for a POST method in a QuestionController class for posting a new question for a survey. The body of the post request will come in as a QuestionDTO object. Write the code for this QuestionDTO class, the code for the controller method, and the code for a saveQuestion method in the SurveyService class. For the saveQuestion method to be able to do its work we will also need a repository for saving Question entities. Write the code for that repository as well.
@RestController
@RequestMapping("/questions")
public class QuestionController {
@Autowired
SurveyService service;
@PostMapping
public void saveQuestion(@RequestBody QuestionDTO dto) {
service.saveQuestion(dto);
}
}
In SurveyService:
public void saveQuestion(QuestionDTO dto) {
Optional<Survey> maybeSurvey = surveyRepo.findById(dto.getSurvey());
if(maybeSurvey.isPresent()) {
Survey survey = maybeSurvey.get();
Question q = new Question(dto);
q.setSurvey(survey);
questionRepo.save(q);
}
}
SurveyRepository
public interface SurveyRepository extends JpaRepository<Survey,Integer>{
}
QuestionRepository
public interface QuestionRepository extends JpaRepository<Question,Integer>{
}
QuestionDTO:
public class QuestionDTO {
private int survey;
private String prompt;
private String options;
public QuestionDTO() {}
public QuestionDTO(Question q) {
this.survey = q.getSurvey().getId();
this.prompt = q.getPrompt();
this.options = q.getOptions();
}
public int getSurvey() { return survey; }
public String getPrompt() { return prompt; }
public String getOptions() { return options; }
}
Our application will also have a controller class for surveys. A method we will want to add to our SurveyController class is a method for fetching all of the questions for a particular survey. This method will respond to GET requests with URL
/survey/{id}/question
where {id} is the id of the survey for which we want to fetch questions. Write the code for this method. This method will need to call a method in the SurveyService to fetch those questions: write the code for this method. That method in turn will need to talk to an appropriate repository. Write the code for that repository as well.
@RestController
@RequestMapping("/survey")
public class SurveyController {
@Autowired
SurveyService service;
@GetMapping("{id}/question")
public List<QuestionDTO> fetchQuestions(@PathVariable("id") Integer id) {
List<Question> qs = service.findQuestions(id);
List<QuestionDTO> ds = new ArrayList<QuestionDTO>();
for(Question q : qs) {
ds.add(new QuestionDTO(q));
}
return ds;
}
}
In SurveyService:
public List<Question> findQuestions(int survey) {
Optional<Survey> maybeSurvey = surveyRepo.findById(survey);
if(maybeSurvey.isPresent()) {
Survey s = maybeSurvey.get();
return s.getQuestions();
}
return new ArrayList<Question>();
}