Hibernate教程之一对多&多对一实现*基于xml和注解

本文详细介绍了在Hibernate框架中实现一对多和多对一关系的方法,包括使用XML配置和注解两种方式,并提供了具体的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载自:https://blog.youkuaiyun.com/xingfei_work/article/details/75668328

在上一篇博客中我们知道数据库的三种关系,那么这一篇就聊聊一对多的关系。
一对多的时候,需要明确外键究竟应该设置到那个表上,一般都是多的那个表中拥有一的表的主键来做外键。
人和银行卡,一个人有多张银行卡,多张卡属于一个人,那么这2个表就存在一对多和多对一的关系。
首先我们看看基于xml的实现:
Person类:

//人类--体现一对多,一个人有多张银行卡
public class Person {
    private int id;
    private String name;
    private int age;
    //不需要通过索引操作集合
    //private Set<BankCard> bankCards;//人拥有的所有银行卡
    //需要索引操作集合
    private List<BankCard> bankCards;//人拥有的所有银行卡

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    /*public Set<BankCard> getBankCards() {
        return bankCards;
    }
    public void setBankCards(Set<BankCard> bankCards) {
        this.bankCards = bankCards;
    }*/
    public List<BankCard> getBankCards() {
        return bankCards;
    }
    public void setBankCards(List<BankCard> bankCards) {
        this.bankCards = bankCards;
    }






}

BankCard类:


//银行卡类,体现的是多对一,多张银行卡对应一个人
public class BankCard {

    private int id;
    private String name;//银行
    private String no;//银行卡号

    private Person person;//卡所属的人

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getNo() {
        return no;
    }

    public void setNo(String no) {
        this.no = no;
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }



}

我这里才有的是list集合,所以配置的时候需要使用list标签并且还得维护一个索引字段,为了让Hibernate知道存储顺序的
Person类的映射文件:

<?xml version="1.0" encoding="UTF-8"?>
<!--文档说明,设置映射文件 -->
<!DOCTYPE hibernate-mapping
        SYSTEM
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" >
<!--映射标签 package:内部类的所在的包名 -->
<hibernate-mapping package="org.qf.onetomany">
    <class name="Person" table="tb_person">
        <!--id:主键,name:属性名称,column:字段名称 -->
        <id name="id" column="id">
            <generator class="identity" />
        </id>
        <!--配置属性对应的字段 -->
        <property name="name" length="20" />
        <property name="age" />
        <!--属性为集合的配置 一对多 对多对 name:集合的属性名称 -->
            <!--一对多是Set集合进行关联,无需去维护索引 -->
        <!-- <set name="bankCards" lazy="false">
            key标记的是集合中泛型类对应的外键字段 column:多的一方的外键(该外键必须来自当前的类的主键)
            <key column="pid"></key>
            存在一对多的关系 class:与哪个类存在一对多关系
            <one-to-many class="BankCard" />
        </set> -->
        <!--使用List集合,通过索引控制  -->
        <list name="bankCards" cascade="save-update">
        <key column="pid"></key>
        <index column="list_index"></index>
        <one-to-many class="BankCard"/>
        </list>



    </class>
</hibernate-mapping>

BankCard类的映射文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping
        SYSTEM
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="org.qf.onetomany">
    <class name="BankCard" table="tb_bankcard">
    <!--id:主键,name:属性名称,column:字段名称  -->
        <id name="id" column="id">
            <generator class="identity"/>
        </id>
        <!--配置属性对应的字段  -->
        <property name="name" length="50" />
        <property name="no" length="30" />
        <!--在一对多和多对一中外键设置到多的一方  
        多对一,只需标记2个属性:
        name:指明当前类的哪个属性存在多对一
        column:指明外键的字段名称
        cascade:级联设置,主要标记的书相关联的数据的修改操作:新增、修改、删除
        当保存或删除当前对象时候,是否需要将有关联的对象也进行相同的操作
        取值说明:
   all:全部
   delete:删除
   save-update:保存或修改
   fetch:抓取数据的策略
   标记如果查询项关联的数据信息
   取值:
   1、join使用连接查询
   2、 select单个查询  -->
        <many-to-one name="person" column="pid" cascade="save-update" fetch="join"></many-to-one>
    </class>
</hibernate-mapping>

以上就是一对多和多对一的关系配置,但是需要注意的是使用list集合,必须维护一个字段记录添加顺序,否则List集合无法使用
那么接下来,我们看看如何通过注解实现一对多和多对一呢?
注解主要用的就是@OneToMany和@ManyToOne
Person类:

