依赖导入
- <dependency>
- <groupId>org.hibernate.orm</groupId>
- <artifactId>hibernate-core</artifactId>
- <version>6.2.7.Final</version>
- </dependency>
- <dependency>
- <groupId>com.mysql</groupId>
- <artifactId>mysql-connector-j</artifactId>
- <version>8.0.33</version>
- </dependency>
复制代码 配置文件
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
- <hibernate-configuration>
-
- <session-factory>
-
- <property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
- <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/jpa_study?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai</property>
- <property name="hibernate.connection.username">root</property>
- <property name="hibernate.connection.password">a1b2c3</property>
-
- <property name="show_sql">false</property>
-
- <property name="format_sql">false</property>
-
- <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
-
- <property name="hibernate.hbm2ddl.auto">create-drop</property>
-
- <property name="current_session_context_class">thread</property>
-
- <mapping />
- <mapping />
- <mapping />
- <mapping />
- </session-factory>
- </hibernate-configuration>
复制代码 一对一
User 实体类- @Entity
- @Table(name = "user")
- @Data
- public class User {
- /*...省略其他内容*/
-
- // 关联列的名称:address_id
- @JoinColumn(name = "address_id")
- @OneToOne(
- // 懒加载
- fetch = FetchType.LAZY
- )
- private Address address;
- }
复制代码 Address 实体类- @Entity
- @Setter
- @Getter
- @Table(name = "address")
- public class Address {
- /*...省略其他内容*/
- @OneToOne(
- // 实体关联的被拥有者,只想User.address字段
- mappedBy = "address"
- )
- private User user;
- }
复制代码 测试- @Test
- public void oneToOneTest() {
- AddressDao addressDao = new AddressDao();// Dao层已经在https://www.cnblogs.com/heirem/p/17616689.html说过了,这里就放代码了
- Address address = new Address();
- address.setDetail("广东中山");
- addressDao.save(address);
- UserDao userDao = new UserDao();
- User user = new User();
- user.setName("张三");
- user.setEmail("zhangsan@email.com");
- userDao.save(user);
- user.setAddress(address);
- userDao.update(user);
- userDao.findAll().forEach(System.out::println);
- }
复制代码- User(id=1, name=张三, email=zhangsan@email.com, address=org.example.entity.Address@74bdfa0b, vLog=[], roles=[])
复制代码 一对多
User实体类- @Entity
- @Table(name = "user")
- @Data
- public class User {
- /*...省略其他内容*/
- @OneToMany(
- // 懒加载
- fetch = FetchType.LAZY,
- // 映射字段,指的是Vlog实体类中映射此实体类的字段,实体关联的被拥有者
- mappedBy = "user"
- )
- private List<Vlog> vLog;
- }
复制代码 Vlog实体类- @Entity
- @Table(name = "vlog")
- @Getter
- @Setter
- public class Vlog {
- /*...省略其他内容*/
- @JoinColumn(name="user_id")// join列,即外键列
- @ManyToOne(
- fetch = FetchType.LAZY
- )
- private User user;
- }
复制代码 测试- @Test
- public void oneToManyTest() {
- UserDao userDao = new UserDao();
- User user = new User();
- user.setName("张三");
- user.setEmail("zhangsan@email.com");
- userDao.save(user);
- VlogDao vlogDao = new VlogDao();
- Vlog v1 = new Vlog();
- v1.setUrl("www.bilirubin.com/video/1");
- vlogDao.save(v1);
- Vlog v2 = new Vlog();
- v2.setUrl("www.bilirubin.com/video/2");
- vlogDao.save(v2);
- v1.setUser(user);
- v2.setUser(user);
- vlogDao.update(v1);
- vlogDao.update(v2);
- userDao.findAll().forEach(System.out::println);
- vlogDao.findAll().forEach(System.out::println);
- }
复制代码- User(id=1, name=张三, email=zhangsan@email.com, address=null, vLog=[org.example.entity.Vlog@6f7a20da, org.example.entity.Vlog@77ba583], roles=[])
- org.example.entity.Vlog@4cd7e993
- org.example.entity.Vlog@685e6a68
复制代码 多对多
- @Entity
- @Table(name = "user")
- @Data
- public class User {
- /*...省略其他内容*/
- @ManyToMany(
- // 懒加载
- fetch = FetchType.LAZY,
- // 关联操作,不过因为多对多只会影响关联表和本表的数据,即user_role表和user
- cascade = {CascadeType.ALL}
- )
- @JoinTable(
- // User Role表关联表的名称
- name = "user_role",
- // joinColumns 链接表的外键,记录此类的的id
- joinColumns = {@JoinColumn(name = "user_id",referencedColumnName = "id")},
- // inverseJoinColumns 链接表的外键,记录链接类的id
- inverseJoinColumns = {@JoinColumn(name = "role_id",referencedColumnName = "id")}
- )
- private List<Role> roles;
- }
复制代码- @Entity
- @Table(name = "role")
- @Setter
- @Getter
- public class Role {
- /*...省略其他内容*/
- @ManyToMany(
- fetch = FetchType.LAZY,
- // 实体关系的拥有者,即在User.roles已经声明过关联规则,这边直接关联User.roles就好了
- mappedBy = "roles"
- )
- private List<User> users;
- }
复制代码 测试- @Test
- public void manyToManyTest() {
- RoleDao roleDao = new RoleDao();
- Role roleUser = new Role();
- roleUser.setName("user");
- roleUser.setDescription("普通用户");
- roleDao.save(roleUser);
- Role roleAdmin = new Role();
- roleAdmin.setName("admin");
- roleAdmin.setDescription("超级用户");
- roleDao.save(roleAdmin);
- UserDao userDao = new UserDao();
- User u1 = new User();
- u1.setName("张三");
- u1.setName("张三@email.com");
- userDao.save(u1);
- User u2 = new User();
- u2.setName("李四");
- u2.setName("李四@email.com");
- userDao.save(u2);
- u1.setRoles(List.of(roleUser));
- u2.setRoles(List.of(roleUser,roleAdmin));
- userDao.update(u1);
- userDao.update(u2);
- userDao.findAll().forEach(System.out::println);
- }
复制代码- User(id=1, name=张三@email.com, email=null, address=null, vLog=[], roles=[org.example.entity.Role@48d44b46])
- User(id=2, name=李四@email.com, email=null, address=null, vLog=[], roles=[org.example.entity.Role@48d44b46, org.example.entity.Role@dd20ebc])
复制代码 数据库表图解

mappedBy属性 和 JoinColumn注解
mappedby : 属性指向实体关联表的拥有者,声明在被拥有者。简单说就是另一边定义了关联规则,这边不用再定义一遍了,直接引用就行。
@JoinColumn: 外键列
- 在一对一中@JoinColumn 声明在那个实体类中,生成数据库表时外键列就在那个类。
- 在一对多中@JoinColumn 必须声明在多的那个实体类中
- 在多对多中@JoinColumn 必须配合@JoinTable使用
toString()造成的栈溢出StackOverflowError
hibernate中实体类如果有互相关联,比如:一对一关系中 User实体中声明了Address的字段private Address address,Address实体中声明了User的字段private User user。在序列化或者打印时,可能出现循环加载关联字段。比如打印User的实例,User的toString中又调用了Address的toString,这是去加载Address实体类的信息,加载出来后Address的toString中有引用了User的toString方法,完了就这样不断的互相调用,循环且套直至StackOverflowError
解决方法:
打印-删除掉User实体类toString引用的Address.toString的代码。
序列化-跳过User的Address字段。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |