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
Hibernate培训笔记
最新推荐文章于 2018-09-10 21:38:41 发布