//人类--体现一对多,一个人有多张银行卡
@Entity
@Table(name="tb_person")
public class Person {
    @Id//主键
    @GeneratedValue(strategy=GenerationType.IDENTITY)//主键生成策略
    private int id;
    @Column(length=20)
    private String name;
    private int age;
    //不需要通过索引操作集合
    //private Set<BankCard> bankCards;//人拥有的所有银行卡
    //需要索引操作集合
    @OneToMany(fetch=FetchType.EAGER,mappedBy="person",targetEntity=BankCard.class)//设置一对多,且立即加载
    private List<BankCard> bankCards;//人拥有的所有银行卡

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    /*public Set<BankCard> getBankCards() {
        return bankCards;
    }
    public void setBankCards(Set<BankCard> bankCards) {
        this.bankCards = bankCards;
    }*/
    public List<BankCard> getBankCards() {
        return bankCards;
    }
    public void setBankCards(List<BankCard> bankCards) {
        this.bankCards = bankCards;
    }
}

注意@OneToMany
体现一对多的映射,不会出现外键
常用属性:
mappedBy:关联的属性名称,就是存在多的一方中的本类的属性名称
targetEntity:集合中泛型类的Class类对象,其实就是多的类的Class
BankCard类:


//银行卡类,体现的是多对一,多张银行卡对应一个人
@Entity
@Table(name="tb_bc")
public class BankCard {

    @Id//主键
    @GeneratedValue(strategy=GenerationType.IDENTITY)//主键生成策略
    private int id;
    @Column(length=30)
    private String name;//银行
    @Column(length=30)
    private String no;//银行卡号
    @ManyToOne
    @JoinColumn(name="pid")
    private Person person;//卡所属的人

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getNo() {
        return no;
    }

    public void setNo(String no) {
        this.no = no;
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }



}

以上就是关于Hibernate中实现一对多和多对一的2种方式,xml和注解

