Jpa:关系(二)

映射关系

1.单向多对一 @ManyToOne

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@Entity
@Table(name="tb_person")
public class Person {
    @Id
    @GeneratedValue
    private Integer pid;
    private String pname;
}
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@Entity
@Table(name="tb_book")
public class Book {

    @Id
    @GeneratedValue
    private Integer bid;
    private String bname;
    //映射单向 n-1 的关联关系
    //使用 @ManyToOne 来映射多对一的关联关系
    //使用 @JoinColumn 来映射外键.
    //可使用 @ManyToOne 的 fetch 属性来修改默认的关联属性的加载策略
    @JoinColumn(name="p_id")
    @ManyToOne(fetch=FetchType.LAZY)
    private Person person;

}
    /**
     * 保存多对一时, 建议先保存 1 的一端, 后保存 n 的一端, 这样不会多出额外的 UPDATE 语句.
     */
	@Test
	public void testManyToOnePersist(){

        Person person = new Person();
        person.setPname("mmm");

        Book book = new Book();
        book.setBname("book");
        Book book1 = new Book();
        book.setBname("book1");

		//设置关联关系
        book.setPerson(person);
        book1.setPerson(person);

		//执行保存操作
        entityManager.persist(person);
        entityManager.persist(book);
        entityManager.persist(book1);

	}

在这里插入图片描述
在这里插入图片描述

    //不能直接删除 1 的一端, 因为有外键约束.
    @Test
    public void testManyToOneRemove(){
        Person person = entityManager.find(Person.class, 8);
        //删除主表,子表还有记录,则会报错
        entityManager.remove(person);
    }

2 单向一对多 @OneToMany

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@Entity
@Table(name="tb_person")
public class Person {
    @Id
    @GeneratedValue
    private Integer pid;
    private String pname;
    //映射单向 1-n 的关联关系
    //使用 @OneToMany 来映射 1-n 的关联关系
    //使用 @JoinColumn 来映射外键列的名称
    //可以使用 @OneToMany 的 fetch 属性来修改默认的加载策略
    //可以通过 @OneToMany 的 cascade 属性来修改默认的删除策略.
    //注意: 若在 1 的一端的 @OneToMany 中使用 mappedBy 属性, 则 @OneToMany 端就不能再使用 @JoinColumn 属性了.
	@JoinColumn(name="p_id")
    @OneToMany(fetch=FetchType.LAZY)
    private Set<Book> books = new HashSet<>();
}
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@Entity
@Table(name="tb_book")
public class Book {

    @Id
    @GeneratedValue
    private Integer bid;
    private String bname;

}
    //单向 1-n 关联关系执行保存时, 一定会多出 UPDATE 语句.
    //因为 n 的一端在插入时不会同时插入外键列.
    @Test
    public void testOneToManyPersist(){

	    Person person = new Person();
        person.setPname("onetomany");

        Book book = new Book();
        book.setBname("book");
        Book book1 = new Book();
        book1.setBname("book1");

		//设置关联关系
        person.getBooks().add(book);
        person.getBooks().add(book1);

		//执行保存操作
        entityManager.persist(person);
        entityManager.persist(book);
        entityManager.persist(book1);
    }

在这里插入图片描述
在这里插入图片描述

3 双向多对一

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@Entity
@Table(name="tb_person")
public class Person {
    @Id
    @GeneratedValue
    private Integer pid;
    private String pname;
    //映射单向 1-n 的关联关系
    //使用 @OneToMany 来映射 1-n 的关联关系
    //使用 @JoinColumn 来映射外键列的名称
    //可以使用 @OneToMany 的 fetch 属性来修改默认的加载策略
    //可以通过 @OneToMany 的 cascade 属性来修改默认的删除策略.
    //注意: 若在 1 的一端的 @OneToMany 中使用 mappedBy 属性, 则 @OneToMany 端就不能再使用 @JoinColumn 属性了.
	@JoinColumn(name="p_id")
    @OneToMany(fetch=FetchType.LAZY)
    private Set<Book> books = new HashSet<>();
}
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@Entity
@Table(name="tb_book")
public class Book {

