SpringBoot 2.2.0 SpringData JPA使用示例(三)

本文详细介绍了如何使用 Java Persistence API (JPA) 实现数据库中的一对一、一对多及多对多关系映射,包括实体类定义、关联关系配置及测试示例。

一对一关系

新建一个类表示文章内容,其中有一个外键(article_id)关联到文章表(id)

  • 文章内容表保存content 大文本
@Entity
@Getter
@Setter
@Table
public class ArticleContent {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    private String content;

    /**
     * 关联关系
     * name 表示article_content表中外键的名称
     * referencedColumnName 表示指向对方 article表中主键名 id
     * unique 表示生成的外键索引唯一的
     */
    @OneToOne
    @JoinColumn(name = "article_id", referencedColumnName = "id", unique = true)
    private Article article;

}

  • 文章表
@Getter
@Setter
@Entity
@Table
public class Article {
    /**
     * 主键
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String title;
    private String name;
    private LocalDateTime createDateTime;

    /**
     * 关联关系 一对一
     * mappedBy 表示维护关系主要让ArticleContent 实体中的article来维护
     * cascade 表示级联关系,表示保存article表时同时保存article_content表
     */
    @OneToOne(mappedBy = "article",cascade = CascadeType.PERSIST)
    private ArticleContent articleContent;
}

建表语句

Hibernate: create table article_content (id integer not null auto_increment, content varchar(255), article_id integer, primary key (id)) engine=InnoDB
Hibernate: alter table article_content drop index UK_9e9uapbfex7ktk3ey108j50j7
Hibernate: alter table article_content add constraint UK_9e9uapbfex7ktk3ey108j50j7 unique (article_id)
Hibernate: alter table article_content add constraint FKr2fwi9p8yrsnwdpuijkai2mx3 foreign key (article_id) references article (id)

测试一对一

 @Test
    public void one2one(){

		//一对一保存测试
        Article article=new Article();

        article.setCreateDateTime(LocalDateTime.now());
        article.setName("felix");
        article.setTitle("SpringData Jpa one2one");

        ArticleContent content=new ArticleContent();
        content.setContent("jpa 实现一对一");
        article.setArticleContent(content);

        Article save = articleRepository.save(article);

        System.out.println(save);

    }

过程

Hibernate: insert into article (create_date_time, name, title) values (?, ?, ?)
Hibernate: insert into article_content (article_id, content) values (?, ?)
Article(id=3, title=SpringData Jpa one2one, name=felix, createDateTime=2019-11-04T23:23:36.994620300, articleContent=ArticleContent(id=1, content=jpa 实现一对一, article=null), comments=null)

一对多关系

建立文章评论表

@Getter
@Setter
@Entity
@Table
public class ArticleComment {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String comment;

    @ManyToOne
    @JoinColumn(name = "article_id",referencedColumnName = "id")
    private Article article;

}

在文章Article实体类中添加

   @Getter
@Setter
@Entity
@Table
public class Article {
    /**
     * 主键
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String title;
    private String name;
    private LocalDateTime createDateTime;

    /**
     * 关联关系 一对一
     * mappedBy 表示维护关系主要让ArticleContent 实体中的article来维护
     */
    @OneToOne(mappedBy = "article", cascade = CascadeType.PERSIST)
    private ArticleContent articleContent;

    /**
     * 一对多关系
     */
    @OneToMany(mappedBy = "article")
    private Set<ArticleComment> comments;

   
}

测试

 @Autowired
    private CommentRepository commentRepository;

    @Test
    public void commentTest() {

        Article article = new Article();

        article.setCreateDateTime(LocalDateTime.now());
        article.setName("felix");
        article.setTitle("SpringData Jpa one2many");

        ArticleComment comment = new ArticleComment();
        comment.setComment("有意思");
        ArticleComment comment1 = new ArticleComment();
        comment1.setComment("加油");

        //建立关系
        HashSet<ArticleComment> comments = new HashSet<>();
        comments.add(comment);
        comments.add(comment1);
        article.setComments(comments);

        //先保存文章
        Article save = articleRepository.save(article);

        System.out.println(save);

        ArticleComment save1 = commentRepository.save(comment);
        System.out.println(save1);
        ArticleComment save2 = commentRepository.save(comment1);
        System.out.println(save2);
    }

