hibernate学习【新】

1.hibernate是一个ORM(Object relation mapping 对象关系映射)框架
2.hibernate是对JDBC轻量级的封装,
3.Employee.hbm.xml需要有个dtd文件,可以在源码包中找个类似的文件
4.Employee.hbm.xml 中的id属性用于指定主键属性
 <id>中的 <generator>用于指定主键生成策略hilo native increment sequence等
5.hibernate的设计者给我们提供了数据库的一些常用的配置:
在hibernate-distribution-3.3.1.GA-dist\hibernate-3.3.1.GA\project\etc\hibernate.properties
6.oracle url   jdbc:oracle:thin:@127.0.0.1:1521:orclhsp
7.操作数据库:
   7.1 创建configuration  用来读取配置文件hibernate.cfg.xml
   Configuration configuration = new Configuration().configure();
   7.2 创建SessionFactory  这是一个会话工厂,是一个重量级的类
   SessionFactory sessionFactory = configuration.buildSessionFactory();
   7.3 创建Session [不同于servlet httpsession  ]相当于JDBC中的Connection
   Session session = sessionFactory.openSession();
   //对于hibernate而言,要求程序员在进行增加,删除,修改的时候,使用事物
   Transaction transaction = session.beginTransaction();
   //添加一个雇员
   Employee employee = new Employee();
   employee.setName("铁哥");
   employee.setEmail("12343@213.com");
   employee.setHiredate("new Date()");
   //保存
   session.save(employee);
   transaction.commit();
   session.close();
8.load()方法是通过主键属性,获取该对象实例, 与表的记录对应
Transaction ts = session.beginTransaction();
Employee emp = (Employee)session.load(Employee.class,3);
emp.setName("韩顺平"); //update
ts.commit();
session.close();

9一个domain(或者也叫pojo)需要被序列化,唯一标识该对象 ,同时可以在网络上传输
implement java.io.Serializable

------------------------------------------------------------------------------------------------------------
1.Configuration 类
功能:
①负责管理hibernate的配置信息
②读取hibernate.cfg.xml文件
③加载hibernate.cfg.xml配置文件中配置的驱动,url,用户名,密码等信息
④管理*.hbm.xml对象关系映射文件
Configuration cf = new Configuration().configure();

2.SessionFactory  是一个重量级的类

3.openSession()是获取一个新的session
  getCurrentSession()获取和当前线程绑定的session,在同一个线程中,我们获取是同一个Session,这样可以利于事务的控制

4.如果使用getCurrentSession()需要配置:
在hibernate.cfg.xml文件中配置
<property name="current_session_context_class">thread</property>
  
5.openSession() 和getCurrentSession()的区别:
①采用getCurrentSession()创建的session会绑定到当前线程中,
而采用openSession()创建的session则不会
②采用getCurrentSession()创建的session在啊commit 或者rollback时会自动关闭,
而采用opensession创建的session必须手动关闭
③使用getCurrentSession()需要在hibernate.cfg.xml文件中加入配置:
如果使用的是本地事务(JDBC事务)
<property name="hibernate.current_session_context_class">thread</property>  
如果使用的是全局事务(JTA事务)
<property name="hibernate.current_session_context_class">jta</property>  
  
6.如何查看session是否及时关闭?
在windows下: cmd 打开命令行,netstat -an 查看对应数据库的端口号 是否有很多个
linux/unix  netstat -anp top 
  
7.get() 和 load() 区别
7.1 get()方法直接返回实体类,如果查不到数据,则返回null,
load()会返回一个实体代理对象(当前这个对象可以自动转换为实体对象),但是当代理对象被调用时,如果没有数据,则会
抛出org.hibernate.ObjectNotFoundException异常
7.2 load()先到缓存(session缓存/二级缓存)中查,如果没有则返回一个代理对象(不马上到DB中去找),
等后面使用这个代理对象操作的时候,才到DB中查询,这就是我们常说的load在默认情况下支持延迟加载(lazy加载)
7.3 get()先到缓存(session缓存/二级缓存)中去查,如果没有就马上到DB中去查(即马上发出sql),总之,
如果你确定DB中有这个对象就用load(),不确定就用get()(这样效率更高)
7.4:get() vs load()
    1.如果查不到数据,get会返回null,但是load会报错
