Hibernate培训笔记

Hibernate 冬眠
持久层框架
jdbc是java访问数据库的唯一手段
EJB2 官方sun公司的产品 是重量级的框架
hibernate 一年个人开发
EJB3 编写规范
ibatis 和 hibernate 有竞争

Hibernate功能
	帮我们写sql
	关系的维护
	性能优化,提供了缓存,延迟加载

ORM:对象关系映射

类	表
属性	字段
关系	外键

需要两个配置文件
hibernate.cfg.xml  连接数据库
Xxx.hbm.xml	图纸 类和对象的映射

hibernate_reference.pdf 官方使用手册 英文版
相关目录:
etc-log4j.properties[直接复制使用]
lib 开发时依赖的第三方jar包
hibernate3.jar  hibernate核心包

中文文档
hibernate jar包  1.2章
hibernate.cfg.xml配置 3.3章
dialect 方言 土话  3.3章
hibernate 类型 	5.5章
id	5.4.1章
hibernate.cfg.xml 中 属性hibernate开头可以省略
===================================================
相关配置代码:
hibernate.cfg.xml

<session-factory>
	<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
	<property name="connection.url">
jdbc:oracle:thin:@10.0.4.98:1521:ww
	</property>
	<property name="connection.username">xwq</property>
	<property name="connection.password">xwq</property>
	<property name="dialect">org.hibernate.dialect.OracleDialect</property>
	<property name="show_sql">true</property>
	<property name="format_sql">true</property>
	<mapping resource="day01/Person.hbm.xml"/>
</session-factory>

Person.hbm.xml

<hibernate-mapping package="day01">
	<class name="Person" table="xwq_person">
		<id name="id" column="id" type="integer">
			<generator class="sequence">
				<param name="sequence">xwq_seq</param>
			</generator>
<!--			<generator class="native">
				<param name="sequence">xwq_seq</param>
			</generator>-->
		</id>
		<property name="name" column="name" type="string"></property>
		<property name="birthday" column="birthday" type="date">
		</property>
		<property name="sex" column="sex" type="boolean"></property>
	</class>
</hibernate-mapping>

util:
public class HibernateUtil
{
    private static SessionFactory sessionFactory;
    
    static{
        sessionFactory = new Configuration()
                            .configure()
                            .buildSessionFactory();
    }
    
    public static Session getSession()
    {
        return sessionFactory.openSession();
    }
}

java:
Person p = new Person();
p.setName("efg");
p.setSex(false);
p.setBirthday(java.sql.Date.valueOf("1999-01-01"));

Session session = null;
try
{
    session = HibernateUtil.getSession();
    session.beginTransaction();
    session.save(p);
    session.getTransaction().commit();
}
catch (Exception e)
{
    session.getTransaction().rollback();
} finally
{
    if(session != null)
    {
        session.close();
    }
}
=======================================
Hibernate 核心api
Configuration 用于解析hibernate.cfg.xml和Xxx.hbm.xml,并创建SessionFactory对象
SessionFactory 用于创建Session对象,创建过程很消耗资源,线程安全 做成单例
Session [程序和数据库的会话] 持久化管理器 线程不安全【】
Transaction	事务管理器

动态DML
dynamic-insert="true"  //映射文件中的class中的属性
dynamic-update="true"  //持久态时 动态更新 不是调用update方法

莫个字段更新时不需要修改  设置 update="false";
			insert="false";
【但可以通过hql来更新  executeUpdate() 来更新】

查询可以不加事务



数据库字段名和属性名完全相同 可以不写 
type类型也可以不写
配置文件中的属性 针对set get方法而言

Hibernate 对象的状态
临时态:	
内存里有,而且数据库没有一条记录跟他对应,对象没有被Session管理
持久态:	
内存里有,而且数据库有对应的记录,这个对象被Session管理
【特征:对象状态改变,自动同步到数据库】
游离态:
内存里有,而且数据库有对应的记录,这个对象没有被Session管理


Hibernate曾删改
//增加
public static void insert(Person p){
	session.save(p);
	//session.saveOrUpdate(p); //数据库有相同的id就更新,反之就插入
	//临时态执行save  游离态 持久态执行update
}

//删除 根据id
public static void delete(Integer id){
	Person p = new Person();
	p.setID(2);
	session.delete(p);
}

//删除 根据 Person
public static void delete(Person p){
	session.delete(p);
}

//修改
public static void update(Person p){
	session.update(p);
	//session.saveOrUpdate(p);
}

