Spring boot + hibernate controller

I try to make a mini forum and I'm stuck. How it should be, first of all you create a post and write message of topic, it redirects to all post and add new posted which you created, an user click on post and it shows in next page all message which filled in. Also I made a comment system, I every post has to have comments, so the problem is in my code which is below, when I tried to make that comments work, it works like this: doesn't matter what post id you choose it shows all comments which does exist, so I changed and failed. May someone explains me, how to make correct with Hibernate.

PostController is: pay attention on method seeMessage, it findes post by id and show message.

package com.pandora.controllers;


import com.pandora.domain.Post;
import com.pandora.services.CommentService;
import com.pandora.services.PostService;
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.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;


@Controller
@RequestMapping("/posts")
public class PostController {

    @Autowired
    private PostService postService;

    @Autowired
    private CommentService commentService;

    @RequestMapping
    public String findAll(Model model) {
        model.addAttribute("posts", postService.findAll());
        return "post/post";
    }

    @RequestMapping(value = "/click", method = RequestMethod.GET)
    public String click() {
        return "post/new";
    }

    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public String addPost(@ModelAttribute Post post) {
        postService.addPost(post);
        return "redirect:/posts";
    }

    @RequestMapping(value = "/{title}/find", method = RequestMethod.GET)
    public String findByName(@PathVariable String title) {
        postService.findByTitle(title);
        return "redirect:/posts";
    }

    @RequestMapping(value = "/{id}/see", method = RequestMethod.GET)
    public String seeMessage(@PathVariable long id, Model model) {
        Post post = postService.findById(id);
        System.out.println("the id is " + id);
        System.out.println("the value of comments are " +post.getComments().size());

        model.addAttribute("post", post);
//        model.addAttribute("postMessage", post.getComments());

        return "post/postmessage";

    }

    @RequestMapping(value = "/{id}/delete")
    public String delete(@PathVariable long id) {
        postService.delete(id);
        return "redirect:/posts";
    }

    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String login(){
        return "login";
    }

}

CommentController is: And here pay attention on method addComment, first I find from what id post it went and after this I have to add comment to founded post.

package com.pandora.controllers;

import com.pandora.domain.Comment;

import com.pandora.domain.Post;
import com.pandora.services.CommentService;
import com.pandora.services.PostService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
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 java.util.ArrayList;
import java.util.List;

@Controller
@RequestMapping("/comments")
public class CommentController {

    @Autowired
    private CommentService commentService;

    @Autowired
    private PostService postService;

    @RequestMapping(value = "/post/{postId}/comment", method = RequestMethod.POST)
    public String addComment(@PathVariable long postId, @ModelAttribute Comment comment){

        Post post = postService.findById(postId);

        System.out.println(post.getId());
        System.out.println(comment.getMessage());

        List comments = new ArrayList();

        comments.add(commentService.addComment(comment));

        post.setComments(comments);

        return "redirect:/posts";
    }

    @RequestMapping(value = "/{id}/delete", method = RequestMethod.GET)
    public String delete(@PathVariable long id){
        commentService.delete(id);
        return "redirect:/posts";
    }

}

Post entity is:

package com.pandora.domain;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import javax.persistence.*;
import java.util.List;

@Entity
@Setter
@Getter
@NoArgsConstructor
public class Post {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "post")
    private List comments;

    @Column(length = 10000)
    private String message;

    private String title;
}

PostService is:

package com.pandora.services;

import com.pandora.domain.Post;
import com.pandora.domain.repositories.PostRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class PostService {

    @Autowired
    private PostRepository postRepository;

    public Post addPost(Post post){
        return postRepository.saveAndFlush(post);
    }

    public List findAll(){
        return postRepository.findAll();
    }

    public Post findByTitle(String title){
        return postRepository.findByTitle(title);
    }

    public Post findById(long id){
        return postRepository.findOne(id);
    }

    public void delete(long id){
        postRepository.delete(id);
    }

}

Comment entity is:

package com.pandora.domain;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import javax.persistence.*;

