1、一 、第一种应用实例1搭建环境:新建一种名为HibernateDemojava工程,并导入Hibernatejar包,特别要注意除了导入lib下jar包还需导入hibernate3.jar核心jar包。 由于涉及数据库操作,还应导入mysql驱动包。阐明,如果使用最新hibernate,hibernate开发基本jar包(7个) 来源:hibernate-distribution-3.3.2.GA.zip hibernate3.jar librequired下所有jar包2简述Hibernate作用:ORM:Object Relational Mapping,对象关系映射。将java程序中对象
2、自动持久化到关系数据库中。而Hibernate作用好比就是在java对象与关系数据库之间一座桥梁,它重要负责两者之间映射。在Hibernate内部封装了JDBC技术(但只是一种轻量级封装,因而可以让程序设计人员更以便以面向对象思想操纵数据库),并向外提供API接口。3建新一种名为User.java类,即是上面所说java对象。咱们后来称这种类为实体类(或是持久化类),它对象为实体对象(或是持久化对象)。User.java内容如下:package com.asm.hibernate.domain;import java.util.Date;public class User private in
3、t id;private String name;private Date date;public int getId() return id;public void setId(int id) this.id = id;public String getName() return name;public void setName(String name) this.name = name;public Date getDate() return date;public void setDate(Date date) this.date = date;4编写配备文献:User.hbm.xml。
4、它和User.java放在同一种包下。内容如下:此配备文献,是用来为User.java进行配备,咱们后来称这种文献为实体配备文献(或是持久化类映射文献) 用来关联一种java类,注旨在前面根元素下有一种package属性,这样结合这个package和class标签下所指定类名,就共同关联映射了一种java类。 其实可以这样理解,每一种包下均有实体配备文献,而这个配备文献开始根元素package指定了此文献所处位置(或是说它所关联包),根元素下可以有各种标签(查阅dtd文献),它们可以分别来关联包下java类文献。 标签,普通建议至少有两个属性:name属性用来关联一种java类,例如这里关联了
5、User类;table属性用来指定这个类所相应表文献,如果不指定,系统会自动name指定类文献进行关联(例如上面实际是:) 标签下子标签:l 子标签实际就是用来映射主键,下name就是用来指java类中id属性,而它可以有一种column属性用来指定表中主键。同步注旨在此标签下有一种标签,它是用来指定主键生成方式。 l 子标签,就是用来指定java类属性映射到表中一种字段,默认下此标签没有指定column属性,即是说它会把name所关联属性名作为字段名。 如果不想java类中某些属性映射到表中,只要不用这个标签来关联这些属性即可。l 总结:上面name属性都分别指定了java类,java类属性
6、。而table,column是用来指定表,字段名配备文献:hibernate.cfg.xml。它放在当前项目根目录下。内容如下:com.mysql.jdbc.Driverjdbc:mysql:/localhost:3306/testroot123456org.hibernate.dialect.MySQLDialectcreate主配备文献,完毕了驱动注册,数据库连接,并关联了相应java对象配备文献。阐明:详细指定了关联所有实体配备文献,关于它作用可以注释掉此属性看效果。另通过create指定了依照实体配备文献来自动生成表,其中涉及:create/create-drop/update/val
7、idate四种可选方式。5编写测试类:UserTest.java 内容如下:package com.asm.hibernate.test;import java.util.Date;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.Transaction;import org.hibernate.cfg.Configuration;import com.asm.hibernate.domain.User;public class UserTest public static
8、 void main(String args)Configuration cf=new Configuration();cf.configure();SessionFactory sf=cf.buildSessionFactory();Session s=sf.openSession();Transaction ts=s.beginTransaction();/事务User user=new User();user.setName(jack);user.setDate(new Date();s.save(user);mit();/提交事务s.close();System.out.println
9、(done);6分析流程:一方面抛开Transaction tx=s.beginTransaction()和mit(),由于它们是提交事务得。支持提交事务意味着支持数据回滚。阐明,普通状况下,诸多数据库都默认支持提交事务,因此加这两句代码非常必要。 下面详细谈流程:第一步:获取SessionFactory对象,它会一方面构建一种Configuration对象,此对象调用可以调用configure()和configure(String resource)这两种办法:这两种办法在Configuration中源代码如下:public Configuration configure() throws
10、HibernateException configure( /hibernate.cfg.xml );return this;public Configuration configure(String resource) throws HibernateException log.info( configuring from resource: + resource );InputStream stream = getConfigurationInputStream( resource );return doConfigure( stream,resource );分析这两个源代码可以懂得:无
11、参调用最后也是调用这个有参数办法,因此咱们也可以直接传参数调用。 当前重点是读配备文献,这个配备文献咱们普通放在eclipsescr根目录下,而当eclipse编译时会自动把这个目录下文献编译到bin目录下,而这个bin目录下是被配备成classpath环境变量,而configure办法就是在classpath环境变量下查找配备文献。 再来分析,无参调用configure办法时,默认是传递hibernate.cfg.xml配备文献,因此只有取名为这个配备文献,才可以调用无参configure办法,如果是其他名字配备文献,则调用含参配备文献,并且这个参数名应为这个配备文献名字。 当读取配备文献后
12、Configuration对象,才是一种真正意义上可操控实例对象。 然后,再用这个对象来构建一种SessionFactory对象。 强调阐明,这一步整个操作最佳是放在类静态代码块中,由于它只在该类被加载时执行一次。第二步:得到一种Session实例,以进行数据库CRUD操作第三步:实例化一种java类第四步:持久化操作第五步:后续操作:重要是关闭连接 7.实体类定义规则:Domain object(java对象)必要要有构造办法,同步建议有一种id属性,为了赖加载,这个java类声明最佳不用final。8.开发流程:官方推荐:先Domain object 再mapping,最后是DB。 惯用开
13、发方式:DB开始,由工具来生成mapping和Domain object。9.总结基本环节:环境搭建(导入有关包等) 实体类及配备文献主配备文献(完毕了数据库配备及通过设立属性创立了相应表)得到Session测试应用。二、优化代码1为会么要优化在前面咱们已经懂得,获取SessionFactory对象是一种重复过程。因而咱们可以把这个操作写成一Util类。下面咱们把这一步写成工具类HibernateUtil,内容如下:package com.asm.hibernate.utils;import org.hibernate.Session;import org.hibernate.SessionF
14、actory;import org.hibernate.cfg.Configuration;public class HibernateUtil private static SessionFactory sf;private HibernateUtil() static Configuration cf = new Configuration();cf.configure();sf = cf.buildSessionFactory();public static SessionFactory getSessionFactory() return sf;public static Sessio
15、n getSession() return sf.openSession();2优化测试类下面复制UserTest.java代码改为UserTest2.java并进行修改 修改后内容如下:package com.asm.hibernate.test;import java.util.Date;import org.hibernate.HibernateException;import org.hibernate.Session;import org.hibernate.Transaction;import com.asm.hibernate.domain.User;import com.asm
16、.hibernate.utils.HibernateUtil;public class UserTest2 static void addUser(User user) Session s = null;Transaction ts = null;try s = HibernateUtil.getSession();ts = s.beginTransaction();s.save(user);mit(); catch (HibernateException e) if (ts != null)ts.rollback();throw e; finally if (s != null)s.clos
17、e();public static void main(String args) User user = new User();user.setName(richie);user.setDate(new Date();addUser(user);阐明,在addUser办法中其实也可以不用catch语句捕获。由于核心关闭连接已在finally实现。上面例子可以作为后来Hibenate操作一种典型模板,只需要修改主办法中内容即可。3.get办法:可以在UserTest2.java中增长这个办法:static User getUser(int id) Session s = null;try s =
18、 HibernateUtil.getSession();return (User) s.get(User.class,id);/* * User user=(User) s.load(User.class,id); * System.out.println(-load-+user); * System.out.println(user.getName(); * /load只是准备连接到数据库,当增长上面一句操作时表达有真正数据库操作,这时它才会去连接数据库 return user; */ finally if (s != null)s.close();以上代码,实现了数据库查询操作,这里get
19、()办法需要传递两个参数,理解传递参数:由于Session可以管理各种数据库所相应各种实体对象,如果只是传递id将不能正拟定位表,因而必要传递这个实体对象 ,get办法才干去查找这个实体对象所相应数据库中表。 用这个办法得到User对象后,便可以用此对象办法来得到有关属性(也就是数据库表中字段) 4.load()办法,懒加载。它特点是:只有实际操作才会被加载,且它是生成这个User.java子类,可以从打印成果看出。也正因而,所此前面建议实例类不使用final。强调:如果是懒加载,虽然数据库中查不到数据,上面user对象永远不会为空,由于它内部实现事实上是new了一种User(子)类对象。下面
20、再在main办法中测试,增长语句如下:User u = getUser(1);System.out.println(id= + u.getId() + t name= + u.getName();5.控制台显示:true在总配备文献中增长这个属性将会在控制台显示数据库操作“数据库语言”。称这个属性为数据库语言显示。三 、Session中重要办法1保存数据:save,presist 阐明:这两种办法重要区别重要体当前未启动事务时。save办法如果是没启动事务,会执行有关sql语句,随后再回滚。而presist主线就不执行这些sql语句。2删除对象:delete3更新数据:update 阐明,如果
21、数据库中没有记录将会浮现异常4查找数据:get,立即访问数据库 load,返回是代理,不会及时访问数据库。5选取操作:saveOrUpdate,merge,依照id和version值来拟定是save还是update。saveOrUpdate办法重要作用:可以把瞬时对象或脱管对象转成持久对象,而不需要详细判断对象是处在瞬时态或是脱管态来选取save或update来让对象变成持久态。只要调用此办法就能由id和version来灵活选取是保存或更新。而merge办法一种对象后,对象仍是脱管态。5持久对象:lock,把对象变成持久对象,但不会同步对象状态。四 、对象三种状态1瞬时(transient):
22、数据库中没有数据与之相应,超过作用域会被JVM垃圾回收器回收,普通是new出来且与Session无关系对象。2脱管-游离(detached):数据库中有数据与之相应,但当前没有Session与之关联:脱管对象状态发生变化,Hibernate不能检测到。3持久(persistent):数据库有数据与之相应,当前与Session关于联,并且有关联Session没关于闭,事务没有提交:持久对象状态发生变化时,在事务提交时会影响到数据库。理解:与Session与否关联,数据库与否有数据与之相应是判断三种对象状态根据。例如,瞬时状态跟它们均无关;脱管,只是数据库有数据与之相应,失去了Session对它管
23、理;而持久与两者者关于。从过程中理解三种对象状态:结合前面实例,当咱们User user=new User()一种对象时,它表达创立一种瞬时对象,当调用save(user)办法时,这个对象成为持久对象,直到事务提交,数据库连接关闭。在这期间,如果咱们user.setXXX()时,会对这个持久对象产生影响,最后它也会被提交到数据库,它最后提交是在提交事务时。例如save(user)办法后,跟user.setName(new name);和user.setPassword(new password);这两句,这样它会在提交时务时,采用对数据库更新操作,也就是说数据库连接关闭后,数据库存是“new
24、name”和“new password” 而如果启动了“数据库语言显示”可以发现执行两次操作:一次是save办法插入操作,一次是setXXX后提交事务时更新作(特别阐明,持久对象在发生变化时,例如setXXX办法变化对象内容时,会在最后,即提交事务时统一进行更新操作,而并非每一次变化就执行一次更新,这样可以保证与数据库交互更高效合理)。当执行完save办法后,咱们关闭数据库连接时,这时user对象就是脱管状态,由于它在数据库有数据与之相应 而脱管状态最佳例子是当咱们用get办法得到一种对象并关闭连接时 补充阐明:既然咱们已经懂得了持久对象可以被Hibernate检测到进行更新操作,那么upda
25、te与否尚有用了?有,例如脱管对象就可以调用update来更新数据库中数据,而调用update()办法后脱管对象又变成了持久对象。 下面是三种对象状态互相转换图例transientpersistentdetachedsava()saveOrUpdate()newdelete()get()load()find()iterate()evict()close()clear()update()saveOrUpdate()lock()garbge()再谈saveOrUpdate办法:此办法兼具了save和update两种办法。它依照传递参数来选取执行其中一种办法。如果参数对象是瞬时态,则执行save办法
26、,而如果参数对象是脱管态,则执行update办法。最后都是把传递参数对象转成持久态。 如何判断对象状态?重要根据是看:实体对象id(或者version)取值与实体配备文献中元素unsaved-value属性值匹配状况。 只要满足下面任一状况则可以阐明对象处在瞬时态:状况一,实体对象(持久化对象)id取值为null形式(例如int型为0,字串为null)。 状况二,实体对象(持久化对象)id取值与预设unsaved-value属性值不同。 状况三,实体对象(持久化对象)具备versionn属性,并且为null。 状况四,实体对象(持久化对象)version取值与预设unsaved-value属性
27、值不同。五、完善工具类及HQL QBC初步有关1无聊讨论:在前面咱们写了一种工具类:HibernateUtil。其实咱们还可以把CRUD操作封装到这个工具类中,并把它们都做成静态,这样这个工具类就可以直接调用了。但是这样操作对查询数据也许不是较好,由于它查询方式诸多,除非咱们一一考虑这些也许涉及到查询方式,并能以重载形式进行统一管理。 其实我也试想过把这此数据库操作办法进行二次封装,在工具类写成如下形式:public void operate(int i )if(i=1) 调用更新办法,执行查询操作if(i=2) 调用删除办法,执行查询操作if(i=3) 调用插入办法,执行查询操作if(i=4
28、)查询?可指定一种惯用查询办法,但返回值如何解决,因此建议不在此处写查询,可再写一种查询统一操作办法来总括所有查询办法2HQL作用概述数据库操作,难点重要集中在查询操作中,而HQL就是专门用来为查询服务。3HQL应用环节:假定咱们已有一种Session对象s环节一,获得Query对象:Query query=s.createQuery(“HQL SELECT Sentence”);环节二,为参数赋值:query.setXXX();环节三,获得List对象:LIST list=query.list();阐明,除了此办法外,Query接口尚有一种惯用办法uniqueResult,如果明确查询成果只
29、有一种,便选取使用此办法。如果查询成果有各种使用此办法会报异常。环节四,遍历查询成果:即遍历上面list对象。关于环节二为参数赋值问题:例如环节一中“HQL Sentence”内容为:from User u where u.name=?and u.password=?and .,如果这里?较少可以setXXX(0,”.”);setXXX(1,”.”);但是如果?较多,就容易把这些设立写错,因此可以采用命令参数方式来决定背面setXXX内容。 例如:from User u where u.name=:uname and u.password=:upass and . ,这样背面就可以写setXX
30、X(“uname”,”.”);4一种细节问题:在前面咱们实体类为User类,而在实体配备文献中意为它所关联表为user表(没有指定名称table),但如果是oracle数据库,咱们懂得它自身就有一张user表,这样就产生了冲突,如何解决这种冲突?一种办法是设定table属性为新名字(首选办法),另一种办法是加(数字1前那个符号),即这样写,这样咱们表还是user表。同样如果属性名与数据库中核心字产生这种冲突,也可以按此办法解决。5.分页技术:query.setFirstResult(200);query.setMaxReslut(10);这两句意思是符合规定语句有诸多条,咱们从第200条取,取
31、出10条。咱们懂得每种数据库分页语句是不同,而Hibernate底层判断使用哪种分页语句就是参照前面配备文献方言属性。6.QBC条件查询:与它有关是Criteria Interface,Criterion Interface,Expressson Class。其实它操作和HQL很相似。同样咱们假定已有一种Session对象s.环节一,获得Criteria对象:Criteria criteria = s.createCriteria(User.class);环节二,封装查询条件为一种Criterion对象:Criterion cr = Expression.eq(name,new name);(
32、阐明Expression继续于org.hibernate.criterion.Restrictions类),因此也可以这样写:Criterion cr=Restrictions.eq(name,new name);Restrictions类中封装查询条件办法均有两个参数:前一种参数是指创立Criteria对象时所使用参数属性名,后一种是要与属性名比较值。例如这里是指User类name属性与否与“new name”相等环节三,获得带查询条件Criteria对象:criteria.add(cr);执行此步才使这个对象具备一种条件限制查询操作。环节四,获得List对象以遍历:List clist =
33、 criteria.list();补充阐明:也可以直接返回一种User对象:User user=(User) criteria.uniqueResult();特别阐明:Criteria对象也具备分页功能,方式是和上面Query同样 。六 、基本应用实例:Dao设计1总体设计:设计User对象及有关实体配备文献,工具类(得到一种Session对象),UserDao接口(实现此接口即以操作数据库),编写主配备文献,编写测试类。2UserDao设计,最初我想打算设计成通用Object操作,日后发现它Session对象操作都要传递一种对象,就设计成如下形式。内容如下:package com.asm.d
34、ao;import com.asm.domain.User;public interface UserDao public void saveUser(User user);public User queryById(int id);public User queryByName(String name);public void update(User user);public void delete(User user);按此设计,意思是此类专门针对User对象数据库操作,传递User对象,所后来面它实现类query有关办法可以直接user = (User) s.get(User.class
35、,name);写name为传递参数,而咱们懂得操作是User对象,因此直接可以User.class。 值得一提是,在JDBC操作中,delete,传递id这种值就可以实现删除,而Hibernate删除操作,必要传递一种对象,操作过程就是咱们通过id查出这个对象,再把这个对象传递给删除办法以供删除。而实事上也可以new一种User对象,并设定id,然后再把这个对象传递给删除办法。 但需要特别注意new出对象必要完毕符合咱们通过id查出对象。3这个实例参照前面有关,基本可以写出。如下几点需要注意:导包:Hibernate包,数据库包;改写配备文献;查询办法设计;注意事务,特别是“增删改”要注意事务
36、。七 、关联关系讨论1多对一关系映射:一种部门有可以有各种员工,而一种员工只属于一种部门。从员工角度看,诸多员工会从属一种部门。现以实例阐明,实例概要:一种部门类,只有id和部门名称两个属性。有一种员工类,有id和员工名称及部门对象三个属性。操作环节如下:环节一,建立Depatment.java及实体配备文献:package com.asm.hibernate.domain;public class Department private int id ;private String name;public int getId() return id;public void setId(int
37、id) this.id = id;public String getName() return name;public void setName(String name) this.name = name;-同包下实体配备文献:Depart.hbm.xml以上操作,没什么可多言,和前面配备是同样形式。环节二,Employee.java内容如下及实体配备文献package com.asm.hibernate.domain;public class Employee private int id;private String name;private Department depart;publi
38、c int getId() return id;public void setId(int id) this.id = id;public String getName() return name;public void setName(String name) this.name = name;public Department getDepart() return depart;public void setDepart(Department depart) this.depart = depart;-同包下实体配备文献:Employee.hbm.xml先来说这个类文献,它一种重要属性就是
39、Department对象,这就是它所关联一种外键,这里咱们只必要记住一点,每个实体类相应于一张表,如果一张表想关联另一张表,则只需要在这张表所相应实体类中引入它想关联表实体类对象。再进行简朴配备即可。再来看配备文献,这里重要看这个元素,它name属性依然是实体类中属性。column为相应表外键。可以留意下数据库表中有关表。修改主配备文献,增长如下内容以便找到相应实体配备文献。 环节四,编写测试类。类中省略导入包内容。package com.asm.hibernate.test;public class ManyToOneTest public static void main(String args) add();static