Hibernate中OneToMany映射讲解
hibernate核心,一对多,多对多映射讲解,看了就完全搞明白了

在many一方删除数据1
• 删除“五四大道”
inverse设为true,由many一方删除 从one一方去“删除”, Hibernate只是执行了 问题出在配置文件上 update语句。还是未删 没有配置set节点的inverse属性 除成功! 根本没有执行 Delete语句,数据 没有被删除!
– 配置Hibernate多对多关联,实现某OA系统项 目和人员对照关系的管理
本章目标
• 掌握单向many-to-one关联 • 掌握双向one-to-many关联 • 掌握many-to-many关联
实体间的关联
• 单向多对一
tblJd.getQx().getQxname();
• 单向一对多
TblJd jd = (TblJd)tblQx.getJds().get(0); jd.getJdname(); tblQx.getJds.add(jd);
小结
• 在租房系统中,房屋信息(Fwxx)与用户 (User)间也是多对一关系。如何配置映 射文件,使之可以通过下面的代码输出房 屋信息和发布该信息的用户名称? Fwxx fwxx = (Fwxx)super.get(Fwxx.class,1);
System.out.println( fwxx.getTitle() + "," + fwxx.getUser.getUname());
inverse是“反转”的意思,表示关联关系的控制权。 为true,表示由对方负责关联关系的添加和删除; 执行了delete语句, 为false,表示由自己负责维护关联关系。 删除成功
• 在many一方删除数据的正确做法:
hibernate框架的工作原理

hibernate框架的工作原理Hibernate框架的工作原理Hibernate是一个开源的ORM(Object-Relational Mapping)框架,它将Java对象映射到关系型数据库中。
它提供了一种简单的方式来处理数据持久化,同时也提供了一些高级特性来优化性能和可维护性。
1. Hibernate框架的基本概念在开始讲解Hibernate框架的工作原理之前,需要先了解一些基本概念:Session:Session是Hibernate与数据库交互的核心接口,它代表了一个会话,可以用来执行各种数据库操作。
SessionFactory:SessionFactory是一个线程安全的对象,它用于创建Session对象。
通常情况下,应用程序只需要创建一个SessionFactory对象。
Transaction:Transaction是对数据库操作进行事务管理的接口。
在Hibernate中,所有对数据库的操作都应该在事务中进行。
Mapping文件:Mapping文件用于描述Java类与数据库表之间的映射关系。
它定义了Java类属性与数据库表字段之间的对应关系。
2. Hibernate框架的工作流程Hibernate框架主要分为两个部分:持久化层和业务逻辑层。
其中,持久化层负责将Java对象映射到数据库中,并提供数据访问接口;业务逻辑层则负责处理业务逻辑,并调用持久化层进行数据访问。
Hibernate框架的工作流程如下:2.1 创建SessionFactory对象在应用程序启动时,需要创建一个SessionFactory对象。
SessionFactory是一个线程安全的对象,通常情况下只需要创建一个即可。
2.2 创建Session对象在业务逻辑层需要进行数据访问时,需要先创建一个Session对象。
Session是Hibernate与数据库交互的核心接口,它代表了一个会话,可以用来执行各种数据库操作。
2.3 执行数据库操作在获取了Session对象之后,就可以执行各种数据库操作了。
jpa onetomany 用法