2.使用get去查询数据,会立刻向DB发出请求(后台有select语句),如果你使用的load查询数据,
即使查询到对象,返回的是一个代理对象,如果后面没有使用那么不会向数据库发出sql语句,只有当该对象使用了,才会真的向数据库
发送sql语句,即懒加载现象(lazy)
3.通过修改配置文件,可以取消lazy(class里面设置lazy=false)
8.如何配置让load()不适用lazy加载??
在对应的配置文件中配置,或者使用hibernate.initialize();

9 openSession 和getCurrentSession区别
在SessionFactory启动的时候,Hibernate会根据配置创建相应的CurrentSessionContext
在getCurrentSession被调用的时候,实际上执行的是
CurrentSessionContext.currentSession();在currentSession()执行时,
如果当前Session为空,currentSession会调用SessionFactory的openSession

10.使用Query接口进行查询
Query query = session.createQuery("from Employee where id=10");
List<Employee> list = query.list();
for(Employee e :list){
System.out.println(e.getName());
}   

11.使用Criteria接口来查询
Criteria criteria = 
session.createCriteria(Employee.class)
.add(Restrictions.like("name","李%")).addOrder(Order.asc("age"));  
//上面这句话的意思是查询Employee这个对象,name外键约束,查询以李开头的人名,按照age排序
List list =criteria.list();   
  
12.HQL语句
Student s = session.createQuery("from Student where id='20003450'").uniqueResult();  
  这种查询方式相对比较高效,适用于数据库中,该记录只有一条的情况,如果有多条记录,会抛出异常
  
13.部分属性的查询,需要使用到Object数组
List<Object[]> list = session.createQuery("from Student where id='20003450'").uniqueResult();  
for(Oject[] obj :list){
System.out.println(obj[0]);
}

//或者 
Iterator it = list.iterator();
while(it.hasNext()){
Object[] objs = (Object[])it.next();
System.out.println(obj[0].toString());
}

14.如果使用Hibernate查询出的数据只有一列,取出数据不能用对象数组,直接用对象就行
上面的查询需要更改为:
List<Object> list = session.createQuery("from Student where id='20003450'").uniqueResult();  
for(Oject obj :list){
System.out.println(obj.toString());
}

15.hibernate里面的分页算法:
private static void showResultByPage(int pageSize){
int pageNow = 1;
int pageCount = 1; //需要计算
int rowCount = 1; //需要查询
Session session = null;
Transaction tx = null;
try{
session = HibernateUtil.getCurrentSesssion();
tx = session.beginTransaction();
//查出rowCount
rowCount = Integer.parseInt(session.createQuery("select count(*) from Student"));
pageCount = (rowCount - 1)/pageSize + 1;
//循环显示每页信息
for(int i=1;i<pageCount;i++){
System.out.println("第*********"+i+"页**********");
List<Student> list = session.createQuery("from Student")
.setFirstResult((i-1)*pageSize).setMaxResults(pageSize).list();
for(Student s:list){
System.out.println(s.getName()+" "+s.getSdept());
}
}
}
}


16.HQL中的参数绑定:
Query q = session.creatQuery("from Student where sdep=:dept1 and sage>:age1");
List<Student> list = q.setString("dept1","计算机").setString("age1","2").list();
其中:dept1,age1名称可以任意取
或者:
Query q = session.creatQuery("from Student where sdep=? and sage>?");
List<Student> list = q.setString(0,"计算机").setString(1,"2").list();