//查询 根据id
public static Person selectById(Integer id){
	session.get(Person.class,id);
	//session.load(Person.class,id) //有取值后再查询  p.getName(); 后执行查询

//load 有延迟加载,如果对象不存在,抛出异常 当用的时候才去数据库查
//get  没有延迟加载,如果对象不存在,返回null
}

//查询所有
public static List<Person> select(){
	List<Person> persons = null;
	Person person = null;
	String hql = "from Person";
	Query query = session.createQuery(hql);
	persons = query.list();
	person = query.uniqueResult();
}

// 查询 根据name
public static List<Person> selectByName(String name){
	List<Person> persons = null;
	String hql = "from Person p where p.name = ?";
// String hql = "from Person p where p.name = :name"; //name随便写
	Query query = session.createQuery(hbl);
	query.setString(0,name);
//	query.setString("name",name);
	persons = query.list();
}

分页技术:
Query
 setFirstResult(int)//开始位置  hibernate 从0开始
 setMaxResults(int)//个数
 setXxx()
 list()
 uniqueResult() //唯一结果
 executeUpdate()

persons = session.createQuery(hql).setFirstResult(3).setMaxResults(4).list();

//通过id 和 sex 更新 sex
public static void updateSexById(Integer id, boolean sex) {
//先查询 后更新(方法一)
Person = session.get(Person.class,id);
person.setSex(true);

//直接更新(方法二)
String hql = "update Person p set p.sex=:sex where id=:id";
session.createQuery(hql).setBoolean("sex", sex).setInteger("id", id).executeUpdate();
}

//通过name 查 person
public static void selectPersonByName(String name) {
//返回一条结果  方法一
String hql = " from Person where name = :name";
p=(Person) session.createQuery(hql)
		.setString("name", name)
		.uniqueResult();
//返回多条
String hql = " from Person where name = :name";
list=session.createQuery(hql)
	.setString("name", name)
	.list();

//返回 id 和  name 结果 是person 对象的
String hql=new StringBuffer()
	.append("select new Person(p.id,p.name) ")
	.append("from Person p ")
	.append("where p.name=:name")
	.toString();
p=(Person) session.createQuery(hql)
		.setString("name", name)
		.uniqueResult();
//返回 id 和 name 的 结果 ---是个objet 对象

String hql=new StringBuffer()
	.append("select p.id,p.name ")
	.append("from Person p ")
	.append("where p.name=:name")
	.toString();
arr=(Object[]) session.createQuery(hql)
		.setString("name", name)
		.uniqueResult();
//模糊查询
String hql = new StringBuffer()
        .append("from Person p ")
        .append("where p.hob like :hob)")
        .toString();

persons = session.createQuery(hql)
             .setString("hob", "%"+hobby+"%")
             .list();


//返回是个Map 对象的 结果
	String hql=new StringBuffer()
		.append("select new Map(p.id as id,p.name as name)")
		.append("from Person p ")
		.append("where p.name=:name")
		.toString();

	map=(Map) session.createQuery(hql)
			.setString("name", name)
			.uniqueResult();
	// List<Person> persons = session.createQuery(hql).list();
}


自动创建表:配置文件中 属性 hbm2ddl.auto 
取值:none【不使用】 create【创建】 update【没有创建,有表更新】

cascade属性设置级联操作
none			不使用
save-update		保存-更新
delete			删除
all			save-update-delete
delete-orphan		删除时,级联删除孤儿
all-delete-orphan	全部级联

关系映射类型:
	多对一
	一对一
	一对多
	多对多
	继承	
	组件

多对一(emp-dept)
Emp.hbm.xml:
<many-to-one name="dept" column="dept_id" class="Dept" fetch="join">
</many-to-one>

test:

String hql=new StringBuffer()
//	.append("select e ")
	.append("from Emp e ")
	.append("left join fetch e.dept d ")
	.toString();

	emps=session.createQuery(hql).list();

关系属性默认有延迟加载
fetch="join" 对于根据主键查询时取消延迟加载【对get load有效】
说明:
默认情况下
多对一情况下
从多方根据id查询一方
关联属性使用了延迟加载
------
fetch="join"
get时,级联抓取关联属性
如果没有配置,关联属性延迟加载
join fetch 解决n+1条sql的问题


一对一(car-engine)
方法一:(
	engine 中	 car_id 作为外键FK 和 唯一 UK
)

car.hbm.xml:
<one-to-one name="engine" class="Engine" fetch="join" cascade="save-update" 
property-ref="car"></one-to-one>

engine.hbm.xml:
<many-to-one name="car" column="car_id" class="Car" fetch="join" unique="true"></many-to-one>

说明:
property-ref="car"  //
unique="true"	// 保证唯一  

test:
session.save(car);

