├── .gitignore
├── LICENSE
├── README.md
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── hellokoding
│ │ └── jpa
│ │ ├── HelloJpaApplication.java
│ │ ├── model
│ │ ├── Book.java
│ │ └── Publisher.java
│ │ └── repository
│ │ ├── BookRepository.java
│ │ └── PublisherRepository.java
└── resources
│ ├── application.properties
│ └── db.sql
└── test
└── java
└── com
└── hellokoding
└── jpa
└── HelloJpaApplicationTests.java
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | *.iml
3 | target
4 | *.DS_Store
5 | .mvn
6 | mvn*
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Hello Koding
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # JPA Many-To-Many Relationship Example with Spring Boot, Maven, and MySQL
2 |
3 | ## Guide
4 | https://hellokoding.com/jpa-many-to-many-relationship-mapping-example-with-spring-boot-maven-and-mysql/
5 |
6 | ## Prerequisites
7 | - JDK 1.8 or later
8 | - Maven 3 or later
9 | - MySQL 5.6 or later
10 |
11 | ## Stack
12 | - Spring Data JPA
13 | - Spring Boot
14 | - MySQL
15 |
16 | ## Run
17 | `mvn spring-boot:run`
18 |
19 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.hellokoding
7 | jpa
8 | 0.0.1-SNAPSHOT
9 | jar
10 |
11 | JPA Many-To-Many Example
12 | JPA Many-To-Many Example
13 |
14 |
15 | org.springframework.boot
16 | spring-boot-starter-parent
17 | 1.2.6.RELEASE
18 |
19 |
20 |
21 |
22 | UTF-8
23 | 1.8
24 |
25 |
26 |
27 |
28 | org.springframework.boot
29 | spring-boot-starter-data-jpa
30 |
31 |
32 |
33 | mysql
34 | mysql-connector-java
35 | runtime
36 |
37 |
38 | org.springframework.boot
39 | spring-boot-starter-test
40 | test
41 |
42 |
43 |
44 |
45 |
46 |
47 | org.springframework.boot
48 | spring-boot-maven-plugin
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/src/main/java/com/hellokoding/jpa/HelloJpaApplication.java:
--------------------------------------------------------------------------------
1 | package com.hellokoding.jpa;
2 |
3 | import com.hellokoding.jpa.model.Book;
4 | import com.hellokoding.jpa.model.Publisher;
5 | import com.hellokoding.jpa.repository.BookRepository;
6 | import com.hellokoding.jpa.repository.PublisherRepository;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 | import org.springframework.beans.factory.annotation.Autowired;
10 | import org.springframework.boot.CommandLineRunner;
11 | import org.springframework.boot.SpringApplication;
12 | import org.springframework.boot.autoconfigure.SpringBootApplication;
13 |
14 | import javax.transaction.Transactional;
15 | import java.util.HashSet;
16 |
17 | @SpringBootApplication
18 | public class HelloJpaApplication implements CommandLineRunner {
19 | private static final Logger logger = LoggerFactory.getLogger(HelloJpaApplication.class);
20 |
21 | @Autowired
22 | private BookRepository bookRepository;
23 |
24 | @Autowired
25 | private PublisherRepository publisherRepository;
26 |
27 | public static void main(String[] args) {
28 | SpringApplication.run(HelloJpaApplication.class, args);
29 | }
30 |
31 | @Override
32 | @Transactional
33 | public void run(String... strings) throws Exception {
34 | // save a couple of books
35 | Publisher publisherA = new Publisher("Publisher A");
36 | Publisher publisherB = new Publisher("Publisher B");
37 | Publisher publisherC = new Publisher("Publisher C");
38 |
39 | bookRepository.save(new HashSet(){{
40 | add(new Book("Book A", new HashSet(){{
41 | add(publisherA);
42 | add(publisherB);
43 | }}));
44 |
45 | add(new Book("Book B", new HashSet(){{
46 | add(publisherA);
47 | add(publisherC);
48 | }}));
49 | }});
50 |
51 | // fetch all books
52 | for(Book book : bookRepository.findAll()) {
53 | logger.info(book.toString());
54 | }
55 |
56 | // save a couple of publishers
57 | Book bookA = new Book("Book A");
58 | Book bookB = new Book("Book B");
59 |
60 | publisherRepository.save(new HashSet() {{
61 | add(new Publisher("Publisher A", new HashSet() {{
62 | add(bookA);
63 | add(bookB);
64 | }}));
65 |
66 | add(new Publisher("Publisher B", new HashSet() {{
67 | add(bookA);
68 | add(bookB);
69 | }}));
70 | }});
71 |
72 | // fetch all publishers
73 | for(Publisher publisher : publisherRepository.findAll()) {
74 | logger.info(publisher.toString());
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/main/java/com/hellokoding/jpa/model/Book.java:
--------------------------------------------------------------------------------
1 | package com.hellokoding.jpa.model;
2 |
3 | import javax.persistence.*;
4 | import java.util.Set;
5 |
6 | @Entity
7 | public class Book{
8 | private int id;
9 | private String name;
10 | private Set publishers;
11 |
12 | public Book() {
13 |
14 | }
15 |
16 | public Book(String name) {
17 | this.name = name;
18 | }
19 |
20 | public Book(String name, Set publishers){
21 | this.name = name;
22 | this.publishers = publishers;
23 | }
24 |
25 | @Id
26 | @GeneratedValue(strategy = GenerationType.AUTO)
27 | public int getId() {
28 | return id;
29 | }
30 |
31 | public void setId(int id) {
32 | this.id = id;
33 | }
34 |
35 | public String getName() {
36 | return name;
37 | }
38 |
39 | public void setName(String name) {
40 | this.name = name;
41 | }
42 |
43 | @ManyToMany(cascade = CascadeType.ALL)
44 | @JoinTable(name = "book_publisher", joinColumns = @JoinColumn(name = "book_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "publisher_id", referencedColumnName = "id"))
45 | public Set getPublishers() {
46 | return publishers;
47 | }
48 |
49 | public void setPublishers(Set publishers) {
50 | this.publishers = publishers;
51 | }
52 |
53 | @Override
54 | public String toString() {
55 | String result = String.format(
56 | "Book [id=%d, name='%s']%n",
57 | id, name);
58 | if (publishers != null) {
59 | for(Publisher publisher : publishers) {
60 | result += String.format(
61 | "Publisher[id=%d, name='%s']%n",
62 | publisher.getId(), publisher.getName());
63 | }
64 | }
65 |
66 | return result;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/main/java/com/hellokoding/jpa/model/Publisher.java:
--------------------------------------------------------------------------------
1 | package com.hellokoding.jpa.model;
2 |
3 | import javax.persistence.*;
4 | import java.util.Set;
5 |
6 | @Entity
7 | public class Publisher {
8 | private int id;
9 | private String name;
10 | private Set books;
11 |
12 | public Publisher(){
13 |
14 | }
15 |
16 | public Publisher(String name){
17 | this.name = name;
18 | }
19 |
20 | public Publisher(String name, Set books){
21 | this.name = name;
22 | this.books = books;
23 | }
24 |
25 | @Id
26 | @GeneratedValue(strategy = GenerationType.AUTO)
27 | public int getId() {
28 | return id;
29 | }
30 |
31 | public void setId(int id) {
32 | this.id = id;
33 | }
34 |
35 | public String getName() {
36 | return name;
37 | }
38 |
39 | public void setName(String name) {
40 | this.name = name;
41 | }
42 |
43 | @ManyToMany(mappedBy = "publishers")
44 | public Set getBooks() {
45 | return books;
46 | }
47 |
48 | public void setBooks(Set books) {
49 | this.books = books;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/hellokoding/jpa/repository/BookRepository.java:
--------------------------------------------------------------------------------
1 | package com.hellokoding.jpa.repository;
2 |
3 | import com.hellokoding.jpa.model.Book;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 |
6 | public interface BookRepository extends JpaRepository{
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/com/hellokoding/jpa/repository/PublisherRepository.java:
--------------------------------------------------------------------------------
1 | package com.hellokoding.jpa.repository;
2 |
3 | import com.hellokoding.jpa.model.Publisher;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 |
6 | public interface PublisherRepository extends JpaRepository{
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.datasource.url=jdbc:mysql://localhost/jpa_manytomany
2 | spring.datasource.username=hellokoding
3 | spring.datasource.password=hellokoding
4 | spring.datasource.driver-class-name=com.mysql.jdbc.Driver
5 |
6 | spring.jpa.show-sql=true
7 | spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
--------------------------------------------------------------------------------
/src/main/resources/db.sql:
--------------------------------------------------------------------------------
1 | CREATE DATABASE IF NOT EXISTS `jpa_manytomany`;
2 | USE `jpa_manytomany`;
3 |
4 | --
5 | -- Table structure for table `book`
6 | --
7 |
8 | DROP TABLE IF EXISTS `book`;
9 | CREATE TABLE `book` (
10 | `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
11 | `name` varchar(255) DEFAULT NULL,
12 | PRIMARY KEY (`id`)
13 | ) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8;
14 |
15 | --
16 | -- Table structure for table `book_publisher`
17 | --
18 |
19 | DROP TABLE IF EXISTS `book_publisher`;
20 | CREATE TABLE `book_publisher` (
21 | `book_id` int(10) unsigned NOT NULL,
22 | `publisher_id` int(10) unsigned NOT NULL,
23 | PRIMARY KEY (`book_id`,`publisher_id`),
24 | KEY `fk_bookpublisher_publisher_idx` (`publisher_id`),
25 | CONSTRAINT `fk_bookpublisher_book` FOREIGN KEY (`book_id`) REFERENCES `book` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
26 | CONSTRAINT `fk_bookpublisher_publisher` FOREIGN KEY (`publisher_id`) REFERENCES `publisher` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
27 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
28 |
29 | --
30 | -- Table structure for table `publisher`
31 | --
32 |
33 | DROP TABLE IF EXISTS `publisher`;
34 | CREATE TABLE `publisher` (
35 | `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
36 | `name` varchar(255) DEFAULT NULL,
37 | PRIMARY KEY (`id`)
38 | ) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8;
--------------------------------------------------------------------------------
/src/test/java/com/hellokoding/jpa/HelloJpaApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.hellokoding.jpa;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.SpringApplicationConfiguration;
6 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
7 |
8 | @RunWith(SpringJUnit4ClassRunner.class)
9 | @SpringApplicationConfiguration(classes = HelloJpaApplication.class)
10 | public class HelloJpaApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------