mirror of
https://github.com/Example-uPagge/spring-boot-one-to-many.git
synced 2024-06-14 11:22:31 +03:00
Initial commit
This commit is contained in:
commit
41af59a122
33
.gitignore
vendored
Normal file
33
.gitignore
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
HELP.md
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
52
pom.xml
Normal file
52
pom.xml
Normal file
@ -0,0 +1,52 @@
|
||||
<?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.6.2</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>com.yapract</groupId>
|
||||
<artifactId>spring-boot-one-to-many</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>spring-boot-one-to-many</name>
|
||||
<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-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>42.4.0</version>
|
||||
<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>
|
@ -0,0 +1,13 @@
|
||||
package com.yprac.spring.hibernate.onetomany;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SpringBootOneToManyApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SpringBootOneToManyApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
package com.yprac.spring.hibernate.onetomany.controller;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.yprac.spring.hibernate.onetomany.exception.ResourceNotFoundException;
|
||||
import com.yprac.spring.hibernate.onetomany.repository.CommentRepository;
|
||||
import com.yprac.spring.hibernate.onetomany.repository.TutorialRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.yprac.spring.hibernate.onetomany.model.Comment;
|
||||
|
||||
@CrossOrigin(origins = "http://localhost:8081")
|
||||
@RestController
|
||||
@RequestMapping("/api")
|
||||
public class CommentController {
|
||||
|
||||
@Autowired
|
||||
private TutorialRepository tutorialRepository;
|
||||
|
||||
@Autowired
|
||||
private CommentRepository commentRepository;
|
||||
|
||||
@GetMapping("/tutorials/{tutorialId}/comments")
|
||||
public ResponseEntity<List<Comment>> getAllCommentsByTutorialId(@PathVariable(value = "tutorialId") Long tutorialId) {
|
||||
if (!tutorialRepository.existsById(tutorialId)) {
|
||||
throw new ResourceNotFoundException("Not found Tutorial with id = " + tutorialId);
|
||||
}
|
||||
|
||||
List<Comment> comments = commentRepository.findByTutorialId(tutorialId);
|
||||
return new ResponseEntity<>(comments, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@GetMapping("/comments/{id}")
|
||||
public ResponseEntity<Comment> getCommentsByTutorialId(@PathVariable(value = "id") Long id) {
|
||||
Comment comment = commentRepository.findById(id)
|
||||
.orElseThrow(() -> new ResourceNotFoundException("Not found Comment with id = " + id));
|
||||
|
||||
return new ResponseEntity<>(comment, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping("/tutorials/{tutorialId}/comments")
|
||||
public ResponseEntity<Comment> createComment(@PathVariable(value = "tutorialId") Long tutorialId,
|
||||
@RequestBody Comment commentRequest) {
|
||||
Comment comment = tutorialRepository.findById(tutorialId).map(tutorial -> {
|
||||
commentRequest.setTutorial(tutorial);
|
||||
return commentRepository.save(commentRequest);
|
||||
}).orElseThrow(() -> new ResourceNotFoundException("Not found Tutorial with id = " + tutorialId));
|
||||
|
||||
return new ResponseEntity<>(comment, HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@PutMapping("/comments/{id}")
|
||||
public ResponseEntity<Comment> updateComment(@PathVariable("id") long id, @RequestBody Comment commentRequest) {
|
||||
Comment comment = commentRepository.findById(id)
|
||||
.orElseThrow(() -> new ResourceNotFoundException("CommentId " + id + "not found"));
|
||||
|
||||
comment.setContent(commentRequest.getContent());
|
||||
|
||||
return new ResponseEntity<>(commentRepository.save(comment), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@DeleteMapping("/comments/{id}")
|
||||
public ResponseEntity<HttpStatus> deleteComment(@PathVariable("id") long id) {
|
||||
commentRepository.deleteById(id);
|
||||
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
@DeleteMapping("/tutorials/{tutorialId}/comments")
|
||||
public ResponseEntity<List<Comment>> deleteAllCommentsOfTutorial(@PathVariable(value = "tutorialId") Long tutorialId) {
|
||||
if (!tutorialRepository.existsById(tutorialId)) {
|
||||
throw new ResourceNotFoundException("Not found Tutorial with id = " + tutorialId);
|
||||
}
|
||||
|
||||
commentRepository.deleteByTutorialId(tutorialId);
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
package com.yprac.spring.hibernate.onetomany.controller;
|
||||
import com.yprac.spring.hibernate.onetomany.exception.ResourceNotFoundException;
|
||||
import com.yprac.spring.hibernate.onetomany.model.Tag;
|
||||
import com.yprac.spring.hibernate.onetomany.model.Tutorial;
|
||||
import com.yprac.spring.hibernate.onetomany.repository.TagRepository;
|
||||
import com.yprac.spring.hibernate.onetomany.repository.TutorialRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@CrossOrigin(origins = "http://localhost:8081")
|
||||
@RestController
|
||||
@RequestMapping("/api")
|
||||
public class TagController {
|
||||
@Autowired
|
||||
private TutorialRepository tutorialRepository;
|
||||
@Autowired
|
||||
private TagRepository tagRepository;
|
||||
|
||||
@GetMapping("/tags")
|
||||
public ResponseEntity<List<Tag>> getAllTags() {
|
||||
List<Tag> tags = new ArrayList<Tag>();
|
||||
tagRepository.findAll().forEach(tags::add);
|
||||
if (tags.isEmpty()) {
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
return new ResponseEntity<>(tags, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@GetMapping("/tutorials/{tutorialId}/tags")
|
||||
public ResponseEntity<List<Tag>> getAllTagsByTutorialId(@PathVariable(value = "tutorialId") Long tutorialId) {
|
||||
if (!tutorialRepository.existsById(tutorialId)) {
|
||||
throw new ResourceNotFoundException("Not found Tutorial with id = " + tutorialId);
|
||||
}
|
||||
List<Tag> tags = tagRepository.findTagsByTutorialsId(tutorialId);
|
||||
return new ResponseEntity<>(tags, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@GetMapping("/tags/{id}")
|
||||
public ResponseEntity<Tag> getTagsById(@PathVariable(value = "id") Long id) {
|
||||
Tag tag = tagRepository.findById(id)
|
||||
.orElseThrow(() -> new ResourceNotFoundException("Not found Tag with id = " + id));
|
||||
return new ResponseEntity<>(tag, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@GetMapping("/tags/{tagId}/tutorials")
|
||||
public ResponseEntity<List<Tutorial>> getAllTutorialsByTagId(@PathVariable(value = "tagId") Long tagId) {
|
||||
if (!tagRepository.existsById(tagId)) {
|
||||
throw new ResourceNotFoundException("Not found Tag with id = " + tagId);
|
||||
}
|
||||
List<Tutorial> tutorials = tutorialRepository.findTutorialsByTagsId(tagId);
|
||||
return new ResponseEntity<>(tutorials, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping("/tutorials/{tutorialId}/tags")
|
||||
public ResponseEntity<Tag> addTag(@PathVariable(value = "tutorialId") Long tutorialId, @RequestBody Tag tagRequest) {
|
||||
Tag tag = tutorialRepository.findById(tutorialId).map(tutorial -> {
|
||||
long tagId = tagRequest.getId();
|
||||
|
||||
// tag is existed
|
||||
if (tagId != 0L) {
|
||||
Tag _tag = tagRepository.findById(tagId)
|
||||
.orElseThrow(() -> new ResourceNotFoundException("Not found Tag with id = " + tagId));
|
||||
tutorial.addTag(_tag);
|
||||
tutorialRepository.save(tutorial);
|
||||
return _tag;
|
||||
}
|
||||
|
||||
// add and create new Tag
|
||||
tutorial.addTag(tagRequest);
|
||||
return tagRepository.save(tagRequest);
|
||||
}).orElseThrow(() -> new ResourceNotFoundException("Not found Tutorial with id = " + tutorialId));
|
||||
return new ResponseEntity<>(tag, HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@PutMapping("/tags/{id}")
|
||||
public ResponseEntity<Tag> updateTag(@PathVariable("id") long id, @RequestBody Tag tagRequest) {
|
||||
Tag tag = tagRepository.findById(id)
|
||||
.orElseThrow(() -> new ResourceNotFoundException("TagId " + id + "not found"));
|
||||
tag.setName(tagRequest.getName());
|
||||
return new ResponseEntity<>(tagRepository.save(tag), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@DeleteMapping("/tutorials/{tutorialId}/tags/{tagId}")
|
||||
public ResponseEntity<HttpStatus> deleteTagFromTutorial(@PathVariable(value = "tutorialId") Long tutorialId, @PathVariable(value = "tagId") Long tagId) {
|
||||
Tutorial tutorial = tutorialRepository.findById(tutorialId)
|
||||
.orElseThrow(() -> new ResourceNotFoundException("Not found Tutorial with id = " + tutorialId));
|
||||
|
||||
tutorial.removeTag(tagId);
|
||||
tutorialRepository.save(tutorial);
|
||||
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
@DeleteMapping("/tags/{id}")
|
||||
public ResponseEntity<HttpStatus> deleteTag(@PathVariable("id") long id) {
|
||||
tagRepository.deleteById(id);
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
package com.yprac.spring.hibernate.onetomany.controller;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.yprac.spring.hibernate.onetomany.exception.ResourceNotFoundException;
|
||||
import com.yprac.spring.hibernate.onetomany.model.Tutorial;
|
||||
import com.yprac.spring.hibernate.onetomany.repository.TutorialRepository;
|
||||
|
||||
@CrossOrigin(origins = "http://localhost:8081")
|
||||
@RestController
|
||||
@RequestMapping("/api")
|
||||
public class TutorialController {
|
||||
|
||||
@Autowired
|
||||
TutorialRepository tutorialRepository;
|
||||
|
||||
@GetMapping("/tutorials")
|
||||
public ResponseEntity<List<Tutorial>> getAllTutorials(@RequestParam(required = false) String title) {
|
||||
List<Tutorial> tutorials = new ArrayList<Tutorial>();
|
||||
|
||||
if (title == null)
|
||||
tutorialRepository.findAll().forEach(tutorials::add);
|
||||
else
|
||||
tutorialRepository.findByTitleContaining(title).forEach(tutorials::add);
|
||||
|
||||
if (tutorials.isEmpty()) {
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
return new ResponseEntity<>(tutorials, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@GetMapping("/tutorials/{id}")
|
||||
public ResponseEntity<Tutorial> getTutorialById(@PathVariable("id") long id) {
|
||||
Tutorial tutorial = tutorialRepository.findById(id)
|
||||
.orElseThrow(() -> new ResourceNotFoundException("Not found Tutorial with id = " + id));
|
||||
|
||||
return new ResponseEntity<>(tutorial, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping("/tutorials")
|
||||
public ResponseEntity<Tutorial> createTutorial(@RequestBody Tutorial tutorial) {
|
||||
Tutorial _tutorial = tutorialRepository.save(new Tutorial(tutorial.getTitle(), tutorial.getDescription(), true));
|
||||
return new ResponseEntity<>(_tutorial, HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@PutMapping("/tutorials/{id}")
|
||||
public ResponseEntity<Tutorial> updateTutorial(@PathVariable("id") long id, @RequestBody Tutorial tutorial) {
|
||||
Tutorial _tutorial = tutorialRepository.findById(id)
|
||||
.orElseThrow(() -> new ResourceNotFoundException("Not found Tutorial with id = " + id));
|
||||
|
||||
_tutorial.setTitle(tutorial.getTitle());
|
||||
_tutorial.setDescription(tutorial.getDescription());
|
||||
_tutorial.setPublished(tutorial.isPublished());
|
||||
|
||||
return new ResponseEntity<>(tutorialRepository.save(_tutorial), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@DeleteMapping("/tutorials/{id}")
|
||||
public ResponseEntity<HttpStatus> deleteTutorial(@PathVariable("id") long id) {
|
||||
tutorialRepository.deleteById(id);
|
||||
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
@DeleteMapping("/tutorials")
|
||||
public ResponseEntity<HttpStatus> deleteAllTutorials() {
|
||||
tutorialRepository.deleteAll();
|
||||
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
@GetMapping("/tutorials/published")
|
||||
public ResponseEntity<List<Tutorial>> findByPublished() {
|
||||
List<Tutorial> tutorials = tutorialRepository.findByPublished(true);
|
||||
|
||||
if (tutorials.isEmpty()) {
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
return new ResponseEntity<>(tutorials, HttpStatus.OK);
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package com.yprac.spring.hibernate.onetomany.exception;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
|
||||
@RestControllerAdvice
|
||||
public class ControllerExceptionHandler {
|
||||
|
||||
@ExceptionHandler(ResourceNotFoundException.class)
|
||||
@ResponseStatus(value = HttpStatus.NOT_FOUND)
|
||||
public ErrorMessage resourceNotFoundException(ResourceNotFoundException ex, WebRequest request) {
|
||||
ErrorMessage message = new ErrorMessage(
|
||||
HttpStatus.NOT_FOUND.value(),
|
||||
new Date(),
|
||||
ex.getMessage(),
|
||||
request.getDescription(false));
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
public ErrorMessage globalExceptionHandler(Exception ex, WebRequest request) {
|
||||
ErrorMessage message = new ErrorMessage(
|
||||
HttpStatus.INTERNAL_SERVER_ERROR.value(),
|
||||
new Date(),
|
||||
ex.getMessage(),
|
||||
request.getDescription(false));
|
||||
|
||||
return message;
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.yprac.spring.hibernate.onetomany.exception;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class ErrorMessage {
|
||||
private int statusCode;
|
||||
private Date timestamp;
|
||||
private String message;
|
||||
private String description;
|
||||
|
||||
public ErrorMessage(int statusCode, Date timestamp, String message, String description) {
|
||||
this.statusCode = statusCode;
|
||||
this.timestamp = timestamp;
|
||||
this.message = message;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public int getStatusCode() {
|
||||
return statusCode;
|
||||
}
|
||||
|
||||
public Date getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package com.yprac.spring.hibernate.onetomany.exception;
|
||||
|
||||
public class ResourceNotFoundException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ResourceNotFoundException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package com.yprac.spring.hibernate.onetomany.model;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
import org.hibernate.annotations.OnDelete;
|
||||
import org.hibernate.annotations.OnDeleteAction;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
@Entity
|
||||
@Table(name = "comments")
|
||||
public class Comment {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "comment_generator")
|
||||
private Long id;
|
||||
|
||||
@Column(name = "content")
|
||||
private String content;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY, optional = false)
|
||||
@JoinColumn(name = "tutorial_id", nullable = false)
|
||||
// @OnDelete(action = OnDeleteAction.CASCADE)
|
||||
@JsonIgnore
|
||||
private Tutorial tutorial;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public Tutorial getTutorial() {
|
||||
return tutorial;
|
||||
}
|
||||
|
||||
public void setTutorial(Tutorial tutorial) {
|
||||
this.tutorial = tutorial;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package com.yprac.spring.hibernate.onetomany.model;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.persistence.*;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
@Entity
|
||||
@Table(name = "tags")
|
||||
public class Tag {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private long id;
|
||||
@Column(name = "name")
|
||||
private String name;
|
||||
@ManyToMany(fetch = FetchType.LAZY, mappedBy = "tags")
|
||||
@JsonIgnore
|
||||
private Set<Tutorial> tutorials = new HashSet<>();
|
||||
public Tag() {
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public Set<Tutorial> getTutorials() {
|
||||
return tutorials;
|
||||
}
|
||||
public void setTutorials(Set<Tutorial> tutorials) {
|
||||
this.tutorials = tutorials;
|
||||
}
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
package com.yprac.spring.hibernate.onetomany.model;
|
||||
|
||||
import org.hibernate.annotations.OnDelete;
|
||||
import org.hibernate.annotations.OnDeleteAction;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@Entity
|
||||
@Table(name = "tutorials")
|
||||
public class Tutorial {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "tutorial_generator")
|
||||
private long id;
|
||||
|
||||
@Column(name = "title")
|
||||
private String title;
|
||||
|
||||
@Column(name = "description")
|
||||
private String description;
|
||||
|
||||
@Column(name = "published")
|
||||
private boolean published;
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
|
||||
@JoinColumn(name = "tutorial_id")
|
||||
private Set<Comment> comments = new HashSet<>();
|
||||
|
||||
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
|
||||
@JoinTable(name = "tutorial_tags",
|
||||
joinColumns = { @JoinColumn(name = "tutorial_id") },
|
||||
inverseJoinColumns = { @JoinColumn(name = "tag_id") })
|
||||
private Set<Tag> tags = new HashSet<>();
|
||||
|
||||
public Tutorial() {
|
||||
|
||||
}
|
||||
|
||||
public Tutorial(String title, String description, boolean published) {
|
||||
this.title = title;
|
||||
this.description = description;
|
||||
this.published = published;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public boolean isPublished() {
|
||||
return published;
|
||||
}
|
||||
|
||||
public void setPublished(boolean isPublished) {
|
||||
this.published = isPublished;
|
||||
}
|
||||
|
||||
public Set<Tag> getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
public void setTags(Set<Tag> tags) {
|
||||
this.tags = tags;
|
||||
}
|
||||
|
||||
public Set<Comment> getComments() {
|
||||
return comments;
|
||||
}
|
||||
|
||||
public void setComments(Set<Comment> comments) {
|
||||
this.comments = comments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Tutorial [id=" + id + ", title=" + title + ", desc=" + description + ", published=" + published + "]";
|
||||
}
|
||||
|
||||
public void addTag(Tag tag) {
|
||||
this.tags.add(tag);
|
||||
tag.getTutorials().add(this);
|
||||
}
|
||||
|
||||
public void removeTag(Long tagId) {
|
||||
Tag tag = this.tags.stream().filter(t -> t.getId() == tagId).findFirst().orElse(null);
|
||||
if (tag != null) {
|
||||
this.tags.remove(tag);
|
||||
tag.getTutorials().remove(this);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.yprac.spring.hibernate.onetomany.repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.transaction.Transactional;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import com.yprac.spring.hibernate.onetomany.model.Comment;
|
||||
|
||||
public interface CommentRepository extends JpaRepository<Comment, Long> {
|
||||
List<Comment> findByTutorialId(Long postId);
|
||||
|
||||
@Transactional
|
||||
void deleteByTutorialId(long tutorialId);
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.yprac.spring.hibernate.onetomany.repository;
|
||||
|
||||
import com.yprac.spring.hibernate.onetomany.model.Tag;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface TagRepository extends JpaRepository<Tag, Long> {
|
||||
|
||||
List<Tag> findTagsByTutorialsId(Long tutorialId);
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package com.yprac.spring.hibernate.onetomany.repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import com.yprac.spring.hibernate.onetomany.model.Tutorial;
|
||||
|
||||
public interface TutorialRepository extends JpaRepository<Tutorial, Long> {
|
||||
List<Tutorial> findByPublished(boolean published);
|
||||
|
||||
List<Tutorial> findByTitleContaining(String title);
|
||||
|
||||
List<Tutorial> findTutorialsByTagsId(Long tagId);
|
||||
}
|
11
src/main/resources/application.properties
Normal file
11
src/main/resources/application.properties
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
spring.datasource.url=
|
||||
spring.datasource.username=
|
||||
spring.datasource.password=
|
||||
|
||||
spring.jpa.show-sql=true
|
||||
#spring.jpa.properties.hibernate.format_sql=true
|
||||
spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.PostgreSQL9Dialect
|
||||
#spring.jpa.generate.ddl=true
|
||||
spring.jpa.hibernate.ddl-auto=none
|
||||
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
|
@ -0,0 +1,13 @@
|
||||
package com.yprac.spring.hibernate.onetomany;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
@SpringBootTest
|
||||
class SpringBootOneToManyApplicationTests {
|
||||
|
||||
@Test
|
||||
void contextLoads() {
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user