方法二:(engine 中	 id 作为主键PK 和 外键 FK)
car.hbm.xml:
<one-to-one name="engine" class="Engine"
fetch="join" cascade="save-update"></one-to-one>

engine.hbm.xml:
<class name="Engine" table="engine2">
	<id name="id" column="id">
		<generator class="foreign">   // 注意:foreign
			<param name="property">car</param>  // 注意:
		</generator>
	</id>
	<property name="name" column="name"></property>
	<one-to-one name="car" class="Car"
		fetch="join"
		constrained="true"></one-to-one>
</class>

说明:
constrained="true"  //默认没有加约束,实际开发可加可不加,实际开发是有sql脚本的

一对多(order-item)
------------
Order(类)--有个属性是 Set<Item> 
Order.hbm.xml:
<set name="items" inverse="true" cascade="all-delete-orphan">
	<key column="order_id"></key>  //通过 order_id 知道 关联的
	<one-to-many class="Item"/>  //集合中的类型
</set>

Item.hbm.xml:
<many-to-one name="order" column="order_id" class="Order"></many-to-one>

说明:
inverse="true"  //放弃维护权   少了 update 操作
是否放弃关系维护权
默认情况下一对多中关系维护权在一方

说明:一对多情况下从一方抓取多方会有重复对象【bug】
解决方法: .append("select distinct o ") [hibernate3.2版本以后解决了]

3.2版本以前解决方法:
方法一:自己遍历集合去比较
方法二:用set集合
List<Order> orders=session.createQuery(hql).list();
Set<Order> set=new HashSet<Order>(orders);
orders=new ArrayList<Order>(set);




用户:xwq订单号:9
商品一:5 商品名:aaa 商品数量:1 商品单价20.00
商品一:6 商品名:bbb 商品数量:3 商品单价10.00
 总价为;50.00

方法一:
		order = (Order) session.get(Order.class, id);

方法二:
		String hql = new StringBuffer()
										.append("select distinct o") //查出多条结果需要
										.append("from Order o ")
										.append("join fetch o.user ")
										.append("join fetch o.items i ")
										.append("join fetch i.product ")
										.append("where o.id=:id")
										.toString();

映射:
类中有属性 --表中没有(属性--sql语句)  //hibernate 可以进行子查询
<property name="count" formula="(select count(1) from t_item i where i.order_id = id)"></property> // id 默认是当前的表的id

.append("join o.items i ")
.append("where i.product=:product ")//集合中每一个元素的属性

多对多(Student--Course)一般采用  两个多对一的 hibernate 也支持 但一般不用。 
----------
Student.hbm.xml:

<set name="courses" table="t_student_course">
	<key column="s_id"></key>
	<many-to-many class="Course" column="c_id"></many-to-many>
</set>

Course.hbm.xml:
<set name="students" inverse="true" table="t_student_course">
	<key column="c_id"></key>
	<many-to-many class="Student" column="s_id"></many-to-many>
</set>


=========================
继承映射:(User - Manager - Member)
三种方法:

一、一张表:所有属性都放在一张表中,用一个字段做区分
	多态查询效率最高的,但会浪费数据库的空间
	user
		id
		username
		password
		name
		phone
		status me/ma

User.hbm.xml:
class name="User" table="user">
		<id name="id" column="id">
			<generator class="native"></generator>
		</id>
		
		<discriminator column="status" type="string"></discriminator>  //  区分的字段 discriminator 类中没有,数据库中要添加该字段
		
		<property name="username" column="username"></property>
		<property name="password" column="password"></property>
		
		<subclass name="Member" discriminator-value="me">  
			// 子类 subclass
			<property name="name" column="name"></property>
			<property name="phone" column="phone"></property>
		</subclass>
		
		<subclass name="Manager" discriminator-value="ma">
		</subclass>
		
	</class>


二、一个子类一张表:只有子类建表,包装自己的和父类的所有数据
	节省空间,多态查询效率最低,如果不考虑多态查询时,效率最高
	member
		id
		username
		password
		name
		phone

	manager
		id
		username
		password

Member.hbm.xml:
<import class="User"/>  //多态查询,不写,也可以用 不能多态查询
	<class name="Member" table="member3">
		<id name="id" column="id">
			<generator class="native"></generator>
		</id>
		<property name="username" column="username"></property>
		<property name="password" column="password"></property>
		<property name="name" column="name"></property>
		<property name="phone" column="phone"></property>
	</class>

Manager.hbm.xml:
	<import class="User"/> //多态查询用的,不写,也可以用 但是不能多态查询
	<class name="Manager" table="manager3">
		<id name="id" column="id">
			<generator class="native"></generator>
		</id>
		<property name="username" column="username"></property>
		<property name="password" column="password"></property>
	</class>