JPA(Java Persistence API)是一种Java持久化标准,它提供了一种将对象映射到数据库中的方式。
在JPA 中,@OneToMany注解用于表示一对多的关系。
@OneToMany注解通常用于在实体类之间建立一对多的关系。
它表示一个实体类中的对象与另一个实体类中的对象存在一对多的关系。
例如,一个班级与多个学生存在一对多的关系,一个学生只能属于一个班级。
以下是使用@OneToMany注解的示例:java复制代码@Entitypublic class Classroom {// ...@OneToMany(mappedBy = "classroom")private List<Student> students;// ...}@Entitypublic class Student {// ...@ManyToOne(fetch = ZY)@JoinColumn(name = "classroom_id")private Classroom classroom;// ...}在上面的示例中,Classroom实体类中有一个students属性,它是一个Student对象的列表。
该列表的一端通过mappedBy属性指定为Student类中的classroom属性。
这意味着Classroom实体类中的每个对象都与Student实体类中的多个对象相关联。
在Student实体类中,classroom属性是一个ManyToOne关联,它表示一个学生只能属于一个班级。
通过@JoinColumn注解指定了外键列的名称(classroom_id),该列用于将学生与班级关联起来。
需要注意的是,在使用@OneToMany注解时,需要在关联的另一端(Student类中的classroom属性)使用@ManyToOne注解来指定关联的另一方。
同时,还需要使用@JoinColumn注解来指定关联的外键列的名称。
one-to-many&many-to-one

Hibernate之one-to-many感悟:基于架构的设计,主要在于xml配置文件的编写原理:表中一对多的实现是在表中使用外键关联,也就是通过一张表的主键做为另一个表的外键来建立一对多关系。
在hibernate的pojo类中实现一对多关系的方法是在主控类中个设置一个集合属性来包含对方类的若干对象,而在另一个类中,只包含主控类的一个对象,从而实现一对多关系的建立。
例如:customer和order表,一个customer对应多个order(订单),则应该在Customer的pojo类中设置一个set来包含order的若干对象。
demo:1、数据库:create table `testdb`.`customer`(`cid` int not null auto_increment,`cname` varchar(20),primary key (`cid`));create unique index `PRIMARY` on `testdb`.`customer`(`cid`);create table `testdb`.`order`(`oid` int not null auto_increment,`odes` varchar(500),`cid` int,primary key (`oid`));create unique index `PRIMARY` on `testdb`.`order`(`oid`);注意,上面两个表在数据库中是相互独立的噢,因为这里所说的一对多是在hibernate层上讨论的,跟在数据库中创建主外键的关联不一样。
2、创建eclipse的hibernate支持3、创建两个表的hbm映射,并相应生成POJO类4、修改pojo类遵从刚才讨论的在hibernate层上实现一对多的原则:在主控类中个设置一个集合属性来包含对方类的若干对象,而在另一个类中,只包含主控类的一个对象,从而实现一对多关系的建立。
hibernate注解之@Onetomany、@Manytoone、@JoinColumn

hibernate注解之@Onetomany、@Manytoone、@JoinColumn @Onetomany⽤于实体类与数据库表映射中少的⼀⽅,请看下⾯的例⼦。
假设⼀个⽤户只有⼀种⾓⾊,⽤户和⾓⾊是onetomany的关系⽤户实体@Entity@Table(name="user")public class UserEntity implements Serializable{@Id@GenericGenerator(name="generator",strategy="uuid")@GeneratedValue(generator="generator")@Column(name="id")private String id;@Column(name="userName")private String userName;@Column(name="password")private String password;@Temporal(value=TemporalType.TIMESTAMP)private Date createDate; ......⾓⾊实体@Entity@Table(name="role")public class RoleEntity implements Serializable{@Id@GenericGenerator(name="generator",strategy="uuid")@GeneratedValue(generator="generator")@Column(name="id")private String id;@Column(name="name")private String name;@OneToMany(fetch=ZY,cascade=CascadeType.PERSIST)private Set<UserEntity> user;同时设置配置⽂件为<prop key="hibernate.hbm2ddl.auto">update</prop>那么在项⽬启动后会⾃动⽣成三张表,分别是⾓⾊表⽤户表⾓⾊⽤户表@Onetomany 的参数:mappedBy:⽤于双向关联时使⽤,否则会引起数据不⼀致的问题。
manytoone注解

manytoone注解在Java开发中,我们经常会遇到需要处理多对一关系的情况。
为了简化开发过程,Hibernate框架提供了一个非常有用的注解——@ManyToOne。
这个注解可以帮助我们轻松地处理多对一关系,使得代码更加简洁和易于维护。
@ManyToOne注解的作用是将一个实体类与另一个实体类建立多对一的关系。
在数据库中,这种关系通常通过外键来实现。
通过使用@ManyToOne注解,我们可以在实体类中指定多对一关系的属性,并且告诉Hibernate框架如何映射到数据库中。
在使用@ManyToOne注解时,我们需要注意一些细节。
首先,我们需要在多对一关系的属性上添加@ManyToOne注解。
这个注解需要指定一个targetEntity属性,用于指定关联的实体类。
例如,如果我们有一个Order实体类和一个Customer实体类,我们可以在Order实体类中的customer属性上添加@ManyToOne注解,并指定targetEntity属性为Customer.class。
其次,我们需要在多对一关系的属性上添加@JoinColumn注解。
这个注解用于指定外键的名称和其他相关属性。
例如,我们可以使用@JoinColumn注解来指定外键的名称、是否可为空、是否唯一等。
除了@ManyToOne注解,Hibernate还提供了其他一些注解来帮助我们处理多对一关系。
例如,@JoinColumn注解可以用于指定外键的名称和其他相关属性。
@Fetch注解可以用于指定关联实体的加载策略。
@Cascade注解可以用于指定级联操作的行为。
使用@ManyToOne注解可以使我们的代码更加简洁和易于维护。
通过使用这个注解,我们可以将多对一关系的处理逻辑集中在实体类中,而不是分散在各个地方。
这样一来,我们可以更加方便地修改和扩展代码。
然而,尽管@ManyToOne注解非常有用,但我们在使用它时还是需要注意一些问题。
首先,我们需要确保多对一关系的属性在数据库中有对应的外键。
Hibernate注解

Hibernate注解常用的hibernate annotation标签如下:@Entity--注释声明该类为持久类。
@Table(name="promotion_info")--持久性映射的表(表名="promotion_info)。
@Column(name=”DESC”,nullable=false,length=512)--用于指定持久属性或字段的映射列。
@Id--注释可以表明哪种属性是该类中的独特标识符(即相当于数据表的主键)。
@GeneratedValue--定义自动增长的主键的生成策略。
@Transient--将忽略这些字段和属性,不用持久化到数据库。
@Temporal(TemporalType.TIMESTAMP)--声明时间格式。
@Enumerated--声明枚举@Version--声明添加对乐观锁定的支持@OneToOne--可以建立实体bean之间的一对一的关联@OneToMany--可以建立实体bean之间的一对多的关联@ManyToOne--可以建立实体bean之间的多对一的关联@ManyToMany--可以建立实体bean之间的多对多的关联@Formula--一个SQL表达式,这种属性是只读的,不在数据库生成属性(可以使用sum、average、max等)@OrderBy--Many端某个字段排序(List)下面是对以上常用Hibernate注解标签的详细介绍与举例:@Entity--注释声明该类为持久类。
将一个Javabean类声明为一个实体的数据库表映射类,最好实现序列化.此时,默认情况下,所有的类属性都为映射到数据表的持久性字段.若在类中,添加另外属性,而非映射来数据库的, 要用下面的Transient来注解.@Table(name="promotion_info")--持久性映射的表(表名="promotion_info).@T able是类一级的注解,定义在@Entity下,为实体bean映射表,目录和schema的名字,默认为实体bean的类名,不带包名.示例:@Entity@T able(name="CUST", schema="RECORDS")public class Customer { ... }@Column(name=”DESC”,nullable=false,length=512)--用于指定持久属性或字段的映射列。
Hibernate_映射配置文件详解

Prepared by TongGang
hibernate.cfg.xml的常用属性
• • • • • • • • • connection.url:数据库URL ername:数据库用户名 connection.password:数据库用户密码 connection.driver_class:数据库JDBC驱动 show_sql:是否将运行期生成的SQL输出到日志以供调试。取 show_sql 值 true | false dialect:配置数据库的方言,根据底层的数据库不同产生不 dialect 同的sql语句,Hibernate 会针对数据库的特性在访问时进行 优化。 hbm2ddl.auto:在启动和停止时自动地创建,更新或删除数据 hbm2ddl.auto 库模式。取值 create | update | create-drop resource:映射文件配置,配置文件名必须包含其相 mapping resource 对于根的全路径 connection.datasource :JNDI数据源的名称
• Class:定义一个持久化类 Class: • name (可选): 持久化类(或者接 (可选): 持久化类( 可选 口)的类名 • table (可选 - 默认是类的非全限 (可选 定名): 定名): 对应的数据库表名 • discriminator-value (可选 - 默 discriminator(可选 认和类名一样): 认和类名一样): 一个用于区分不 同的子类的值,在多态行为时使用。 同的子类的值,在多态行为时使用。 它可以接受的值包括 null 和 not null。 null。
Prepared by TongGang
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
<class name="Person" table="t_person"> <id name="id" type="integer" column="t_id"> <generator class="sequence"> <param name="sequence">hb_person_seq</param> </generator> </id> <property name="name" type="string" column="t_name"></property> <property name="age" type="integer" column="t_age"></property> <many-to-one name="team" class="Team" column="t_team_id"></many-toone> </class>
OneToMany映射(List)
之前,在一对多的映射中,one方使用Set集合去关联many方,我们都知 道Set集合是无序的,而我们现在有这样的需求:one方包含的many方的 对象需要为他们编号,让它们是有序的,可能大家立刻想到使用主键ID, 但是,一方面组件ID的作用并不是编号,它是起唯一标识对象的作用, 另一方面,我们在实际的项目中,很多时候都使用UUID机制来生成和控 制ID,你不可能拿那些值来标识对象吧?也就是说,我们这个时候要单 独拿一个字段来标识many方对象的编号,而该字段又不是主键ID,不能 使用序列,那么这个时候怎么办呢?我们使用one-to-many的list机制来、 实现。
保存
Team team=new Team(); team.setName("广州恒大"); Person p=new Person(); p.setName("可卿"); p.setAge(25); //要让p认识team,到时候外键才会有值 p.setTeam(team); //面向team做保存,同样要让team认识p team.getMembers().add(p); session.saveOrUpdate(team);
删除
删除要考虑的问题:是否级联删除 这里可分三种情况讨论: 1、没有设置cascade级联删除的情况 2、设置了cascade记录删除的情况 3、t_turn为空,外键不为空的情况。
案例描述: 假设现在有一个球队(Team),球队当中有球 员,球队和球员之间显然是一对多的关系, 现在我们一对多的list机制来实现为这些球员 编号,同时引入UUID机制。
UUID:Universally Unique Identifier,是指在一台机器上生 成的数字,它保证对在同一时空中的所有机器都是唯一的。 按照开放软件基金会(OSF)制定的标准计算,用到了以太网 卡地址、纳秒级时间、芯片IDxxx-xxxx-xxxx-xxxxxx-xxxxxxxxxx (8-4-4-4-12)
其中每个 x 是 0-9 或 a-f 范围内的一个十六进制的数字。
UUID的配置
<id name="id" type="string" column="t_id"> <generator class="uuid"></generator> </id>
UUID的优缺点
Hibernate在保存对象时,由hibernate生成一个UUID字符串 作为主键,保证了唯一性,但其并无任何业务逻辑意 义,只能作为主键,唯一缺点长度较大,32位(Hibernate 将UUID中间的“-”删除了)的字符串, 占用存储空间大,但是有两个很重要的优点,Hibernate在维 护主键时,不用去数据库查询,从而提高效率,而且它是跨 数据库的,以后切换数据库极其方便。
特点:uuid长度大,占用空间大,跨数据库,不用访问数据 库就生成主键值,所以效率高且能保证唯一性,移植非常方 便,推荐使用。
one-to-many(List)案例
public class Person { private int id; private String name; private int age; private Team team; }
public class Team { private int id; private String name; List<Person> members=new ArrayList<Person>(); }
<id name="id" type="integer" column="t_id"> <generator class="sequence"> <param name="sequence">hb_team_seq</param> </generator> </id> <property name="name" type="string" column="t_name"></property> <!-- 注意:这里不能有inverse。因为最后执行的更新语句,还要设置t_turn字 段的值。 也就是说,这个时候,one方不但要维护many方的外键t_team_id,还要 维护many方的t_turn字段,这是与set集合的本质区别,因此不能像在set集合 那里那样使用inverse。这里必须要执行update。 --> <list name="members" cascade="all"> <key column="t_team_id"></key> <list-index base="0" column="t_turn"></list-index> <one-to-many class="Person"/> </list>