执行过程

Hibernate: insert into article (create_date_time, name, title) values (?, ?, ?)
Article(id=2, title=SpringData Jpa one2many, name=felix, createDateTime=2019-11-04T22:54:18.045233, articleContent=null, comments=[ArticleComment(id=null, comment=加油, article=null), ArticleComment(id=null, comment=有意思, article=null)])
Hibernate: insert into article_comment (article_id, comment) values (?, ?)
ArticleComment(id=1, comment=有意思, article=null)
Hibernate: insert into article_comment (article_id, comment) values (?, ?)
ArticleComment(id=2, comment=加油, article=null)

多对多关系

@Getter
@Setter
@Entity
@Table(name = "type")
public class ArticleType {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String type;

    /**
     * name 中间表名称
     *
     * joinColumns 中间表对应当前表的主键名称
     *
     * inverseJoinColumns 中间表对应对方表的主键名称
     */
    @ManyToMany
    @JoinTable(name = "article_type",
            joinColumns = {@JoinColumn(name = "tid",referencedColumnName = "id")},
            inverseJoinColumns = {@JoinColumn(name = "aid",referencedColumnName = "id")}
    )
    private Set<Article> articles;

}

 @Getter
@Setter
@Entity
@Table
public class Article {
    /**
     * 主键
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String title;
    private String name;
    private LocalDateTime createDateTime;

    /**
     * 关联关系 一对一
     * mappedBy 表示维护关系主要让ArticleContent 实体中的article来维护
     */
    @OneToOne(mappedBy = "article", cascade = CascadeType.PERSIST)
    private ArticleContent articleContent;

    /**
     * 一对多关系
     */
    @OneToMany(mappedBy = "article")
    private Set<ArticleComment> comments;

    /**
     * 多对多关联
     */
    @ManyToMany(mappedBy = "articles")
    private Set<ArticleType> types;
}

测试

  @Test
    public void manytomanyTest() {
        Article article = new Article();
        article.setCreateDateTime(LocalDateTime.now());
        article.setName("felix");
        article.setTitle("SpringData Jpa many2many");

        Article article1 = new Article();
        article1.setCreateDateTime(LocalDateTime.now());
        article1.setName("felix");
        article1.setTitle("SpringData Jpa many2many");

        ArticleType type = new ArticleType();
        type.setType("other");

        ArticleType type1 = new ArticleType();
        type.setType("other1");

        HashSet<Article> articles = new HashSet<>();
        articles.add(article);
        articles.add(article1);
        type.setArticles(articles);


        HashSet<ArticleType> types = new HashSet<>();
        types.add(type);
        types.add(type1);
        article.setTypes(types);

        articleRepository.save(article);
        articleRepository.save(article1);
        typeRepository.save(type1);
        typeRepository.save(type);

    }

Hibernate: create table article_type (tid integer not null, aid integer not null, primary key (tid, aid)) engine=InnoDB
Hibernate: create table type (id integer not null auto_increment, type varchar(255), primary key (id)) engine=InnoDB
Hibernate: alter table article_type add constraint FK6rv3y9rl4moi6ipc3ecgw2xnn foreign key (aid) references article (id)
Hibernate: alter table article_type add constraint FK7xbykh632xpgso3js30phx3kc foreign key (tid) references type (id)

Hibernate: insert into article (create_date_time, name, title) values (?, ?, ?)
Hibernate: insert into article (create_date_time, name, title) values (?, ?, ?)
Hibernate: insert into type (type) values (?)
Hibernate: insert into type (type) values (?)
Hibernate: insert into article_type (tid, aid) values (?, ?)
Hibernate: insert into article_type (tid, aid) values (?, ?)

表关联情况

在这里插入图片描述

注意

在使用lombok @Data注解会引起 java.lang.StackOverflowError 异常,原因是两个实体进行关联@Data 包含了@ToString,lombok 在生成时会出现循环比较两类中的 hashcode,导致内存溢出。

解决方式:不要使用@Data 改用@Getter、@Setter

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值