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 属性来修改默认的删除策略