Hibernate基础知识

来源:互联网 发布:html5网站源码 编辑:程序博客网 时间:2024/06/05 00:17

ORM原理

  • ORM(Object Relational Mapping)对象到关系的映射;
  • 作用是在关系数据库和对象之间做自动映射,将数据库中的数据表映射成对象,即持久化类。
  • Hibernate通过持久化类(*.java)、映射文件(*.hbm.xml)和配置文件(*.cfg.xml)操作关系型数据库。是ORM工具中的一种。


Hibernate

三个重要的类

配置类(Configuration)|管理Hibernate的配置信息以及启动Hibernate,在运行时读取底层实现的基本信息,包括数据库URL、数据库用户名、密码、驱动类和适配器(dialect)(dialect 指明hibernate连接的数据库方言 不同的数据库 方言在hibernate中是不一样的 连接数据库时必须对应的方言连接对应的数据库)。

会话工厂类(SessionFactory)|生成Session,保存当前数据库中所有映射关系,线程安全。初始化创建过程耗费大量系统资源。

会话类(Session)|是Hibernate数据库持久化操作的核心,负责所有持久化操作,通过它实现增删改查。非线程安全,应注意不要多个线程共享一个Session。

Hibernate配置文件

属性 说明 connection.driver_class 数据库驱动 connection.url 数据库URL地址 connection.username 数据库用户名 connection.password 密码 dialect 连接数据库使用的方言 show_sql 在控制台打印sql语句 format_sql 格式化sql语句 hbm2ddl.auto 自动生成数据库表

POJO编程模型指普通的JavaBean,设置一些参数作为属性,对每个参数定义get和set方法作为访问接口。

Hibernate持久化类的4条编程原则:

  1. 实现一个默认的构造函数:必须包含默认无参构造函数,以便Hibernate通过Constructor.newInstance()实例化持久化类。
  2. 提供一个标识属性(可选):标识属性映射的是数据库表中的主键。
  3. 使用非final类(可选):如果使用final,Hibernate就不能使用代理来延迟关联加载。
  4. 为属性声明访问器(可选):持久化属性不能声明为public,以private的set和get对属性进行持久化。

Hibernate映射

映射文件的命名规则为*.hbm.xml.

  • \元素:用来获取DTD文件
  • \:映射文件中其他元素的根元素,包含可选属性:schema是指该文件映射表所在数据库的schema名称;package:指定包前缀,如果\元素中没有指定全限定的类名,就使用package定义的包前缀作为包名。
  • \:指定持久化类和映射的数据库表名。name:持久化类名;table:映射的数据库表名。包含一个\和多个\.
  • \:持久化的唯一标识,数据库表的主键字段映射。通过\定义主键的生成策略。
  • \:主要的设置属性有:

hibernate主键策略

Hibernate主键生成策略常用属性:

Hibernate数据持久化

Hibernate实例状态

1、瞬时状态(Transient)
由 new 命令开辟内存空间的 Java 对象,也就是平时所熟悉的普通 Java 对象。
瞬时对象特点:
(1) 不和 Session 实例关联
(2) 在数据库中没有和瞬时对象关联的记录

2、持久状态 (Persistent)

持久的实例在数据库中有对应的记录,并拥有一个持久化标识 (identifier).
持久对象总是与 会话Session 和 事务Transaction 相关联,在一个 Session 中,对持久对象的改变不会马上对数据库进行变更,而必须在 Transaction 终止,也就是执行 commit() 之后,才在数据库中真正运行 SQL 进行变更,持久对象的状态才会与数据库进行同步。在同步之前的持久对象称为脏 (dirty) 对象。

瞬时对象转为持久对象:
(1) 通过 Session 的 save() 和 saveOrUpdate() 方法把一个瞬时对象与数据库相关联,这个瞬时对象就成为持久化对象。

(2) 使用 fine(),get(),load() 和 iterater() 待方法查询到的数据对象,将成为持久化对象。

持久化对象的特点:

(1) 和 Session 实例关联

(2) 在数据库中有和持久对象关联的记录

3、脱管状态(Detached)

与持久对象关联的 Session 被关闭后,对象就变为脱管对象。对脱管对象的引用依然有效,对象可继续被修改。

脱管对象特点:

(1) 本质上和瞬时对象相同

(2) 只是比瞬时对象多了一个数据库记录标识值 id.

持久对象转为脱管对象:

当执行 close() 或 clear(),evict() 之后,持久对象会变为脱管对象。

瞬时对象转为持久对象:

通过 Session 的 update(),saveOrUpdate() 和 lock() 等方法,把脱管对象变为持久对象。


通过save()说明对象状态

Save() 方法将瞬时对象保存到数据库,对象的临时状态将变为持久化状态。当对象在持久化状态时,它一直位于 Session 的缓存中,对它的任何操作在事务提交时都将同步到数据库,因此,对一个已经持久的对象调用 save() 或 update() 方法是没有意义的。如:

Student stu = new Strudnet();stu.setCarId(“200234567”);stu.setId(“100”);// 打开 Session, 开启事务session.save(stu);stu.setCardId(“20076548”);session.save(stu); // 无效session.update(stu); // 无效// 提交事务,关闭 Session

Hibernate实体关联关系映射

1、多对一单项关联

    <many-to-one name="factory" class="com.ice.bean.Factory">        <column name="factoryId"></column>    </many-to-one>

:多对一关联,需要此持久化类映射表的外键引用另一个持久化类映射表的主键。
其中name是类中的属性,class是关联的目标类。