    @Id
    @GeneratedValue
    private Integer bid;
    private String bname;
    //映射单向 n-1 的关联关系
    //使用 @ManyToOne 来映射多对一的关联关系
    //使用 @JoinColumn 来映射外键.
    //可使用 @ManyToOne 的 fetch 属性来修改默认的关联属性的加载策略
    @JoinColumn(name="p_id")
    @ManyToOne(fetch=FetchType.LAZY)
    private Person person;

}
    //若是双向 1-n 的关联关系, 执行保存时
    //若先保存 n 的一端, 再保存 1 的一端, 默认情况下, 会多出 n 条 UPDATE 语句.
    //若先保存 1 的一端, 则会多出 n 条 UPDATE 语句
    //在进行双向 1-n 关联关系时, 建议使用 n 的一方来维护关联关系, 而 1 的一方不维护关联系, 这样会有效的减少 SQL 语句.
    //注意: 若在 1 的一端的 @OneToMany 中使用 mappedBy 属性, 则 @OneToMany 端就不能再使用 @JoinColumn 属性了.
    @Test
    public void testOneToManyPersist(){

	    Person person = new Person();
        person.setPname("onetomany");

        Book book = new Book();
        book.setBname("book");
        Book book1 = new Book();
        book1.setBname("book1");

		//设置关联关系
        person.getBooks().add(book);
        person.getBooks().add(book1);

        book.setPerson(person);
        book1.setPerson(person);

		//执行保存操作(两种顺序,sql执行的数量就不一样)
        //sql执行13条
        entityManager.persist(book);
        entityManager.persist(book1);
        entityManager.persist(person);
        //sql执行11条
        entityManager.persist(person);
        entityManager.persist(book);
        entityManager.persist(book1);
    }

在这里插入图片描述
在这里插入图片描述

4 双向一对一

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@Entity
@Table(name="tb_person")
public class Person {
    @Id
    @GeneratedValue
    private Integer pid;
    private String pname;
    //对于不维护关联关系, 没有外键的一方, 使用 @OneToOne 来进行映射, 建议设置 mappedBy=true
    @OneToOne(mappedBy="person")
    private Book book;
}
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@Entity
@Table(name="tb_book")
public class Book {

    @Id
    @GeneratedValue
    private Integer bid;
    private String bname;
    //使用 @OneToOne 来映射 1-1 关联关系。
    //若需要在当前数据表中添加主键则需要使用 @JoinColumn 来进行映射. 注意, 1-1 关联关系, 所以需要添加 unique=true
    @JoinColumn(name="p_id", unique=true)
    @OneToOne(fetch=FetchType.LAZY)
    private Person person;

}
    //双向 1-1 的关联关系, 建议先保存不维护关联关系的一方, 即没有外键的一方, 这样不会多出 UPDATE 语句.
    @Test
    public void testOneToOnePersistence(){
	    Person person = new Person();
        person.setPname("one");

        Book book = new Book();
        book.setBname("toone");

        //设置关联关系
        person.setBook(book);
        book.setPerson(person);

        //执行保存操作
        entityManager.persist(person);
        entityManager.persist(book);
    }

在这里插入图片描述
外键在book表里维护
在这里插入图片描述

5 双向多对多 @ManyToMany

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@Entity
@Table(name="tb_person")
public class Person {
    @Id
    @GeneratedValue
    private Integer pid;
    private String pname;
    @ManyToMany(mappedBy="persons")
    private Set<Book> books = new HashSet<>();
}
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@Entity
@Table(name="tb_book")
public class Book {

    @Id
    @GeneratedValue
    private Integer bid;
    private String bname;
    //使用 @ManyToMany 注解来映射多对多关联关系
    //使用 @JoinTable 来映射中间表
    //1. name 指向中间表的名字
    //2. joinColumns 映射当前类所在的表在中间表中的外键
    //2.1 name 指定外键列的列名
    //2.2 referencedColumnName 指定外键列关联当前表的哪一列
    //3. inverseJoinColumns 映射关联的类所在中间表的外键
    @JoinTable(name="person_book",
            joinColumns={@JoinColumn(name="book_id", referencedColumnName="bid")},
            inverseJoinColumns={@JoinColumn(name="person_id", referencedColumnName="pid")})
    @ManyToMany
    private Set<Person> persons = new HashSet<>();

}
    //多对多的保存
    @Test
    public void testManyToManyPersist(){
        Person person = new Person();
        person.setPname("P1");
        Person person2 = new Person();
        person2.setPname("P2");

        Book book = new Book();
        book.setBname("B1");

        Book book2 = new Book();
        book2.setBname("B2");

        //设置关联关系
        person.getBooks().add(book);
        person.getBooks().add(book2);

        person2.getBooks().add(book);
        person2.getBooks().add(book2);

        book.getPersons().add(person);
        book.getPersons().add(person2);

        book2.getPersons().add(person);
        book2.getPersons().add(person2);

        //执行保存
        entityManager.persist(person);
        entityManager.persist(person2);
        entityManager.persist(book);
        entityManager.persist(book2);
    }

在这里插入图片描述
在这里插入图片描述
多对多,会产生一个中间表
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值