17.在映射文件中得到hql语句:
可以从映射文件中得到hql语句,执行查询语句,这样可以更加灵活,在某些情况下,可以考虑使用:
比如在:Student.hbm.xml中
<query name="myquerytest">
<![CDATA[select sanme,ssex from Student where sage>22]]>
</query>
使用:
List list = session.getNamedQuery("myquerytest").list();
System.out.println(list.size());
Iterator it = list.itrator();
while(it.hasNext()){
Object obj[] = (Object[])it.next();
System.out.println("n="+obj[0]);
}

18.hibernate对象的三种关系:
one-to-one 如身份证<---> 人
one-to-many  部门 <---> 员工
many-to-one  员工<--->部门
many-to-many  学生 <---> 课程
一般多对多都转换为一对多和多对一的关系
具体见hibernate视频第19讲!
18.1 one-to-one 
18.2 one-to-many [many-to-one]
18.3 many-to-many

19: domain对象细节
   19.1 需要一个无参数的构造方法(用于hibernate反射该对象)
   19.2 应该有一个无业务逻辑的主键属性
   19.3 给每个属性提供set get 方法
   19.4 hibernate的映射是根据xx.hbm.xml文件映射,而不是domain类

20:hibernate对象的3种状态
20.1 瞬时态(transient) 数据库中没有数据与之对应,超过作用域会被JVM垃圾回收器回收,
一般是new出来的对象且与session没有关联的对象
20.2 持久态(persistent) 数据库中有数据与之对应,当前与session有关联,并且相关联的session没有关闭,
事务没有提交,持久态对象状态发生改变,在事务提交时会影响到数据库(hibernate能够检测到)
20.3 脱管态/游离态(detached) 数据库中有数据与之对应,但是当前没有session与之关联,
托管对象状态发生改变,hibernate不能够检测到
注意:判断一个对象的状态,①是否处于session的管理 ②是否在数据库中有对应的记录

懒加载:当查询一个对象的时候,默认情况下,返回的只是该对象的普通属性,

当用户区使用对象属性的时候,才会向数据库发出再一次的查询,这种现象称为lazy加载


21 解决懒加载的办法:一般一个类中有其他类的对象作为成员属性的时候,就有可能出现懒加载的情况
 21.1 Hibernate.initialize(使用代理对象)
Hibernate.initialize(student.getDept());
 21.2 在配置文件中禁用懒加载  即设置lazy=false
 21.3 通过过滤器解决  openSessionInView

22.一对多one-to-many
如:通过一个部门号,来查询该部门的所有学生?
可以使用 from Student where dept.id=1;
也可以使用one-to-many
在Department类中,添加属性:
private Set<Student> stud;   //也可以是list 集合
修改对应的对象关系映射文件,添加:
<set>
<key>
<ont-to-many/>
</set>

23.一对一 one-to-one 有2中方式
23.1 基于主键的一对一
23.2 基于外键的一对一

24.hibernate中懒加载加强
一级缓存:session级缓存
二级缓存:sessionFactory级缓存
①什么操作会向一级缓存放入数据:
save ,update ,saveOrUpdate,load,get,list,iterate,lock
比如save();list是Query的list结果
//添加一个学生
Student student = new Student();
student.setName("小米");
session.save(stduent);
//然后马上去查询
Student stu2 = (Student)s.get(Student.class,student.getId());
System.out.println("你刚刚加入的学生是:"+stu2.getName());
transaction.commit();
在后台可以看出,会先打出:你刚刚加入的学生是:小米
然后是Hibernate的插入语句:Hibernate:inser into Student(XXX)
可以这样理解:在save()的时候,hibernate会把student放入到一级缓存中,在下面马上去查询的时候,
是直接从session中去查,然后在使用transaction.commit()的时候,才向数据库中插入数据

