commit 41af59a122a253f8280dc3337c7f2c79a45bee25 Author: Epikhin Aleksey Date: Tue Aug 16 12:04:20 2022 +0300 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..549e00a --- /dev/null +++ b/.gitignore @@ -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/ diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..3a59bd1 --- /dev/null +++ b/pom.xml @@ -0,0 +1,52 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.6.2 + + + com.yapract + spring-boot-one-to-many + 0.0.1-SNAPSHOT + spring-boot-one-to-many + + 1.8 + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + org.springframework.boot + spring-boot-starter-web + + + + org.postgresql + postgresql + 42.4.0 + runtime + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/src/main/java/com/yprac/spring/hibernate/onetomany/SpringBootOneToManyApplication.java b/src/main/java/com/yprac/spring/hibernate/onetomany/SpringBootOneToManyApplication.java new file mode 100644 index 0000000..13139ae --- /dev/null +++ b/src/main/java/com/yprac/spring/hibernate/onetomany/SpringBootOneToManyApplication.java @@ -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); + } + +} diff --git a/src/main/java/com/yprac/spring/hibernate/onetomany/controller/CommentController.java b/src/main/java/com/yprac/spring/hibernate/onetomany/controller/CommentController.java new file mode 100644 index 0000000..7a69c4f --- /dev/null +++ b/src/main/java/com/yprac/spring/hibernate/onetomany/controller/CommentController.java @@ -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> getAllCommentsByTutorialId(@PathVariable(value = "tutorialId") Long tutorialId) { + if (!tutorialRepository.existsById(tutorialId)) { + throw new ResourceNotFoundException("Not found Tutorial with id = " + tutorialId); + } + + List comments = commentRepository.findByTutorialId(tutorialId); + return new ResponseEntity<>(comments, HttpStatus.OK); + } + + @GetMapping("/comments/{id}") + public ResponseEntity 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 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 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 deleteComment(@PathVariable("id") long id) { + commentRepository.deleteById(id); + + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @DeleteMapping("/tutorials/{tutorialId}/comments") + public ResponseEntity> 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); + } +} diff --git a/src/main/java/com/yprac/spring/hibernate/onetomany/controller/TagController.java b/src/main/java/com/yprac/spring/hibernate/onetomany/controller/TagController.java new file mode 100644 index 0000000..d0fea34 --- /dev/null +++ b/src/main/java/com/yprac/spring/hibernate/onetomany/controller/TagController.java @@ -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> getAllTags() { + List tags = new ArrayList(); + 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> getAllTagsByTutorialId(@PathVariable(value = "tutorialId") Long tutorialId) { + if (!tutorialRepository.existsById(tutorialId)) { + throw new ResourceNotFoundException("Not found Tutorial with id = " + tutorialId); + } + List tags = tagRepository.findTagsByTutorialsId(tutorialId); + return new ResponseEntity<>(tags, HttpStatus.OK); + } + + @GetMapping("/tags/{id}") + public ResponseEntity 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> getAllTutorialsByTagId(@PathVariable(value = "tagId") Long tagId) { + if (!tagRepository.existsById(tagId)) { + throw new ResourceNotFoundException("Not found Tag with id = " + tagId); + } + List tutorials = tutorialRepository.findTutorialsByTagsId(tagId); + return new ResponseEntity<>(tutorials, HttpStatus.OK); + } + + @PostMapping("/tutorials/{tutorialId}/tags") + public ResponseEntity 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 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 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 deleteTag(@PathVariable("id") long id) { + tagRepository.deleteById(id); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } +} diff --git a/src/main/java/com/yprac/spring/hibernate/onetomany/controller/TutorialController.java b/src/main/java/com/yprac/spring/hibernate/onetomany/controller/TutorialController.java new file mode 100644 index 0000000..0c5869e --- /dev/null +++ b/src/main/java/com/yprac/spring/hibernate/onetomany/controller/TutorialController.java @@ -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> getAllTutorials(@RequestParam(required = false) String title) { + List tutorials = new ArrayList(); + + 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 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 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 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 deleteTutorial(@PathVariable("id") long id) { + tutorialRepository.deleteById(id); + + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @DeleteMapping("/tutorials") + public ResponseEntity deleteAllTutorials() { + tutorialRepository.deleteAll(); + + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @GetMapping("/tutorials/published") + public ResponseEntity> findByPublished() { + List tutorials = tutorialRepository.findByPublished(true); + + if (tutorials.isEmpty()) { + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + return new ResponseEntity<>(tutorials, HttpStatus.OK); + } +} diff --git a/src/main/java/com/yprac/spring/hibernate/onetomany/exception/ControllerExceptionHandler.java b/src/main/java/com/yprac/spring/hibernate/onetomany/exception/ControllerExceptionHandler.java new file mode 100644 index 0000000..ba7cb17 --- /dev/null +++ b/src/main/java/com/yprac/spring/hibernate/onetomany/exception/ControllerExceptionHandler.java @@ -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; + } +} \ No newline at end of file diff --git a/src/main/java/com/yprac/spring/hibernate/onetomany/exception/ErrorMessage.java b/src/main/java/com/yprac/spring/hibernate/onetomany/exception/ErrorMessage.java new file mode 100644 index 0000000..b73b122 --- /dev/null +++ b/src/main/java/com/yprac/spring/hibernate/onetomany/exception/ErrorMessage.java @@ -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; + } +} \ No newline at end of file diff --git a/src/main/java/com/yprac/spring/hibernate/onetomany/exception/ResourceNotFoundException.java b/src/main/java/com/yprac/spring/hibernate/onetomany/exception/ResourceNotFoundException.java new file mode 100644 index 0000000..db6f3e3 --- /dev/null +++ b/src/main/java/com/yprac/spring/hibernate/onetomany/exception/ResourceNotFoundException.java @@ -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); + } +} \ No newline at end of file diff --git a/src/main/java/com/yprac/spring/hibernate/onetomany/model/Comment.java b/src/main/java/com/yprac/spring/hibernate/onetomany/model/Comment.java new file mode 100644 index 0000000..f0b3dd6 --- /dev/null +++ b/src/main/java/com/yprac/spring/hibernate/onetomany/model/Comment.java @@ -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; + } + +} diff --git a/src/main/java/com/yprac/spring/hibernate/onetomany/model/Tag.java b/src/main/java/com/yprac/spring/hibernate/onetomany/model/Tag.java new file mode 100644 index 0000000..69187ec --- /dev/null +++ b/src/main/java/com/yprac/spring/hibernate/onetomany/model/Tag.java @@ -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 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 getTutorials() { + return tutorials; + } + public void setTutorials(Set tutorials) { + this.tutorials = tutorials; + } +} diff --git a/src/main/java/com/yprac/spring/hibernate/onetomany/model/Tutorial.java b/src/main/java/com/yprac/spring/hibernate/onetomany/model/Tutorial.java new file mode 100644 index 0000000..fd4cba8 --- /dev/null +++ b/src/main/java/com/yprac/spring/hibernate/onetomany/model/Tutorial.java @@ -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 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 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 getTags() { + return tags; + } + + public void setTags(Set tags) { + this.tags = tags; + } + + public Set getComments() { + return comments; + } + + public void setComments(Set 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); + } + } +} diff --git a/src/main/java/com/yprac/spring/hibernate/onetomany/repository/CommentRepository.java b/src/main/java/com/yprac/spring/hibernate/onetomany/repository/CommentRepository.java new file mode 100644 index 0000000..f730495 --- /dev/null +++ b/src/main/java/com/yprac/spring/hibernate/onetomany/repository/CommentRepository.java @@ -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 { + List findByTutorialId(Long postId); + + @Transactional + void deleteByTutorialId(long tutorialId); +} diff --git a/src/main/java/com/yprac/spring/hibernate/onetomany/repository/TagRepository.java b/src/main/java/com/yprac/spring/hibernate/onetomany/repository/TagRepository.java new file mode 100644 index 0000000..0bb4e4d --- /dev/null +++ b/src/main/java/com/yprac/spring/hibernate/onetomany/repository/TagRepository.java @@ -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 { + + List findTagsByTutorialsId(Long tutorialId); +} diff --git a/src/main/java/com/yprac/spring/hibernate/onetomany/repository/TutorialRepository.java b/src/main/java/com/yprac/spring/hibernate/onetomany/repository/TutorialRepository.java new file mode 100644 index 0000000..d7f11c1 --- /dev/null +++ b/src/main/java/com/yprac/spring/hibernate/onetomany/repository/TutorialRepository.java @@ -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 { + List findByPublished(boolean published); + + List findByTitleContaining(String title); + + List findTutorialsByTagsId(Long tagId); +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..390dd01 --- /dev/null +++ b/src/main/resources/application.properties @@ -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 \ No newline at end of file diff --git a/src/test/java/com/yprac/spring/hibernate/onetomany/SpringBootOneToManyApplicationTests.java b/src/test/java/com/yprac/spring/hibernate/onetomany/SpringBootOneToManyApplicationTests.java new file mode 100644 index 0000000..be383f6 --- /dev/null +++ b/src/test/java/com/yprac/spring/hibernate/onetomany/SpringBootOneToManyApplicationTests.java @@ -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() { + } + +}