《2022年hibernate学习笔记 .pdf》由会员分享,可在线阅读,更多相关《2022年hibernate学习笔记 .pdf(19页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、Domain object 限制:1 Domain 对象必须有一个不带参数的构造方法(必须的)因为 hibernate 创建对象的时候是调用的Newinstance 方法,这个方法必须有不带参数的构造方法。2 有无意义的标识符id(主键)(可选)3 非 final 的,对懒加载有影响(可选)配置实体表时,如果和数据库冲突,表名可以另起或者加上User 反引号( 1 左边那个键)注意:如果表已经创建,再去配置表的属性,不会对表属性有影响,所以一开始就要把表的约束性条件,字段设置好。1.domain.hbm.xml 的配置 /domain对象所处的包 /name是类名, table是数据库中对应的
2、表名 /id表示的是主键,name 是属性名, column是字段 /class表示的是主键默认值 此字段唯一 unique /缺省的 column的名字和属性名相同2.session的主要方法1.save,persist 保存数据, persist 在事务外不会产生insert 语句2.delete 删除对象3.update,更新对象,如果数据库中没有记录,会出现异常4.get,根据 id 查,会立刻访问数据库5.load,根据 id 查(返回的是代理,不会立即访问数据库)懒加载6SaveOrUpdate,merge(根据 id 和 version 的值来确定是save或 update)调用
3、 merge 你的对象还是脱管的7.lock(把对象变成持久对象,但不会同步对象的状态)3.实体对象的三种状态1.Transient(瞬时的)数据库中没有数据与之对应,超过作用域会被JVM 垃圾回收器回收,一般是new 出来且与 session没有关联的对象2.Persistent(持久的)数据库中有数据与之对象,当前与session有关联,并且相关联的session 没有关闭,事务没有提交;持久对象状态发生变化,在事务提交时,会影响到数据库(hibernate 能检测到)3.Detached(脱管的)数据库中有数据与之对应,但当前没有session与之关联,托管对象状态发生改变,hibern
4、ate 不能检测到。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 19 页 - - - - - - - - - 4.实现复杂的查询HQL(Hibernate Query Language) 面向对象的查询语言,与SQL 不同, HQL 中的对象名是区分大小写的(除了JAVA 类和属性其他部分不区分大小写);HQL 中查的是对象而不是和表,并且支持多态;HQL 主要通过 Query 来操作, Query 的创建方式:Query q = session.createQuer
5、y(hql); from Person from User user where user.name=:name from User user where user.name=:name and user.birthday :birthday Criteria Criteria 是一种比 HQL 更面向对象的查询方式;Criteria 的创建方式:Criteria crit = session.createCriteria(DomainClass.class); 简单属性条件如:criteria.add(Restrictions.eq(propertyName, value), criteri
6、a.add(Restrictions.eqProperty(propertyName,otherPropertyName) staticvoid query(String name) Session session=null; try session=HibernateUtil.getSession(); / String hql=from User as user where user.name=?;/ Query que=session.createQuery(hql);/ que.setString(0, name);/* * 运用别名的方式设置参数 */String hql=from
7、User as user where user.name=:n; Query que=session.createQuery(hql); que.setString(n, name); que.setFirstResult(0); /实现分页查询设置起始记录的位置名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 19 页 - - - - - - - - - que.setMaxResults(2); /设置最多的记录数List user=que.list(); for(Us
8、er u: user) System.out .println(u.getBirthday(); / User us=(User)que.uniqueResult();/当查询的结果只有一个对象的时候可以用这个方法。/ System.out.println(us.getBirthday(); catch(HibernateException e) e.printStackTrace(); throw e; finally if(session!=null) session.close(); /* * 使用 criteria接口来查询 * 所拥有的方法和HQL基本相同 * param name
9、*/staticvoid criteria(String name) Session s=null; try s=HibernateUtil.getSession(); Criteria ca=s.createCriteria(User.class); ca.add(Restrictions.eq ( name, name); ca.add(Restrictions.le ( birthday, new Date(); List user=ca.list(); for(User u: user) System.out .println(u.getBirthday(); catch(Hibern
10、ateException e) throw e; 5.实体对象关联关系注意:多对一和一对多的关系都必须对其进行初始化不然将得到的是空值,因为用到了懒加载初始化过程:Hibernate.initialize(emp.getDepart(); /对多对一关系进行初始化Hibernate.initialize(depart.getEmp(); /对一对多关系进行初始化注意:1.多对一的关系映射Employee-Department 的关系映射多个员工有可能对应的是一个部门Employee 实体类名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - -
11、- - 名师精心整理 - - - - - - - 第 3 页,共 19 页 - - - - - - - - - publicclass Employee privateintid ; private String name ; private Department depart; public Employee() Employee 实体映射文件的配置 /unique设置字段的唯一性/多对一的配置 name是实体类中的属性名,column是外键的列名 在类中的使用/* * 增加一个部门和一个该部门的员工。 * return */static Employee add() Session s=n
12、ull; Transaction tx=null; try s=HibernateUtil.getSession(); tx=s.beginTransaction(); Department depart=new Department(); depart.setName(new depatr1); Employee emp=new Employee(); emp.setDepart(depart); emp.setName(new Employee1); s .save(depart); /如果先保存员工,再保存部门,那么depart_id就会是默认空值,然后 hibernate会执行一条更新
13、语句,将id 加上去s.save(emp); / / 如果 depart_id设置了 not-null,那么这两个的顺序就不能换,不然就会报错。mit(); return emp; catch(HibernateException e) if(tx!=null) tx.rollback(); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页,共 19 页 - - - - - - - - - throw e; finally if(s!=null) s.close(); /* *
14、 根据员工 id 查询员工信息 * param id * return */static Employee getEmp(int id) Session s=null; try s=HibernateUtil.getSession(); Employee emp=(Employee)s.get(Employee.class, id); Hibernate.initialize(emp.getDepart(); /此处是懒加载,必须初始化一下return emp; catch(HibernateException e) throw e; finally if(s!=null) s.close()
15、; 2.一对多的关系映射Department-Employee 的关系映射一个部门有多个员工Department 实体类publicclass Department privateintid ; private String name ; private Set emp; public Department() Department 实体映射文件的配置 /实体类中的属性 /对应多类中的外键id /对应多的类名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 5 页,共 19 页 - -
16、- - - - - - - 在类中的使用/* * 根据 id 获取部门 * param id * return */static Department getDepart(int id) Session s=null; try s=HibernateUtil.getSession(); /获取实体对象Department depart=(Department)s.get(Department.class, id); Hibernate.initialize(depart.getEmp(); /此处懒加载, 对set 集合进行初始化return depart; catch(HibernateEx
17、ception e) throw e; finally if(s!=null) s.close(); 3.一对一的关系映射Person-IdCard 的关系映射一个人只有一个身份证Person 实体类publicclass Person privateintid ; private String name ; private IdCard idCard; public Person() IdCard 实体类publicclass IdCard privateintid ; private Date usefulDate; private Person person; public IdCard
18、() 实体映射文件的配置Person 实体名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 6 页,共 19 页 - - - - - - - - - Idcard 实体person /constrained建立外键约束 在类中的使用/* * 增加一个人及其他的身份证 * * 一对一的关系映射 * return */static Person addOneToOne() Session s=null; Transaction tx=null; try s=HibernateUtil.ge
19、tSession(); tx=s.beginTransaction(); IdCard idCard=new IdCard(); idCard.setUsefulDate(new Date(); Person person=new Person(); person.setName(p2); person.setIdCard(idCard); idCard.setPerson(person); s.save(person); s.save(idCard); mit(); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理
20、 - - - - - - - 第 7 页,共 19 页 - - - - - - - - - return person; catch(HibernateException e) if(tx!=null) tx.rollback(); throw e; finally if(s!=null) s.close(); 4.多对多的关系映射Student-Teacher 的关系映射一个学生可以有多个老师教,一个老师也可以教多个学生Student 实体类publicclass Student privateintid ; private String name ; private Set teacher
21、s; public Student() Teacher 实体类publicclass Teacher privateintid ; private String name ; private Set students; public Teacher() 实体映射文件的配置Student 实体Teacher 实体名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 8 页,共 19 页 - - - - - - - - - 在类中的使用/* * 增加两个老师和两个学生 * 一个学生两个老师教
22、* 一个老师教两个学生 * return老师 */static Teacher addTeacher() Session s=null; Transaction tx=null; try s=HibernateUtil.getSession(); tx=s.beginTransaction(); Set ss=new HashSet(); Set st=new HashSet(); Teacher t1=new Teacher(); t1.setName(t1); st.add(t1); Teacher t2=new Teacher(); t2.setName(t2); st.add(t2);
23、 Student s1=new Student(); s1.setName(s1); ss.add(s1); Student s2=new Student(); s2.setName(s2); ss.add(s2); s.save(s1); s.save(s2); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 9 页,共 19 页 - - - - - - - - - s.save(t1); s.save(t2); t1.setStudents(ss); t2.setStudents
24、(ss); /s2.setTeachers(st);mit(); return t1; catch(HibernateException e) if(tx!=null) tx.rollback(); throw e; finally if(s!=null) s.close(); /* * 根据 id 查询得到一个学生 * 并返回了教这个学生的老师 * param id * return学生 */static Student getStudent(int id) Session s=null; try s=HibernateUtil.getSession(); Student st=(Stude
25、nt)s.get(Student.class, id); Hibernate.initialize(st.getTeachers(); return st; catch(HibernateException e) throw e ; finally if(s!=null) s.close(); 注意:如果需要将两个实体放入一个表,那么就用组件关系映射否则就用一对一或者多对一的关系映射5.组件关联关系映射User-Name 的关系映射这种关系适应于两个对象放入一个表中的情况一个用户的名字,可以由两部分组成,需要放入一个表中User 实体类名师资料总结 - - -精品资料欢迎下载 - - - -
26、- - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 10 页,共 19 页 - - - - - - - - - publicclass User privateintid ; private Name name ; private Date birthday; public User()Name 实体类publicclass Name private String firstName; private String lastName; public Name()实体映射文件的配置User 实体 在类中的使用/* * 增加一个用户,并设置他的名字
27、组合 * param args */publicstaticvoid main(String args) UserDao dao=new UserDaoHibernateImpl(); User user=new User(); user.setBirthday(new Date(); Name n= new Name(); n.setFirstName(MyFristName); n.setLastName(MyLastName); user.setName(n); dao.addUser(user); System.out .println(user); . 名师资料总结 - - -精品资
28、料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 11 页,共 19 页 - - - - - - - - - 6.hibernate中使用的集合类型List 是有序的 Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(元素在List 中的位置,类似于数组下标)来访问List 中的元素,这类似于Java 的数组。和下面要提到的Set 不同, List 允许有相同的元素。除了用 set还可以用 list 在 xml 中的配置 /这个为了标识顺序如果不需要区分顺序,可以这样配置 Map
29、注意:在运用集合类的时候,不要用到具体的类。一定要定义成接口,不然就会报错。如: set ,就不要定义为hashset,因为 hibernate重写了集合类,会将你定义的类转换成他定义的类,所以如果是具体的类,就不能进行这个强制转换了。集合映射:级联Cascade 用来说明当对主对象进行某种操作时是否对其关联的从对象也作类似的操作,常用的cascade:none,all,save-update ,delete,lock,refresh,evict,replicate,persist,merge,delete-orphan(one-to-many) 。一般对many-to-one,many-to
30、-many不设置级联,在 和中设置级联名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 12 页,共 19 页 - - - - - - - - - inverse表“ 是否放弃维护关联关系 ” ( 在Java 里两个对象产生关联时, 对数据库表的影响 ) ,在one-to-many和many-to-many的集合定义中使用,inverse=” true” 表示该对象不维护关联关系; 该属性的值一般在使用有序集合时设置成 false(注意 hibernate的缺省值是 false) 注意
31、:一般设置inverse关系是设置一这端的关系,让一这端放弃对关系的维护,增加效率如果先保存一,再保存多,就会要少两条更新的语句,会要加快速率。注:不能在有序集合里使用inverse=true,如: list,array 因为有序集合如果放弃了对关系的维护,就没有那有序的字段了。注意: cascade和inverse只能在集合里面才可以配置7.继承父类实体映射文件配置: !- 1. 鉴别器:这里用到的是鉴别器,在表中增加一个字段type,用于 hibernate区分是哪一个子类这种方法是一张表中存在整个继承树,这种方法的缺点是会在关系模型中增加子类特有的属性字段,这样就会造成很多NULL 的字
32、段。这对关系模型的设计不是很合理的。如果子类的特有属性越多,那么存在的NULL 字段也就会越多。所以这种方法适应于子类的特有属性较少的情况-!- 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 13 页,共 19 页 - - - - - - - - - 这里是对子类的配置,property是配置子类特有的属性 - /这个是主外键,就是父类表的id /这个是子类特有的属性 2. 内连接,联合查询:这种方法是每增加一个子类就会增加一张表,子类的特有属性就会放入这张表中,公共属性放入父类表
33、表的主外键就是父类表的id 。这种设计就不会出现NULL字段的情况,符合关系模型的设计。但在进行查询的时候,就会出现效率问题,因为他至少要查询两张表,所以这种情况适用于子类的特有属性较多的情况。使用:Employee emp = (Employee) s.get(Skiller.class, id); 如果 Skiller.class改为了 Employee.class,那么在查询的时候,父类有几个子类就会对几张表进行联合查询,这就会有很大的效率问题。所以在查询的时候,一定要注明是哪个子类。而上面的那种方法就不会出现这种问题,因为他不管怎么的,都是进行单表查询,在效率上会有很大的优势 3. 鉴
34、别器与内连接结合: 4. 每个具体类映射一张独立表名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 14 页,共 19 页 - - - - - - - - - 每张表中存放的是具体类的所有信息/如果设置为 true将不会有 Employee这张表 /主键生成器必须设置成这种类型的因为如果是原来那种,当用id 查询的时候,就会出现一个id 对应了多张表的多个人会出现 id 重复的现象 6.懒加载通过 asm和 cglib 二个包实现; Domain 是非 final 的。1.sessio
35、n.load懒加载。2.one-to-one(元素)懒加载:必需同时满足下面三个条件时才能实现懒加载(主表不能有 constrained=true,所以主表没有懒加载) lazy!=false 2)constrained=true 3)fetch=select 3.one-to-many (元素)懒加载: 1)lazy!=false 2)fetch=select 4.many-to-one (元素) :1)lazy!=false 2)fetch=select 5.many-to-many (元素) :1)lazy!=false 2)fetch=select 6.能够懒加载的对象都是被改写过的代
36、理对象,当相关联的session没有关闭时,访问这些懒加载对象(代理对象)的属性(getId 和 getClass除外) hibernate会初始化这些代理,或用Hibernate.initialize(proxy) 来初始化代理对象;当相关联的 session关闭后,再访问懒加载的对象将出现异常。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 15 页,共 19 页 - - - - - - - - - Lazy 有三个值: false,propxy(缺省,代理方式) ,no-pro
37、pxy 是否使用懒加载和使用懒加载的方式Fetch:join,select(缺省)查询的方式Join 会破坏懒加载,在进行查询的时候就会直接进行联合查询,将关联的对象也一并查出来而 select会进行懒加载,当加载时,会另起一条select语句7缓存一级缓存: session / s.evict(emp); 清除一个对象的缓存/ s.clear(); 清除所有的缓存二级缓存 SessionFactory级共享:1.Session的:save(这个方法不适合 native 生成方式的主键 ), update,saveOrUpdate,list,iterator,get,load, 以及 Quer
38、y,Criteria 都会填充二级缓存2.SessionFactory中提供了 evictXXX() 方法用来清除缓存中的内容。在 hibernate.cfg.xml 中的配置:true /获取统计信息true /是否使用二级缓存org.hibernate.cache.OSCacheProvider /使用的第三方二级缓存 /使用缓存的类的配置usage的值: read-only(只读,不会对表进行修改)、read-write(可以读和写,也考虑了并发操作)、nonstrict-read-write(可以读和写,但不会考虑并发操作,用于不用很精确的数据)、transactional Stati
39、stics s= HibernateUtil.getSessionFactory().getStatistics(); /获取统计信息名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 16 页,共 19 页 - - - - - - - - - System.out .println(hit:+s.getSecondLevelCacheHitCount(); System.out .println(miss:+s.getSecondLevelCacheMissCount(); Syste
40、m.out .println(put+s.getSecondLevelCachePutCount(); 使用缓存的条件1. 读取大于修改。2. 数据量不能超过内存容量。3. 对数据要有独享的控制。4. 可以容忍出现无效数据。session context和事务边界用 current_session_context_class属性来定义context (用 sessionFactory.getCurrentSession()来获得 session),其值为:1.thread:ThreadLocal来管理 Session实现多个操作共享一个Session,避免反复获取Session,并控制事务边界
41、,此时session不能调用close当 commit或 rollback的时候 session会自动关闭(connection.release_mode:after_transaction)。Open session in view:在生成(渲染)页面时保持session打开。用 ThreadLocal来获取 session /* * 使用线程实现同一个session的事务边界处理 * * 实现多个操作共享一个Session * * 使用的时候,写一个继承Tomcat容器 Filter的类,在 doFilter方法中,获取这个session,并开启事务。然后调用业务逻辑层,最后实现 * 事务
42、的提交和session的关闭。这样就保证了业务逻辑层和数据访问层代码的隔离。不会产生依赖关联。 * return */publicstatic Session getThradLocalSession() Session s=(Session)session.get(); if(s= null) s= getSession(); session.set(s); return s; /* * 对线程 session进行关闭 */publicstaticvoid closeThreadLocalSession() Session s=(Session)session.get(); if(s!=nu
43、ll) s.close(); session.set(null); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 17 页,共 19 页 - - - - - - - - - 2.jta:由 JTA 事务管理器来管理事务(connection.release_mode:after_statement)。数据类型 1. type可以是 hibernate、java类型或者你自己的类型( 需要实现hibernate的一个接口 ) 。2. 基本类型一般不需要在映射文件(hbm.xml)中说
44、明, 只有在一个JAVA 类型和多个数据库数据类型相对应时并且你想要的和hibernate缺省映射不一致时,需要在映射文件中指明类型( 如:java.util.Date,数据库DATE,TIME,DATATIME,TIMESTAMP,hibernate缺省会把java.util.Date映射成 DATATIME 型,而如果你想映射成 TIME ,则你必须在映射文件中指定类型) 。3. 数据类型的对应关系见参考文档5.2.2 Session是非线程安全的,生命周期较短, 代表一个和数据库的连接,在 B/S 系统中一般不会超过一个请求内部维护一级缓存和数据库连接,如果session长时间打开,会长
45、时间占用内存和数据库连接。SessionFactory是线程安全的,一个数据库对应一个SessionFactory,生命周期长,一般在整个系统生命周期内有效;SessionFactory保存着和数据库连接的相关信息(user ,password,url)和映射信息,以及Hibernate运行时要用到的一些信息。s.flush(); /让一级缓存与数据库同步,会访问数据库s.clear(); /清空一级缓存,不会保存一级缓存里的数据,不会访问数据库离线查询:/* * 离线查询可以随意的变换查询的条件 * * param d * return */static List dc(DetachedCr
46、iteria d) Session s = HibernateUtil.getSession(); Criteria c = d.getExecutableCriteria(s); List lt = c.list(); s.close(); / 在实际中的调用/ DetachedCriteria deta=DetachedCriteria.forClass(User.class);/ String name=;/ int age=0;/ if(name!=null)/ deta.add(Restrictions.eq(name, name);/ if(age!=0)/ deta.add(Re
47、strictions.eq(age, age);/ dc(deta);/return lt; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 18 页,共 19 页 - - - - - - - - - 事件监听/当保存的时候,就会触发该事件。publicclass TestListenner implements SaveOrUpdateEventListener /* (non-Javadoc) * see org.hibernate.event.SaveOrUpdateEvent
48、Listener#onSaveOrUpdate(org.hibernate.event.SaveOrUpdateEvent) */Overridepublicvoid onSaveOrUpdate(SaveOrUpdateEvent event) throws HibernateException if(event.getObject()instanceof User) User u=(User)event.getObject(); System.out .println(u.getName(); /这个是会默认调用的类,但如果你配置了其他的实现类,hibernate就不会自动调用了,需要进行
49、配置才能对对象进行保存 SQL 查询String hql = select * from user where name=:n; / Query que=session.createQuery(hql);Query que=session.createSQLQuery(hql).addEntity(User.class); que.setString(n, name); User u=(User)que.uniqueResult(); System.out .println(u.getBirthday(); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 19 页,共 19 页 - - - - - - - - -