②什么操作会从一级缓存中取数据?
get,load会从一级缓存去取,但是Query查询如list uniqueResult不会从一级缓存中取数据
注意:list会往一级缓存中放数据,但是不会从一级缓存中取数据
③ 一级缓存不需要配置,可以直接使用,本身没有保护机制,所以开发的时候需要考虑这个问题
注意:一级缓存不能控制缓存的数量,所以要注意大批量操作数据的时候,可能会造成内存的
溢出,可以用evict,clear方法清除缓存中的内容
evict():如session.evict(student);这句话可以显式的从session中移除student
clean():用于清除session中的所以缓存
④session级缓存中的对象的生命周期,当session关闭后就自动销毁
注意:可以使用HashMap来模拟一个session缓存,加深对缓存的理解

25:为什么需要二级缓存?
因为一级缓存是有限的,而且生命周期较短,所以需要二级缓存弥补这个问题。
25.1 二级缓存需要配置
25.2 二级缓存一般交给了第三方框架去管理,常见的有Hashtable,OSCache,EHCache
25.3 二级缓存的原理:
二级缓存的对象可能放在内存,也可能放在磁盘上

26.主键增长策略
①increment
自增,是hibernate提供的,每次增长1,适用于所有数据库,但是不要用在多进程下,
只有主键是long,int等数值型的才能使用
select max(id) from student
②identity
由底层数据库生成标识符,
前提条件:数据库支持自增字段类型(如sqlserver,mysql,注意:oracle不行),
而且OID(object identity 对象标识符)必须为数值类型,如long,int,short等
③sequence
依赖于底层数据库系统的序列
前提条件:需要数据库支持序列机制(如oracle),而且OID必须是数值类型,比如long,int,short等
配置文件:
<id name="id" type="java.lang.Long" column="id">
<generator class="sequence">
<param name="sequence">my_seq</param>
</generator>
</id>
④ native
native生成器能够根据底层数据库系统的类型,自动选择合适的标识符生成器,因此非常适用于跨数据库平台的开发,
他会由hibernate根据数据库适配器中的定义,自动采用identity,hilo,sequence的其中一种作为主键生成方式,
但是OID必须为数值类型(如:long,short,int等)
如果以前的配置不是native,但是是数值型的,当修改为native后,不同数据库的实现机制会有差异
如对于oracle:select hibernate_sequence.nextval from dual
⑤hilo 高底位
hilo标识符生成器由hibernate按照一种high/low算法生成标识符,他从数据库中的特定表的字段中获取high值,
因此需要额外的数据库表保存主键生成的历史状态,hilo生成方法不依赖与底层数据库,因此
适用于每一种数据库,但是OID必须是数值型(long int short等类型)
<id name="id" type="java.lang.Integer" column="id">
<generator class="hilo">
<param name="table">my_hi_value</param>
<param name="column">next_value</param>
</generator>
</id>
这样配置后,会自动在数据库中创建一个my_hi_value的表,其中的字段是next_value
⑥ uuid
由hibernate基于128位(128bit)唯一值产生算法,根据当前设备的IP,时间,JVM启动时间
,内部自增量等4个参数生成16进制数值作为主键,一般而言,利用uuid方式生成的主键
提供最好的数据插入性能和数据库平台适应性。OID一般使用String类型,不能是数值
<id name="id" type="java.lang.String" column="id">
<generator class="uuid"></generator>
</id>
⑦assigned
采用assigned生成策略表示由应用程序逻辑负责生成主键标识符,OID类型没有限制
<id name="id" type="java.lang.Integer" column="id">
<generator class="assigned"></generator>
</id>
⑧ 映射复合主键 尽量不要使用,比较复杂,效率相对较低,数据不稳定
⑨foreign
在one-to-one的关系中,由另一张表的主键充当外键


数据库设计时,参考主键生成策略的原则:
对于oracle:如果主键是数值型的(int,long等),建议使用sequence;如果主键是string建议使用uuid或者assigned
对于mysql:如果主键是数值型的(int,long等),建议使用increment或者assigned;如果是string,建议用uuid火assigned
对于sqlserver:如果主键是数值型的(int,long等),建议适应identity,或者native,assigned;如果是string,建议用uuid,assigned
如果是基于主键的one-to-one,建议使用foreign

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值