什么是hibernate?
O/R Mapping
如何进行对象-关系数据库的匹配?
对象与关系型数据库的不匹配范式,主要表现为下面五个方面,
粒度(精确度)问题
同一性问题:
对象导航问题:
与关系问题
子类型问题
说到这里,我们就知道hibernate是O/R Mapping的一个优秀框架,用于实
现类对象到数据库表的转换
一,环境搭建
建立数据库和数据库表
建立java工程,导入相应的hibernate jar包
配置heibernate.cfg.xml文档
具体配置如下所示:
<?xml version="1.0"?>
<!-- 这一行是xml文档的标准头,表示xml文档的版本为1.0,
标明解析此XML文档的DTD文档的位置,XML解析器使用DTD文档解析XML文档
的合法性 -->
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
标明hibernate.cfg.xml配置信息的开始
<hibernate-configuration>
<!--标明以下的配置是针对seeion-factory的,这个类主要负责保存hibernate的配置,以及对session的操作-->
<session-factory>
<property name="show_sql">true</property>
<!--数据库驱动程序,hibernate在连接数据库的时候,需要用到这个数据-->
<property name="connection.driver_class">
com.mysql.jdbc.Driver
</property>
<!--数据库url地址-->
<property name="connection.url">
jdbc:mysql://127.0.0.1:3306/weixin1</property>
<!--数据库用户名密码-->
<property name="connection.username">root</property>
<property name="connection.password"></property>
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property><!-- 方言 -->
<mapping resource="User.hbn.xml" />
</session-factory>
</hibernate-configuration>
编写测试类:
新建User类 提供get set方法
配置对象/关系映射文件POJO User.hbm.xml
配置如下
<hibernate-mapping>
<class name="com.seehope.po.User" table=“user_list">
<id name=“userId" column=“user_id">
<generator class="native"/>
</id>
<property name=" userName " column=“user_name"/>
<property name=“passwd“ column=“user_passwd"/>
</class>
</hibernate-mapping>
接下里就是实例应用:
这里有三种对数据进行操作的方法,是根据封装的不同层次进行分类的:
配置完成之后,可以使用configuration类建立数据连接,
创建 SessionFactory类 然后打开Session使用回话对数据库进行操作
Configuration cfg = new Configuration().configure();
//获取会话工厂(一个数据库只能有一个会话工厂)
SessionFactory sf = cfg.buildSessionFactory();
//会话
Session session = sf.openSession();
//事务
Transaction tx = session.beginTransaction();
//面向对象的方式 删除默认按照主键删除 此外,hibernate的操作都必须在事务中进行
User user=new User();
user.setUserId(7);
user.setPassWord("123");
user.setUserName("yanjie");
// session.save(user);
session.delete(user);//默认按照主键删除
tx.commit();
2,半对象化
使用HQL(hibernate的SQL)
Configuration cfg = new Configuration().configure();
//获取会话工厂(一个数据库只能有一个会话工厂)
SessionFactory sf = cfg.buildSessionFactory();
//会话
Session session = sf.openSession();
//事务
Transaction tx = session.beginTransaction();
String hql="from User";
Query query=session.createQuery(hql);
List<User> list=query.list();
//返回的是map类型的独享数组
for(int i=0;i<list.size();i++)
{
User user=list.get(i);
System.out.println(user.getUserName());
}
3,SQL语言
直接使用SQLQuery接口
Insert只支持Insert … select
Insert table values …不支持
,二,hibernate-mapping详解:
<hibernate-mapping
schema="schemaName“-------------------(1)
default-cascade="none|save-update“----(2)
auto-import="true|false" --------------(3)
package="package.name" ---------------(4)
/>
(1)、schema(可选):数据库Schema Name
(2)、default-cascade(可选,默认为none):默认的级联风格
(3)、auto-import(可选,默认为true):是否在查询中只使用类名。不用加package名字。
(4)、package(可选),如果该映射文件中定义的类名不包含package,则使用这里定义的package作为类名的前缀。
<class
name=“ClassName”--------------------------- (1)
table=“tableName”-------------------------- (2)
dynamic-update=“true|false”-----------------(3)
dynamic-insert=“true|false“---------------- (4)
select-before-update=“true|false”---------- (5)
/>
、po的类名
、数据库表名
、动态更新(与select-before-update 结合使用)
、动态插入数据
、更新之前查询
主键生产策略
数据库提供的主键生成机制:
sequence(序列)、 identity 。
外部程序提供的主键生成机制:
increment (递增) ,hilo(高低位) ,seqhilo(使用序列的高低位 ),uuid (使用了IP地址+JVM的启动时间(精确到1/4秒)+系统时间+一个计数器值(在JVM中唯一) ),uuid.string。
其它:
native(本地),assigned(手工指定),foreign(外部引用)
<property
name="propertyName" (1)
column="column_name" (2)
type="typename" (3)
update="true|false" (4)
insert="true|false" (4)
formula="arbitrary SQL expression" (5)
/>
(1)、实体类属性名
(2)、表字段名
(3)、属性类型
(4)、 update, insert (可选 - 默认为 true) :表明在用于UPDATE 和/或 INSERT的SQL语句中是否包含这个字段。
(5) 、formula (可选): 一个SQL表达式,定义了这个计算(computed) 属性的值。计算属性没有和它对应的数据库字段。
概述:要做表关系映射之前先了解表关系分类。(注:为了测试方便,我们后面建表策略采用自动建表策略)
表关系分类:
一对一(one-to-one)
一对多(one-to-many)
多对多(many-to-many)
附:自动建表策略配置
在session-factory标签中增加一个子配置
<property name="hbm2ddl.auto">create</property>
取值有:validate | update | create | create-drop
具体解释可参见hibernate_reference.pdf 3.4章节中其他配置
One-one配置:
1、数据库中:一个表的外健对应另一个表的主健,外键要加上Unique约束。或者两个表共享一个主健。(后面采用自动建表策略)
2、javaBean中:在JavaBean中增加一个属性,即另外一个对象的引用,可以单向也可以双向。
3、在hibernate中:
主键映射:都是one-to-one要用foreign生成策略。
外键映射:主表中用one-to-one,副表通过property-ref many-to-one
表关系:
1,一对一
A)主键共享
One to one 其中一个对象的主键采用生成策略
配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="net.seehope.po">
<class name="User" table="user_list">
<id name="userId" column="userID">
<generator class="native"></generator>
</id>
<property name="userName"></property>
<one-to-one name="acct" class="Account" cascade="all">
</one-to-one>
</class>
<class name="Account" table="account_list">
<id name="acctId" column="acctId">
<generator class="foreign">
<param name="property">user</param><!--生成侧却采用外键方式,这是主表-->
</generator>
</id>
<one-to-one name="user" class="User" ></one-to-one>
</class>
B)外键唯一
Many to noe 外键名称
每个对象的主键都自己生成
2,一对多,多对一
当表之间的关系是一对多的时候,我们使用SET标签来配置为一的那一段
<<set
name="propertyName" (1)
table="table_name" (2)
lazy="true|false" (3)
inverse="true|false" (4)
cascade="all|none|save-update|delete|all-delete-orphan" (5)
order-by="column_name asc|desc" (6)
where="arbitrary sql where condition" (7)
outer-join="true|false|auto" (8)
>
(1) name 集合属性的名称
(2) table (可选)目标关联数据库表
(3) lazy (可选——默认为true)允许延迟加载(lazy initialization )
(4) inverse (可选——默认为false) 标记由哪一方来维护关联关系(双向关联中使用)。
(5) cascade (可选——默认为none) 让操作级联到子实体
(6) order-by (可选, 仅用于jdk1.4) 指定表的字段(一个或几个)再加上asc或者desc(可选), 定义Map,Set和Bag的迭代顺序
(7) where (可选) 指定任意的SQL where条件
(8) outer-join(可选-默认为auto)是否使用外联接
A)对象多端使用集合建议使用Set
<set>标签:
各种属性设置
Key标签
迎来配置外键名
One to many
是使用类名来配置的
插入和查询:
user.setUserName("yanjuie1");
Account acct=new Account();
Account acct1=new Account();
acct.setUser(user);
acct1.setUser(user);
user.getActs().add(acct1);
user.getActs().add(acct);
// session.save(user);
String hql="from Account";
Query query=session.createQuery(hql);
List<Account> result=query.list();
双向关联:
Inverse
多对多关联:
Many to many
学生和课程
新建学生和课程java类
配置POJO文档
Many to many 映射
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping auto-import="true" package="net.seehope.po">
<class name="Student">
<id name="sId">
<generator class="native"></generator>
</id>
<property name="sName"></property>
<set name="cous" table="m2m_sc" cascade="all">
<key column="fsid"></key>
<many-to-many class="Course" column="fcid"></many-to-many>
</set>
</class>
<class name="Course">
<id name="cId">
<generator class="native"></generator>
</id>
<property name="cName"></property>
<set name="stds" table="m2m_sc" cascade="all">
<key column="fcid"></key>
<many-to-many class="Student" column="fsid"></many-to-many>
</set>
</class>
</hibernate-mapping>
持久化对象的状态和生命周期
状态:
瞬时对象:
持久化对象:
离线对象:
生命周期:
Hibernate中对象的生命周期如图所示,当经过sava 和 saveOrUpdate 之后,就变成了持久化对象,不可悲回收,且任何修改与数据库褒词同步,期间状态的转换如图所示
:示例代码如下:
package net.seehope.test;
import net.seehope.po.User;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
public class Test {
public static void main(String[] args)
{
// TODO Auto-generated method stub
//加载总配置文件
Configuration cfg = new Configuration().configure();
//获取会话工厂(一个数据库只能有一个会话工厂)
SessionFactory sf = cfg.buildSessionFactory();
//会话
Session session = sf.openSession();
//事务
Transaction tx = session.beginTransaction();
//hibernate对象的生命周期
/* User user=new User();//瞬时对象 不与数据库同步
user.setUserName("yanjie");
session.save(user);
user.setUserName("学生1");
user.setPassWord("123");*/
/* session.evict(user);//转为离线对象,将不再与数据库同步 save之后的
//操作都不在与数据库同步
session.update(user);//再次转换为持久化对象,与数据库褒词同步
user.setUserName("updatezhihou");*/
//查询的到的结果也是持久化对象,将于数据库进行同步
User user2=(User) session.get(User.class, 1);
user2.setPassWord("456");
session.delete(user2);//user2变为瞬时对象
tx.commit();
}
}
结果如下