三、一个类一张表:一个类一张表,用外键做关系
	节省空间,效率最低,不建议使用
	user
		id
		usename
		password
	
	member
		user_id
		name
		phone
	
	manager
		user_id

User.hbm.xml:
<class name="User" table="user2">
		<id name="id" column="id">
			<generator class="native"></generator>
		</id>
		<property name="username" column="username"></property>
		<property name="password" column="password"></property>
		
		<joined-subclass name="Member" table="member2">   
			// id有关联的子类 joined-subclass
			<key column="user_id"></key>
			<property name="name" column="name"></property>
			<property name="phone" column="phone"></property>
		</joined-subclass>
		
		<joined-subclass name="Manager" table="manager2">
			<key column="user_id"></key>
		</joined-subclass>
	
	</class>

------------------------
组件映射
Person
	id
	Name name

Name
	firstName
	lastName
person
	id first_name last_name

Person.hbm.xml:
<hibernate-mapping package="day05">
	<class name="Person" table="person">
		<id name="id" column="id">
			<generator class="native"></generator>
		</id>
		<component name="name" class="Name">  			 
// 组件 component 
			<property name="firstName" column="first_name"></property>
			<property name="lastName" column="last_name"></property>
		</component>
	</class>
	


缓存:
一级缓存:将持久态对象缓存在Session中【查同一个对象,只查一次数据库,一个sql】
二级缓存:将对象缓存在SessionFactory
	 映射文件中<class>加上<cache/> 就添加到二级缓存中,一般不用。

三种 query 方法 
Query	官方文档中文15章
Criteria官方文档中文16章
SQLQuery官方文档中文17章

Query:
----------
<query name="selectAll">   //hql语句 可以写在配置文件中
	<![CDATA[					
		from Person
		where id<:id
	]]>
</query>
<query name="selectByName">
	<![CDATA[
		from Person p
		where p.name.firstName=:firstName
		and p.name.lastName=:lastName
	]]>
</query>

//test类的写法:
	persons=session.getNamedQuery("selectByName")
			.setString("firstName", "aaa")
			.setString("lastName", "bbb")
			.list();
			
Criteria:
功能做条件查询
----------

----------
StringBuffer hql=new StringBuffer()
		.append("from Person p ")
		.append("where 1=1 ");
List params=new ArrayList();
if(p.getName()!=null&&!"".equals(p.getName())){
	hql.append("and p.name=? ");
	params.add(p.getName());
}
if(p.getBirthday()!=null){
	hql.append("and p.birthday=? ");
	params.add(p.getBirthday());
}
if(p.getSex()!=null){
	hql.append("and p.sex=? ");
	params.add(p.getSex());
}
if(p.getHobbies()!=null){
	hql.append("and p.hob=? ");
	params.add(p.getHob());
}
Query query=session.createQuery(hql.toString());
for (int i = 0; i < params.size(); i++) {
	setParam(i,params.get(i),query);
}
			
List<Person> persons=query.list();

private static void setParam(int i, Object param, Query query) {
	if(param instanceof String){
		query.setString(i, (String)param);
	} else if(param instanceof Date){
		query.setDate(i, (Date)param);
	} else {
		query.setParameter(i, param);
}
--------------
List<Person> persons=session.createCriteria(Person.class)
			.add(Restrictions.eq("name", "ooo"))
			.list();

List<Person> persons=session.createCriteria(Person.class)
			.add(Example.create(p))
			.list();

Criteria criteria=session.createCriteria(Person.class);

if(p.getName()!=null&&!"".equals(p.getName())){
	criteria.add(Restrictions.like("name", "%"+p.getName()+"%"));
}

if(p.getSex()!=null){
	criteria.add(Restrictions.eq("sex", p.getSex()));
}

criteria.list();

SQLQuery:
---------------

<sql-query name="s">
	<return alias="p" class="day01.Person"></return>
	<![CDATA[
		select *
		from t_person p
	]]>
</sql-query>

Test中代码:
List list=session.getNamedQuery("s").list();


String sql=new StringBuffer()
	.append("select * ")
	.append("from t_person ")
//	.append("where name=? ")
	.append("where name=:name")
	.toString();
			
List list=session.createSQLQuery(sql)
	 .addEntity(Person.class)
//	 .setString(0, "aaa")
	 .setString("name", "aaa")
	 .setFirstResult(2)
	 .setMaxResults(5)
	 .list();


自动生成Hibernate
右击-MyEclipse-Add Hibernate


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值