目录&lt;br&gt;&lt;br&gt;前言&lt;br&gt;1. 翻译说明&lt;br&gt;1. 在Tomcat中快速上手&lt;br&gt;1.1. 开始Hibernate之旅&lt;br&gt;1.2. 第一个可持久化类&lt;br&gt;1.3. 映射cat&lt;br&gt;1.4. 与猫同乐&lt;br&gt;1.5. 结语&lt;br&gt;2. 体系结构&lt;br&gt;2.1. 总览&lt;br&gt;2.2. JMX集成&lt;br&gt;2.3. JCA支持&lt;br&gt;3. SessionFactory配置&lt;br&gt;3.1. 可编程配置方式&lt;br&gt;3.2. 获取SessionFactory&lt;br&gt;3.3. 用户自行提供JDBC连接&lt;br&gt;3.4. Hibernate提供的JDBC连接&lt;br&gt;3.5. 可选配置属性&lt;br&gt;3.5.1. SQL Dialects SQL 方言&lt;br&gt;3.5.2. 外连接抓取(Outer Join Fetching )&lt;br&gt;3.5.3. 二进制流&lt;br&gt;3.5.4. 自定义CacheProvider&lt;br&gt;3.5.5. 事务策略配置&lt;br&gt;3.5.6. 绑定SessionFactory到JNDI&lt;br&gt;3.5.7. 查询语言替换 &lt;br&gt;3.6. Logging&lt;br&gt;3.7. 实现NamingStrategy(命名策略)&lt;br&gt;3.8. XML配置文件&lt;br&gt;4. 持久化类(Persistent Classes)&lt;br&gt;4.1. POJO简单示例&lt;br&gt;4.1.1. 为持久化字段声明访问器(accessors)是否可变的标志(mutators)&lt;br&gt;4.1.2. 实现一个默认的构造方法(constructor)&lt;br&gt;4.1.3. 提供一个标识属性(identifier property)(可选) &lt;br&gt;4.1.4. 建议使用不是final的类 (可选)&lt;br&gt;4.2. 实现继承(Inheritance)&lt;br&gt;4.3. 实现equals()hashCode()&lt;br&gt;4.4. 持久化生命周期(Lifecycle)中的回调(Callbacks)&lt;br&gt;4.5. 合法性检查(Validatable)回调&lt;br&gt;4.6. XDoclet标记示例&lt;br&gt;5. O/R Mapping基础&lt;br&gt;5.1. 映射声明(Mapping declaration)&lt;br&gt;5.1.1. Doctype&lt;br&gt;5.1.2. hibernate-mapping&lt;br&gt;5.1.3. class&lt;br&gt;5.1.4. id&lt;br&gt;5.1.4.1. generator&lt;br&gt;5.1.4.2. 高/低位算法(Hi/Lo Algorithm)&lt;br&gt;5.1.4.3. UUID算法(UUID Algorithm )&lt;br&gt;5.1.4.4. 标识字段序列(Identity columns and Sequences)&lt;br&gt;5.1.4.5. 程序分配的标识符(Assigned Identifiers)&lt;br&gt;5.1.5. composite-id 联合ID&lt;br&gt;5.1.6. 识别器(discriminator)&lt;br&gt;5.1.7. 版本(version)(可选)&lt;br&gt;5.1.8. 时间戳(timestamp )(可选)&lt;br&gt;5.1.9. property&lt;br&gt;5.1.10. 多对一(many-to-one)&lt;br&gt;5.1.11. 一对&lt;br&gt;5.1.12. 组件(component), 动态组件(dynamic-component)&lt;br&gt;5.1.13. 子类(subclass)&lt;br&gt;5.1.14. 连接的子类(joined-subclass)&lt;br&gt;5.1.15. map, set, list, bag&lt;br&gt;5.1.16. 引用(import)&lt;br&gt;5.2. Hibernate 的类型&lt;br&gt;5.2.1. 实体(Entities)值(values)&lt;br&gt;5.2.2. 基本值类型&lt;br&gt;5.2.3. 持久化枚举(Persistent enum)类型&lt;br&gt;5.2.4. 自定义值类型&lt;br&gt;5.2.5. 映射到&quot;任意&quot;(any)类型&lt;br&gt;5.3. SQL中引号包围的标识符&lt;br&gt;5.4. 映射文件的模块化(Modular mapping files)&lt;br&gt;6. 集合类(Collections)映射&lt;br&gt;6.1. 持久化集合类(Persistent Collections)&lt;br&gt;6.2. 映射集合(Mapping a Collection)&lt;br&gt;6.3. 值集合关联(Collections of Values and Many-To-Many Associations)&lt;br&gt;6.4. 一对关联(One-To-Many Associations)&lt;br&gt;6.5. 延迟初始化(延迟加载)(Lazy Initialization)&lt;br&gt;6.6. 集合排序(Sorted Collections)&lt;br&gt;6.7. 使用&lt;idbag&gt;&lt;br&gt;6.8. 双向关联(Bidirectional Associations)&lt;br&gt;6.9. 三重关联(Ternary Associations)&lt;br&gt;6.10. 异类关联(Heterogeneous Associations)&lt;br&gt;6.11. 集合例子(Collection example)&lt;br&gt;7. 组件(Component)映射&lt;br&gt;7.1. 依赖对象(Dependent objects)&lt;br&gt;7.2. 在集合中出现的依赖对象&lt;br&gt;7.3. 组件作为Map的索引(Components as Map indices )&lt;br&gt;7.4. 组件作为联合标识符(Components as composite identifiers)&lt;br&gt;7.5. 动态组件 (Dynamic components)&lt;br&gt;8. 继承映射(Inheritance Mappings)&lt;br&gt;8.1. 三种策略&lt;br&gt;8.2. 限制&lt;br&gt;9. 操作持久化数据(Manipulating Persistent Data)&lt;br&gt;9.1. 创建一个持久化对象&lt;br&gt;9.2. 装载对象&lt;br&gt;9.3. Querying&lt;br&gt;9.3.1. 标量查询(Scalar query)&lt;br&gt;9.3.2. 查询接口(Query interface)&lt;br&gt;9.3.3. 可滚动迭代(Scrollable iteration)&lt;br&gt;9.3.4. 过滤集合类(Filtering collections)&lt;br&gt;9.3.5. 条件查询&lt;br&gt;9.3.6. 使用本地SQL的查询&lt;br&gt;9.4. 更新对象&lt;br&gt;9.4.1. 在同一Session中更新&lt;br&gt;9.4.2. 更新从session脱离的对象&lt;br&gt;9.4.3. 把与Session脱离的对象重新绑定&lt;br&gt;9.5. 删除持久化对象&lt;br&gt;9.6. 同步(Flush)&lt;br&gt;9.7. 结束一个Session&lt;br&gt;9.7.1. 同步(Flush) Session&lt;br&gt;9.7.2. 提交数据库事务&lt;br&gt;9.7.3. 关闭Session&lt;br&gt;9.7.4. 处理异常&lt;br&gt;9.8. 生命周期对象图(Lifecyles and object graphs)&lt;br&gt;9.9. 拦截器(Interceptors)&lt;br&gt;9.10. 元数据(Metadata) API&lt;br&gt;10. 事务并行(Transactions And Concurrency)&lt;br&gt;10.1. 配置,会话工厂(Configurations, Sessions and Factories)&lt;br&gt;10.2. 线程连接(Threads and connections)&lt;br&gt;10.3. 考虑对象辨别&lt;br&gt;10.4. 乐观并发控制(Optimistic concurrency control)&lt;br&gt;10.4.1. 使用长生命周期带有自动版本化的会话&lt;br&gt;10.4.2. 使用带有自动版本化的个会话&lt;br&gt;10.4.3. 应用程序自己进行版本检查&lt;br&gt;10.5. 会话断开连接(Session disconnection)&lt;br&gt;10.6. 悲观锁定(Pessimistic Locking)&lt;br&gt;11. Hibernate查询语言(Query Language), 即HQL&lt;br&gt;11.1. 大小写敏感性(Case Sensitivity)&lt;br&gt;11.2. from 子句&lt;br&gt;11.3. 联合(Associations)连接(joins)&lt;br&gt;11.4. select子句&lt;br&gt;11.5. 统计函数(Aggregate functions)&lt;br&gt;11.6. 态(polymorphism)查询&lt;br&gt;11.7. where子句&lt;br&gt;11.8. 达式(Expressions)&lt;br&gt;11.9. order by 子句&lt;br&gt;11.10. group by 子句&lt;br&gt;11.11. 子查询&lt;br&gt;11.12. HQL示例&lt;br&gt;11.13. 提示技巧(Tips &amp; Tricks)&lt;br&gt;12. 条件查询(Criteria Query)&lt;br&gt;12.1. 创建一个Criteria实例&lt;br&gt;12.2. 缩小结果集范围&lt;br&gt;12.3. 对结果排序&lt;br&gt;12.4. 关联(Associations)&lt;br&gt;12.5. 动态关联对象获取(Dynamic association fetching)&lt;br&gt;12.6. 根据示例查询(Example queries)&lt;br&gt;13. 原生SQL查询&lt;br&gt;13.1. 创建一个基于SQL的Query&lt;br&gt;13.2. 别名属性引用&lt;br&gt;13.3. 为SQL查询命名&lt;br&gt;14. 性能提升(Improving performance)&lt;br&gt;14.1. 理解集合的性能&lt;br&gt;14.1.1. 分类&lt;br&gt;14.1.2. Lists, maps sets用于更新效率最高&lt;br&gt;14.1.3. Baglist是反向集合类中效率最高的&lt;br&gt;14.1.4. 一次性删除(One shot delete)&lt;br&gt;14.2. 用于延迟装载的代理&lt;br&gt;14.3. 第二层缓存(The Second Level Cache)s&lt;br&gt;14.3.1. 对映射(Mapping)缓冲&lt;br&gt;14.3.2. 策略:只读缓存&lt;br&gt;14.3.3. 策略:读/写缓存&lt;br&gt;14.3.4. 策略:不严格的读/写缓存&lt;br&gt;14.3.5. 策略:事务缓存(transactional)&lt;br&gt;14.4. 管理Session缓存&lt;br&gt;14.5. 查询缓存(Query Cache)&lt;br&gt;15. 工具箱指南&lt;br&gt;15.1. Schema 生成器(Schema Generation)&lt;br&gt;15.1.1. 对schema定制化(Customizing the schema)&lt;br&gt;15.1.2. 运行该工具&lt;br&gt;15.1.3. 属性(Properties)&lt;br&gt;15.1.4. 使用Ant(Using Ant)&lt;br&gt;15.1.5. 对schema的增量更新(Incremental schema updates)&lt;br&gt;15.1.6. 用Ant来增量更新schema(Using Ant for incremental schema updates)&lt;br&gt;15.2. 代码生成(Code Generation)&lt;br&gt;15.2.1. 配置文件(可选)&lt;br&gt;15.2.2. meta属性&lt;br&gt;15.2.3. 基本的finder生成器(Basic finder generator)&lt;br&gt;15.2.4. 基于Velocity的渲染器/生成器(Velocity based renderer/generator)&lt;br&gt;15.3. 映射文件生成器(Mapping File Generation)&lt;br&gt;15.3.1. 运行此工具&lt;br&gt;16. 示例:父子关系(Parent Child Relationships)&lt;br&gt;16.1. 关于collections&lt;br&gt;16.2. 双向的一对关系(Bidirectional one-to-many)&lt;br&gt;16.3. 级联生命周期(Cascading lifecycle)&lt;br&gt;16.4. 级联更新(Using cascading update())&lt;br&gt;16.5. 结论&lt;br&gt;17. 示例:Weblog 应用程序&lt;br&gt;17.1. 持久化类&lt;br&gt;17.2. Hibernate 映射&lt;br&gt;17.3. Hibernate 代码&lt;br&gt;18. 示例:不同的映射&lt;br&gt;18.1. 雇员/雇主(Employer/Employee)&lt;br&gt;18.2. 作者/著作(Author/Work)&lt;br&gt;18.3. 客户/订单/产品(Customer/Order/Product)&lt;br&gt;19. 最佳实践(Best Practices)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值