JPA 一对多 @OneToMany

一个出版者可以发布多本书

@Entity
public class Book {
    @Id
    String isbn;
    String title;
}
@Entity
public class Publisher {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) // 自增
    Long id;
    String name;
    @OneToMany // 会增加 Publisher_Book 表,包含 Publisher 表和 Book 表的主键
    Collection<Book> books;
}

结果

[Hibernate] 
    create table Book (
        isbn varchar(255) not null,
        title varchar(255),
        primary key (isbn)
    ) engine=InnoDB
[Hibernate] 
    create table Publisher (
        id bigint not null auto_increment,
        name varchar(255),
        primary key (id)
    ) engine=InnoDB
[Hibernate] 
    create table Publisher_Book (
        Publisher_id bigint not null,
        books_isbn varchar(255) not null
    ) engine=InnoDB
[Hibernate] 
    alter table Publisher_Book 
       drop index UK_i3heo6s838oow0mpa79ng274f
[Hibernate] 
    alter table Publisher_Book 
       add constraint UK_i3heo6s838oow0mpa79ng274f unique (books_isbn)
[Hibernate] 
    alter table Publisher_Book 
       add constraint FK6ha20gwxv096tljkhx41e71y9 
       foreign key (books_isbn) 
       references Book (isbn)
[Hibernate] 
    alter table Publisher_Book 
       add constraint FKo2gqb7owpbck5t6pgupvs9jha 
       foreign key (Publisher_id) 
       references Publisher (id)

使用 ManyToOne 双向关联

@Entity
public class Book {
    @Id
    String isbn;
    String title;
    @ManyToOne // Book 表会增加 publisher_id 与 Publisher 表关联
    Publisher publisher;
}
@Entity
public class Publisher {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) // 自增
    Long id;
    String name;
    @OneToMany // 会增加 Publisher_Book 表,包含 Publisher 表和 Book 表的主键
    Collection<Book> books;
}

结果

[Hibernate] 
    create table Book (
        isbn varchar(255) not null,
        title varchar(255),
        publisher_id bigint,
        primary key (isbn)
    ) engine=InnoDB
[Hibernate] 
    create table Publisher (
        id bigint not null auto_increment,
        name varchar(255),
        primary key (id)
    ) engine=InnoDB
[Hibernate] 
    create table Publisher_Book (
        Publisher_id bigint not null,
        books_isbn varchar(255) not null
    ) engine=InnoDB
[Hibernate] 
    alter table Publisher_Book 
       drop index UK_i3heo6s838oow0mpa79ng274f
[Hibernate] 
    alter table Publisher_Book 
       add constraint UK_i3heo6s838oow0mpa79ng274f unique (books_isbn)
[Hibernate] 
    alter table Book 
       add constraint FKrb2njmkvio5mhe42empuaiphu 
       foreign key (publisher_id) 
       references Publisher (id)
[Hibernate] 
    alter table Publisher_Book 
       add constraint FK6ha20gwxv096tljkhx41e71y9 
       foreign key (books_isbn) 
       references Book (isbn)
[Hibernate] 
    alter table Publisher_Book 
       add constraint FKo2gqb7owpbck5t6pgupvs9jha 
       foreign key (Publisher_id) 
       references Publisher (id)

使用 @JoinColumn 将维护关系放到 Book 表

@Entity
public class Publisher {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) // 自增
    Long id;
    String name;
    @OneToMany // 使用 @JoinColumn 后不会增加 Publisher_Book 表
    @JoinColumn(name = "publisher_id", referencedColumnName = "id",
            foreignKey = @ForeignKey(name = "PUBLISHER_ID_FK")
    ) // Book 表会增加 publisher_id 字段与 Publisher 表 id(不写默认主键) 关联
    Collection<Book> books;
}
@Entity
public class Book {
    @Id
    String isbn;
    String title;
}

结果

[Hibernate] 
    create table Book (
        isbn varchar(255) not null,
        title varchar(255),
        publisher_id bigint,
        primary key (isbn)
    ) engine=InnoDB
[Hibernate] 
    create table Publisher (
        id bigint not null auto_increment,
        name varchar(255),
        primary key (id)
    ) engine=InnoDB
[Hibernate] 
    alter table Book 
       add constraint PUBLISHER_ID_FK 
       foreign key (publisher_id) 
       references Publisher (id)

 

测试

src/main/resources/META-INF/persistence.xml

<persistence xmlns="https://jakarta.ee/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"
             version="3.0">
    <persistence-unit name="persistenceUnitName">
        <properties><!-- org.hibernate.cfg.JdbcSettings -->
            <property name="jakarta.persistence.jdbc.user" value="root"/>
            <property name="jakarta.persistence.jdbc.password" value="root"/>
            <property name="jakarta.persistence.jdbc.url" value="jdbc:mysql://127.0.0.1:3306/jpa"/>
            <property name="jakarta.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>

            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.highlight_sql" value="true"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
        </properties>
    </persistence-unit>
</persistence>

Main

Persistence.createEntityManagerFactory("persistenceUnitName");
// 单向 1-n 关联关系执行保存时, 一定会多出 UPDATE 语句,与保存先后顺序无关. 因为 n 的一端在插入时不会同时插入外键列
// 查询时, 默认对关联的多的一方使用懒加载策略. 可以使用 @OneToMany 的 fetch 属性来修改默认的加载策略
// 删除时, 默认情况下, 若删除 1 的一端, 则会先把关联的 n 的一端的外键置空, 然后进行删除. 可以通过 @OneToMany 的 cascade 属性来修改默认的删除策略

 


https://docs.jboss.org/hibernate/orm/current/introduction/html_single/Hibernate_Introduction.html#many-to-one

https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html#associations-one-to-many

https://jakarta.ee/learn/docs/jakartaee-tutorial/current/persist/persistence-intro/persistence-intro.html#_multiplicity_in_entity_relationships

posted @ 2019-02-11 16:55  江湖小小白  阅读(1725)  评论(0编辑  收藏  举报