2、多对一双向关联

在上述Product配置的基础上,在Factory配置文件中增加一对多映射:

    <set name="products" inverse="true">        <key column="factoryId"></key>        <one-to-many class="com.ice.bean.Product"></one-to-many>    </set>

3、一对一主键关联

两个表之间通过主键形成一对一映射。

<one-to-one name="com.ice.bean.IdCard" cascade="all"></one-to-one><one-to-one name="com.ice.bean.People" constrained="true"></one-to-one>

cascade属性:
all: 所有情况下均进行关联操作,即save-update和delete。
none: 所有情况下均不进行关联操作。这是默认值。
save-update: 在执行save/update/saveOrUpdate时进行关联操作。
delete: 在执行delete 时进行关联操作。
all-delete-orphan: 当一个节点在对象图中成为孤儿节点时,删除该节点。比如在一个一对多的关系中,Student包含多个book,当在对象关系中删除一个book时,此book即成为孤儿节点。

constrained只能在one-to-one的映射中使用,(一般在主表的映射中,有外键的那个表)。如果constrained=true, 则表明存在外键与关联表对应,并且关联表中肯定存在对应的键与其对应, 另外该选项最关键的是影响save和delete的先后顺序。例如增加的时候,如果constainted=true,则会先增加关联表,然后增加本表。 删除的时候反之。

one-to-one的单向关联中,如果constrained=false,则会在查询时就全部取出来,用left outer join的方式。如果constrained=true,hibernate即会延迟加载sql,只把主表的查出来,等有用到关联表的再发sql取。

one-to- one的双向关联中,必须设置constrained=true,要不然会有重复数据读,如2个表user,car;在位false时sql如 下:select * from user a left outer join car b on a.id=b.id left outer join on user c on a.id=c.id where a.id=? 删除的时候最好删除从表,删除主表会先查询下主表,在联合查询下。

4、一对一外键关联

5、多对多关联

通过另外一张表保存多对多的映射关系。

User.hbm.xml:

    <set name="roles" table="tab_mapping">        <key column="user_id"></key>        <many-to-many class="com.ice.bean.Role" column="role_id"></many-to-many>    </set>

Role.hbm.xml:

    <set name="users" table="tab_mapping">        <key column="role_id"></key>        <many-to-many class="com.ice.bean.User" column="user_id"></many-to-many>    </set>  

级联操作

级联(cascade)指的是当主控方执行save、update或delete时,关联对象(被控方)是否进行同步操作。
cascade的参数说明:

—|—
all|所有情况下均采用级联操作
none|默认参数,所有情况下均不采用
save-update|在执行save-update时执行级联操作
delete|在执行delete时执行级联操作


继承关系映射

1、类继承树映射成一张表


配置文件:

<class name="Person" table="tab_person">    <discriminator column="type" type="string"></discriminator>  <!-- 声明鉴别器 -->    <subclass name="Student" discriminator-value="学生">  <!-- 声明子类Student -->        <property name="school"></property>    </subclass>    <subclass name="Staffer" discriminator-value="职员">        <property name="company"></property>    </subclass></class>

特殊限制:那些由子类属性映射的字段,例如tab_person中的school,不能有非空(not null)的限制,否则会导致Hibernate添加数据失败。

2、每个子类映射成一张表

每个子类映射的表都通过主键关联到超类映射的表,形成一对一的关系。

配置文件:

<class name="Person2" table="tab_person2">      <joined-subclass name="Student" table="tab-student">  <!-- 映射子类Student -->        <key column="id"></key>        <property name="school"></property>    </joined-subclass>    <joined-subclass name="Staffer" table="tab_staffer">        <key column="id"></key>        <property name="company"></property>    </joined-subclass></class>

产生的结果是主键相同。

3、每个具体类映射成一张表

每个子类的映射表中都包含继承的父类属性映射字段。

配置文件:

<class name="Person3" abstract="true">      <id name="id">        <generator class="assigned"></generator> <!-- 主键生成策略为手动分配 -->    </id>    <union-subclass name="Student" table="tab-student">  <!-- 映射子类Student -->        <property name="school"></property>    </union-subclass>    <union-subclass name="Staffer" table="tab_staffer">        <property name="company"></property>    </union-subclass></class>

限制:需要父类中的属性名必须与子类映射表中的字段相同。


HQL

HQL:面向对象,从目标对象查询信息并返回单个实体对象或多个实体对象的集合。
SQL:从数据库中查找指定信息,返回单条或多条信息的集合。

HQL区分大小写,SQL语句不区分。

1、通过from查询:

from Person==select * from Person

2、from查询指定字段:

select Person(id,name) from Person per

select per.id,per.name from Person per,此语句返回的不是原有的对象实体状态,而是Object数组,破坏了原有封装性。

HQL参数绑定

1、利用顺序占位符”?”替代,利用Query的setParameter()赋值。

String hql = "from Employee emp where emp.sex=?";Query q = session.createQuery(hql);q.setParameter(0,"男");    //为占位符赋值empList = q.list();

2、利用引用占位符”:parameter”替代

String hql = "from Employee emp where emp.sex=:sex";Query q = session.createQuery(hql);q.setParameter("sex","男");    //为占位符赋值empList = q.list(); 

排序查询

asc是正序排列,desc是降序排列

聚合函数

select avg(emp.age) from Employee emp  //平均年龄select min(emp.age) from Employee emp  //最小年龄 

分组

使用group by子句

原创粉丝点击