初学Hibernate,阅读了有关书籍,做了如下笔记和思考心得。
第一部分:Hibernate 工作原理
首先我们使用MyEclipse 6.5开发环境,我们可以使用其添加Hibernate框架的能力,自动导入那些需要使用的包。并且自动创建
Hibernate配置文件以及HibernateSessionFactory
一、构建Configuration实例,初始化该实例中的所有变量
private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";
private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
private static Configuration configuration = new Configuration();
private static org.hibernate.SessionFactory sessionFactory;
private static String configFile = CONFIG_FILE_LOCATION;
二、加载hibernate.cfg.xml文件至该实例(内存)
通过hibernate.cfg.xml 文件中的mapping节点配置并加载hbm.xml 文件至该实例(内存)
configuration.configure(configFile);
三、利用上面创建的Configuration实例构建一个SessionFactory实例
sessionFactory = configuration.buildSessionFactory();
注:前三步在HibernateSessionFactory中已经配置好了,下面就在相应的类中完成数据库操作
四、由上面得到的SessionFactory实例创建连接
session = (sessionFactory != null) ? sessionFactory.openSession(): null;//这个是在MySessionFactory中
Session session = MySessionFactory.getSession();//这个是在类似MemberDAOImpl的类中
五、由连接实例创建事物操作接口Transaction的一个实例
Transaction ts = session.beginTransaction();
六、通过session接口提供的各种方法操作对数据库的访问
比如:保存某用户到数据库中
session.save(user);
七、提交数据库的操作结果
tx.commit()
八、关闭session连接
MySessionFactory.closeSession();
第二部分:
操作持久化对象的常用方法介绍
一、常用方法
1.使用Session的beginTransaction()方法:开辟一个事务管理单元,对业务代码进行事务管理。有三个部分
Session session = MySessionFactory.currentSession();//或者为MySession.getSession();
Transaction ts = null;
try{
ts = session.beginTransaction();
//业务代码
ts.commit();
}catch(Exception ex){
if(ts!=null)ts.rollback();
ex.printStackTrace();
}
finally{
MySessionFactory.closeSession();
}
2、使用Session的connection()方法
该方法用于取得当前Session实例的JDBC连接,在得到了JDBC连接后就可以绕开Hibernate直接使用JDBC API来访问数据库。
Session session = MySessionFactory.currentSession();
Transaction ts = null;
try{
Connection conn = session.connection();
Statement stat = conn.creatStatement();
String sql = "select * from orders";
ts = session.beginTransaction();
ResultSet rs = stat.executeQuery(sql);
while(rs.next){
System.out.println(rs.getString(1)+"\t"+rs.getString(2));
}
ts.commit();
}
3.使用Session的delete方法
删除数据库中指定对象obj所对应的记录。
4.使用Session的get(Class entityClass,Serializable id)方法。用于从数据库中加载指定的持久化对象到Session缓存中,如果指定的记录不存在则返回null.
Item item = (Items)session.get(Items.class,id);
5.使用session的load方法,从数据库中加载指定的持久化对象到Session缓存。不同于get方法在于,如果指定方法不在就抛出异常。
6.Session的save()方法,用于将一个临时对象加载到Session缓存中,使临时对象转换成持久对象,当session缓存被清理时,向数据库发送一条insert语句,在数据库中新增一条与该持久化对象相应的记录。
session.save(item);
7.Session的update对象。将一个处于脱管状态的游离对象加载到Session缓存中,与一个具体的Session实例关联。使其成为持久化对象,当session缓存被清理时,向数据库发送一条update语句,在数据库中更新与该持久化对象相应的记录。
session.update(item);
8.如果我们不知道指定对象的状态时,就使用saveOrUpdate()方法。
9.Hibernate的isInitialized()与initialize()方法。
非延迟加载在读取一个对象的时候会将与这个对象所有相关的其他对象一起读取出来。
Hibernate提供的延迟加载机制。这种初始化策略只在一个对象调用它的一对多或多对多关系时才将关系对象读取出来。也就是说延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作,只有我们用它的时候才把它加载到数据库中来。
这个过程对开发者来说是透明的,而且只进行了很少的数据库操作请求,因此会得到比较明显的性能提升。这项技术的一个缺陷是延迟加载技术要求一个Hibernate会话要在对象使用的时候一直开着。
所以,我们为了确保集合中的元素被正常访问,就是用如下的方式:
if(!Hibernate.isInitialized(item.getOrders())){
Hibernate.initialize(item.getOrders());
}
具体每个方法的操作过程可以参见
http://sishuok.com/forum/blogPost/list/2483.html
二、级联操作
什么是级联操作:从任何一个对象出发,去寻找并操作与之关联的对象的过程称为级联操作。
三、检索策略(加载策略)
1.立即检索:如果要启用立即检索策略的话,就必须手动将Lazy设置为false。
2.延迟检索:Hibernate的默认检索策略是延迟检索(加载),所以我们要先判断其是否初始化。
这里要注意:对于类级别我们要使用立即检索,对于关联级别我们要使用延迟检索,类级别立即检索就是立即加载检索方法制定的
对象。而关联级别延迟检索就是延迟加载检索方法指定的关联对象。
具体可参见
http://hi.baidu.com/%C7%E5%D0%C4%B5%C2%B8%A3/blog/item/f9c863062bf04fc57b894793.html
3.左外连接(左边的关系表无论有没有匹配都显示出来):只适用于关联级别,
四、HQL查询方式:Hibernate Query Language
具体HQL介绍,可参加
baike.baidu.com/view/1257019.htm
1.基本查询:HQL查询方式首先得创建一个Query对象。
Query query = session.createQuery();
Iterator it = query.list().iterator();
Query query = session.createQuery("from Orders as a order by a.money desc");
query.setMaxResults(1);//设置最大检索数目为1
Orders orders = (Orders)query.uniqueResult();//装载单个对象
2.条件查询:
Query query = session.createQuery("from Customer as a Where a.cname =:p1");//这里:p1是参数名
query.setString("p1","张三");//为参数p1指定参数值。
query.setMaxResults(1);
Customer customer = (Customer)query.uniqueResult();
3.分页查询
使用这两个方法setFirstResult(int firstResult)//指定从哪个对象开始检索(序号从0开始)
setMaxResults(int maxResults)//一次最多检索的数目对象。
具体代码如下:
Query query = session.createQuery("from Orders as a");
int pageSize = 15;//每页的记录条数
int pageNo =1 ;//当前页号,即第几页
query.setFirstResult((pageNo-1)*pageSize);//指定从哪一个对象还是检索
query.setMaxResult(pageSize);//指定一次最多检索出的对象数目
Iterator it = query.list().iterator();//查询我们需要的那页。
4.连接查询
比如:
Query query = session.createQuery("from Customer as a inner join a.orders as b");//内连接,这里我们要注意,我们
不需要输入where Customer.ID = Orders.Customer_ID;,因为在Customer的映射文件中存在
<set name="orders"
cascade="all"
lazy="true"
inverse="true">
<key column="CUSTOMER_ID" />
<one-to-many class="com.ORM.Orders" />
</set>
它指定了外键CUSTOMER_ID,而存在该默认的连接,我们不需要再输入where这一句。
Query query = session.createQuery("from Customer as a left join a.orders as b");//左外连接
Query query = session.createQuery("from Customer as a right join a.orders as b");//右外连接
Query query = session.createQuery("from Customer as a, Orders as b");//交叉连接,内连接。逗号可以理解为交叉连接
5.子查询(一定要确定底层支持子查询):
相关子查询:子查询需要用到外层查询中的对象。
无关子查询:子查询和外层查询无关。
这里我们复习下in,exists的两种用法,in代表着外层查询是否出现在子查询返回的所有记录中。而exists代表子查询是否至少返回一条记录。
6.动态实例化查询结果
为了提高检索效率,只需要检索对象的部分属性,然后将检索出来的属性封装成自定义的类对象,这个过程就叫动态实例化查询结
果。
package com.bean
public class MyReport{
private String cname;
private String bank;
private String orderno;
private Double money;
public MyReport(String cname ,String bank,String orderno,Double money){
cname = this.cname;
bank = this.bank;
orderno = this.orderno;
money = this.money;
}
//省略了set和get方法
}
Session session = MySessionFactory.currentSession();
Transaction ts = session.beginTransaction();
Query query = session.createQuery("select new com.bean.MyReport(a.cname,a.bank,b.orderno,b.money)from Customer
as a inner join a.orders as b");
Iterator it =query().list().iterator();
ts.commit();
MySessionFactory.closeSession();
MyReport report = null;
while(it.hasNext()){
report = (MyReport)it.next();
System.out.println("顾客姓名:"+report.getCname());
System.out.println("银行账号:"+report.getBank());
System.out.println("订单编号:"+report.getOrderno());
System.out.println("订单金额:"+report.getMoney());
}