hibernate 一对一 一对多 多对多

这篇具有很好参考价值的文章主要介绍了hibernate 一对一 一对多 多对多。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

依赖导入

<!-- hibernate 核心 -->
<dependency>
    <groupId>org.hibernate.orm</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>6.2.7.Final</version>
</dependency>

<!--  jdbc 实现 -->
<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&amp;useUnicode=true&amp;characterEncoding=utf-8&amp;serverTimezone=Asia/Shanghai</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">a1b2c3</property>

        <!-- 显示sql语句 -->
        <property name="show_sql">false</property>
        <!-- 格式化sql -->
        <property name="format_sql">false</property>
        <!-- sql方言 -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <!-- 自动操作:创建-删除 -->
        <property name="hibernate.hbm2ddl.auto">create-drop</property>
        <!-- 配置sessionFactory.getCurrentSession()的上下文 -->
        <property name="current_session_context_class">thread</property>

        <!-- 导入实体类和映射关系 -->
        <mapping class="org.example.entity.User"/>
        <mapping class="org.example.entity.Address"/>
        <mapping class="org.example.entity.Vlog"/>
        <mapping class="org.example.entity.Role"/>
    </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])

数据库表图解

hibernate 一对一 一对多 多对多

mappedBy属性 和 JoinColumn注解

mappedby : 属性指向实体关联表的拥有者,声明在被拥有者。简单说就是另一边定义了关联规则,这边不用再定义一遍了,直接引用就行。
@JoinColumn: 外键列

  1. 在一对一中@JoinColumn 声明在那个实体类中,生成数据库表时外键列就在那个类。
  2. 在一对多中@JoinColumn 必须声明在多的那个实体类中
  3. 在多对多中@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字段。文章来源地址https://www.toymoban.com/news/detail-639767.html

到了这里,关于hibernate 一对一 一对多 多对多的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 杨中科 .NETCORE EFCORE第七部分 一对一,多对多

    1、builder.HasOne(o =o.Delivery).WithOne(d=d.Order).HasForeignKey(d=dOrderId); 2、测试插入和获取数据 示例 新建 Order 新建 Delivery DeliveryConfig OrderConfig 执行 迁移命令 查看数据库 测试数据插入 运行查看数据 1、多对多:老师一学生 2、EF Core 5.0开始,才正式支持多对多 3、需要中间表,举例数据

    2024年01月17日
    浏览(42)
  • Django基础入门⑪:DjangoDjango数据表关联(一对一,一对多,多对多关系)

    🏘️🏘️个人简介:以山河作礼。 🎖️🎖️: Python领域新星创作者,CSDN实力新星认证,阿里云社区专家博主,CSDN内容合伙人 🎁🎁:Web全栈开发专栏:《Web全栈开发》免费专栏,欢迎阅读! 🎁🎁: 文章末尾扫描二维码可以加入粉丝交流群,不定期免费送书。 Django数据表关

    2024年02月12日
    浏览(58)
  • websocket 局域网 webrtc 一对一 多对多 视频通话 的示例

    基本介绍 WebRTC(Web Real-Time Communications)是一项实时通讯技术,它允许网络应用或者站点,在不借助中间媒介的情况下,建立浏览器之间点对点(Peer-to-Peer)的连接,实现视频流和(或)音频流或者其他任意数据的传输。WebRTC 包含的这些标准使用户在无需安装任何插件或者第

    2024年04月28日
    浏览(46)
  • MyBatis-Plus不写任何resultMap和SQL执行一对一、一对多、多对多关联查询

    MyBatis-Plus不写任何resultMap和SQL执行一对一、一对多、多对多关联查询 MyBatis-Plus不写任何resultMap和SQL执行一对一、一对多、多对多关联查询 com.github.dreamyoung mprelation 0.0.3.2-RELEASE 注解工具使用优缺点: 优点: 使用简单,通过在实体类上添加@OneToOne / @OneToMany / @ManyToOne / @ManyToM

    2024年01月20日
    浏览(49)
  • [Django-04]一对一,一对多

    OneToOneField(),ForeignKey() 的参数如下 to 要连接的模型 to_field 要被关联的目标Model的字段 on_delete 删除主表(被关联的表,也就是非OneToOneField,ForeignKey的表)时,当前表怎么处理。 CASCADE-联动删除 PROTECT -抛出异常 SET_NULL-设为null SET_DEFAULT-设为预定义的默认值 SET-设置为指定的值

    2024年02月04日
    浏览(48)
  • [Mybatis的一对一和一对多]

    目录  🎂前言:  🎂一对一关联查询:  🎂一对多关联查询:  🎂 下面是上面代码中所涉及到的实体类结构设计:  🎂一对一关联查询:  🎂用户实体类(User):  🎂用户详情实体类(UserDetail):  🎂一对多关联查询:  🎂订单实体类(Order):  🎂订单详情实体类

    2024年02月12日
    浏览(44)
  • [MySql]实现多表查询-一对一,一对多

    目录 多表关联关系的分类 mybatis中的多表查询: 数据库准备  项目目录  一对一查询(多对一) 方式一:(xml文件映射) 查询结果:  方式二:(注解映射)  一对多查询(一对多) 方式一:(xml文件映射)  方式二:(注解映射) 既然数据库是存储项目中的数据的,项目中的

    2023年04月10日
    浏览(50)
  • TCP一对一聊天

    客户端 服务端  结果展示  第二种 客户端 服务端 结果

    2024年02月04日
    浏览(42)
  • STM32 LWIP UDP 一对一 一对多发送

    之前没有接触过网络的通信,工作需要 UDP 接收和发送通信,在网上没有找到一对一、一对多的相关例程;于是在技术总监对我的指导,用正点原子板子给的例程是从官方的程序修改的,实现了Lwip UDP通信一对一、一对多的发送程序,可以随便指定发送 ip地址 、发送 端口号

    2024年02月15日
    浏览(47)
  • OVS Vxlan一对一模式VS一对多模式

    OVS Vxlan模式 OVS 支持 GRE、VXLAN、STT、Geneve和IPsec隧道协议,这些隧道协议就是overlay网络的基础协议,通过对物理网络做的一层封装和扩展,解决了二层网络数量不足的问题,最大限度的减少对底层物理网络拓扑的依赖性,同时也最大限度的增加了对网络的控制。针对VXLAN隧道创

    2024年02月03日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包