@Entity
@Setter
@Getter
@NoArgsConstructor
public class Comment {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @ManyToOne(fetch = FetchType.EAGER)
    private Post post;

    private String message;

}

and CommentService is :

package com.pandora.services;

import com.pandora.domain.Comment;
import com.pandora.domain.repositories.CommentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class CommentService {

    @Autowired
    private CommentRepository commentRepository;

    public Comment addComment(Comment comment){
        return commentRepository.saveAndFlush(comment);
    }

    public List findAll(){
        return commentRepository.findAll();
    }

    public void delete(long id){
        commentRepository.delete(id);
    }

    public Comment findOne(long id){
        return commentRepository.findOne(id);
    }

}

and html which showes post which choose by id is: here pay attention to th:each div container. I retrieve from list which are gone from PostController comments. But it doesnt work because when I do it it's always empty. I don't know why it's empty.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
      layout:decorator="layout">

<div layout:fragment="content">

    <h2 align="center">
        <h2 align="left">
            <div th:text="${post.title}"></div>
        </h2>
    </h2>

    <h4 align="center">
        <div th:text="${post.message}"></div>
    </h4>
    <hr/>
    <h4>Comments:</h4>
    <br/>

    <h4>
        <div th:each="comments : ${post}">
           
            <label for="username"><div th:inline="text">[[${#httpServletRequest.remoteUser}]]: </div> </label>
            <div  th:each="comment : ${comments.comments}">
                <div  id="username" th:text="${comment}"></div>
            </div>
        </div>
    </h4>

    <br/>
    <form method="post" name="comment_form" id="comment_form" th:action="@{'/comments/post/{id}/comment'(id=${post.id}) }" role="form">
        <div class="form-group">
            <label for="message">Comment</label>
            <textarea rows="5" class="form-control" id="message" name="message"/>
        </div>
        <button type="submit" id="submit" class="btn btn-primary">Submit</button>
    </form>

</div>

</html>

You need to change the controller as well. Think about something like this, you have a post with zero comments now. The user then posts a comment on PostController method say:

 @RequestMapping(value = "/post/{postId}/addComment", method = RequestMethod.POST)
            public String addPost(@PathVariable("postId")long id, @ModelAttribute Comment comment) {
                postService.addComment(id, comment);
                return "redirect:/to_whatever";
            }

And in your PostService you might want to add the below function:

   public Post addComment(long id, Comment comment){
       Post post = postRepository.findOne(id);
       post.getComments().add(comment);
       return postRepository.saveAndFlush(post);
    }

Change your UI post call accordingly. Also, this will achieve the retrieval part also. Say you want to get comments for a post, all you need to do is find the post by id (or any other unique identifier) and do post.getComments();

Embeddable will establish a OneToMany kind of relation between post and comment. Refer this for more details.

At the database level, you will have something like this:

POST TABLE
post_id     post_name
  1            A
  2            B



POST_COMMENTS TABLE
post_id     message
  1            C
  1            D
  2            E
  2            F

Hope this clears the issue.


Based on your scenario this is what I understand: You have a post and some comments associated with it. However, when you are trying to retrieve comments for a particular post, you are seeing all comments (from other posts as well).

Assuming the above, I would suggest you to not treat comments as a separate entity because comments will only be present if there is a post and comments have to be associated to a single post. @Embeddable might help in this.

My recommendation would be to try something like this:

Make Comments as embeddable:

@Embeddable
public class Comment {
    private String message;
    ...
    ...
    //Any other properties you might need to add
}

And in the Post Entity, make the below changes:

@Entity
@Setter
@Getter
@NoArgsConstructor
public class Post {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @ElementCollection(fetch=FetchType.EAGER)
    private List<Comment> comments = new ArrayList<>();

    @Column(length = 10000)
    private String message;

    private String title;
}

After this, you might want to loose the CommentService and CommentRepository as they wont be needed any longer. Let me know if this helps.

链接地址: http://www.djcxy.com/p/48838.html

上一篇: 结果数量

下一篇: Spring引导+休眠控制器