In this blog, I will explain how to use many-to-many mapping in Spring boot Application
What you need?
Initial Plan
Below diagram is the database model diagram which we going to install using the spring boot application.
1. AuditModel Class
This class will automatically create create_at and update_at fields while persisting the entities.
2. Post class
1. PostRepository interface
You can download the source code from Github
What you need?
- JAVA
- MySql
- Eclipse IDE ( whatever you like IDE, I'm using Eclipse for this example)
- Maven ( you can use the Gradle as well)
Initial Plan
spring boot application will be created using spring initializer web tool and imported as a maven project to the eclipse ide. Scenarios will be post and tags. one post have more than one tags and one tags have more than one posts. Two model classes will be created for Post and Tags. Finally, the command line runner interface will be used to run the application.
Below diagram is the database model diagram which we going to install using the spring boot application.
Let's Start to Code.
You need to configure the application.properties file for database connections. add the following content to the src/main/resources/application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/learning spring.datasource.username=root spring.datasource.password=root spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect spring.jpa.hibernate.ddl-auto = updateChange the database username and password according to your MySql configurations.
1. AuditModel Class
This class will automatically create create_at and update_at fields while persisting the entities.
package lk.hjsoft.springbootmanytomany.model; import java.io.Serializable; import java.util.Date; import javax.persistence.Column; import javax.persistence.EntityListeners; import javax.persistence.MappedSuperclass; import javax.persistence.Temporal; import javax.persistence.TemporalType; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @MappedSuperclass @EntityListeners(AuditingEntityListener.class) @JsonIgnoreProperties(value = { "createdAt", "updatedAt" }, allowGetters = true) public abstract class AuditModel implements Serializable { @Temporal(TemporalType.TIMESTAMP) @Column(name = "createAt", nullable = false) @CreatedDate public Date createAt; @Temporal(TemporalType.TIMESTAMP) @Column(name = "updateAt", nullable = false) @LastModifiedDate public Date updateAt; public Date getCreateAt() { return createAt; } public void setCreateAt(Date createAt) { this.createAt = createAt; } public Date getUpdateAt() { return updateAt; } public void setUpdateAt(Date updateAt) { this.updateAt = updateAt; } }Auditing, JsonIgonreProperties. JsonIgnore annotations are discussed in this blog post
2. Post class
package lk.hjsoft.springbootmanytomany.model; import java.util.HashSet; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.Lob; import javax.persistence.ManyToMany; import javax.persistence.Table; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; @Entity @Table(name = "POSTS") public class Post extends AuditModel { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @NotNull @Size(max = 200) @Column(name = "title") private String title; @NotNull @Size(max = 200) @Column(name = "description") private String description; @NotNull @Lob private String content; @ManyToMany(fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST, CascadeType.MERGE }) @JoinTable(name="POSTS_TAGS", joinColumns = { @JoinColumn(name="post_id") }, inverseJoinColumns = { @JoinColumn(name="tag_id") }) private Set3. Tag Classtags = new HashSet<>(); public Set getTags() { return tags; } public void setTags(Set tags) { this.tags = tags; } public Long getId() { return id; } public void setId(Long id) { this.id = 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 String getContent() { return content; } public void setContent(String content) { this.content = content; } }
package lk.hjsoft.springbootmanytomany.model; import java.io.Serializable; import java.util.HashSet; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.ManyToMany; import javax.persistence.Table; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; @Entity @Table(name = "TAGS") public class Tag implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @NotNull @Size(max = 100) private String name; @ManyToMany( fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST, CascadeType.MERGE }, mappedBy = "tags") private SetNow Repository interfaces will be created for database operations.posts = new HashSet<>(); public Set getPosts() { return posts; } public void setPosts(Set posts) { this.posts = posts; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
1. PostRepository interface
package lk.hjsoft.springbootmanytomany.repository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import lk.hjsoft.springbootmanytomany.model.Post; @Repository public interface PostRepository extends JpaRepository<Post, Long>2. TagRepository interface{ }
package lk.hjsoft.springbootmanytomany.repository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import lk.hjsoft.springbootmanytomany.model.Tag; @Repository public interface TagRepository extends JpaRepository<Tag, Long>{ }
Codes to test the application
Main-Class will be replaced with the following codes.package lk.hjsoft.springbootmanytomany; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; import lk.hjsoft.springbootmanytomany.model.Post; import lk.hjsoft.springbootmanytomany.model.Tag; import lk.hjsoft.springbootmanytomany.repository.PostRepository; import lk.hjsoft.springbootmanytomany.repository.TagRepository; @SpringBootApplication @EnableJpaAuditing public class Application implements CommandLineRunner { @Autowired private PostRepository postRepo; @Autowired private TagRepository tagRepo; public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Override public void run(String... args) throws Exception { Post p1 = new Post(); p1.setTitle("first title"); p1.setDescription("first description"); p1.setContent("this is first content"); Tag t1 = new Tag(); t1.setName("spring"); Tag t2 = new Tag(); t2.setName("java"); p1.getTags().add(t1); p1.getTags().add(t2); t1.getPosts().add(p1); t2.getPosts().add(p1); postRepo.save(p1); } }Running the application
mvn spring-boot:runCheck the database and data will be in the relevant tables.
You can download the source code from Github
Comments
Post a Comment