在我的前一篇博客中,主要介绍了我的第一个hibernate项目的开发过程。这一篇博客,继续写我在学习hibernate的过程中遇到的问题以及一些hibernate的知识点,作为我学习hibernate的一点总结。
上一篇关于hibernate的博客,我写的是完全用手动配置的方式来开发hibernate,这一篇,先写写如果在写好了domain对象和mapping对象映射文件之后,如何自动生成数据表。在这里,我切换了数据库,将Oracle切换成MySQL数据库。
1. 首先把hibernate.cfg.xml重新配置,将原先Oracle配置信息修改成MySQL配置
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- hibernate 设计者给我们提供了一些常用的配置可在etc文件夹下找到 --> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.username">root</property> <property name="connection.password">HUHUI</property> <property name="connection.url">jdbc:mysql:/localhost:3306/test</property> <!-- 配置dialect,明确告诉hibernate连接的是哪种数据库 --> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <!-- 显示出对应的SQL语句 --> <property name="show_sql">true</property> <!-- 让hibernate给我们自动创建表 。create表示如果没有该表,则创建--> <property name="hbm2ddl.auto">create</property> <!-- 指定对象关系映射文件 --> <mapping resource="com/hh/domain/Employee.hbm.xml" /> </session-factory> </hibernate-configuration>
2. 对对象映射文件进行修改
主要是对主键生成策略做了修改
<id name="id" column="id" type="java.lang.Integer">
<generator class="assigned"></generator>
</id>
这个assigned方式,是用户调用sava()方法,设置主键值
3. 运行TestMain.java文件,程序将在MySQL数据库中自动生成employee表
在切换数据库的过程中,我没有修改java代码,只是修改了两个配置文件,十分的方便。
下面提供一套模板代码,用于在hibernate中进行回滚操作
//在hibernate中回滚事务 Session session = MySessionFactory.getSessionFactory().openSession(); Transaction ts = null; try { ts = session.beginTransaction(); Employee employee = (Employee)session.load(Employee.class, 1);//这句话产生一个select语句 employee.setName("name8");//update.这句话会导致一个update语句产生 employee.setEmail("[email protected]"); ts.commit(); } catch (Exception e) { // TODO: handle exception if(ts != null){ ts.rollback(); } throw new RuntimeException(e.getMessage()); }finally{ //关闭session if(session != null && session.isOpen()){ session.close(); } }
new Configuration.configure("com/hh/config/hh.cfg.xml");
1. Configuration
① 读取hibernate.cfg.xml文件
② 管理对象关系映射文件 <mapping resource="">
③ 加载hibernate驱动、url、用户名和密码
④ 管理hibernate配置信息
2. SessionFactory
① 可以加载sql语句和数据(称为session级缓存)
② 是一个重量级的类,占用较多内存。
这里我们讨论通过SessionFactory获取Session的两个方法openSession()和getCurrentSession()
a. openSession()是获取一个新的session
b. getCurrentSession()获取的是和当前线程绑定的session,换言之,在同一个线程中,我们获取的session是同一个session,这样可以有利于我们事务的控制
c. 如果希望使用getCurrentSession(),我们需要配置hibernate.cfg.xml
<property name="current_session_context_class">thread</property>关于是配置thread还是jta的问题:
配置thread是jdbc事务,也即本地事务,是针对一个数据库的事务;
配置jta是jta事务,也即全局事务,是跨数据库的。
d. 如何选择这两个方法,原则如下:
如果在在同一个线程中,保证使用同一个session,则使用getCurrentSession;如果在一个线程中,需要使用不同的session,则使用openSession
e. 通过getCurrentSession获取的session在事务提交后,会自动关闭,而用openSession获取的session则必须手动关闭。
在query查询的时候,如果是使用openSession,则不需要事务处理,但是如果使用的是getCurrentSession,则需要事务处理。
Configuration cf = new Configuration().configure(); SessionFactory sf = cf.buildSessionFactory(); Session s = sf.getCurrentSession(); //Session s = sf.openSession();
① Session一个实例代表与数据库的一次操作
② Session实例通过SessionFactory获取,用完需要关闭
③ Session是线程不同步的(不安全),因此要保证在同一个线程中使用,可以用getCurrentSession()
④ Session可以看做是持久化管理器,它是与持久化操作相关的接口
Session接口的几个重要方法:
a) 保存一个对象——sava方法
b) 删除一个对象——delete方法
c) 查询一个对象——get/load方法
d) 修改一个对象——update方法
get()和load()的区别
① 如果查询不到数据记录,那么get不会报错,而是返回一个null,而load如果查询不到数据,则抛出一个异常;
② 使用get去查询的时候,会立即向DB发出SQL语句查询请求;如果是用load查询,即使查询到了,返回的是一个代理对象,如果后面没有使用查询的结果,则不会向DB发出SQL语句,当程序员使用查询结果的时候,才会真的发出SQL语句,这个现象称为“懒加载”;
③ 通过修改配置文件,可以取消load的懒加载,在class中配置lazy=false;
注:当用load查询时,如果后面使用了查询对象,则向DB发出SQL语句,然后将查询到的结果放在二级缓存中,当下次再查询相同的记录时,则直接在二级缓存中查询。get也是如此,第二次查询记录,也不再发一次SQL语句,而是在缓存中找。
4. Query接口
通过Query接口我们可以完成更加复杂的查询任务,其基本用法如下:
ts = session.beginTransaction(); //获取query引用 //这里的Employee不是表明,而是domain对象名;where后面的条件,id可以是数据库中的字段名,也可以是domain中属性名 //按照hibernate的推荐,我们还是应该使用类的属性名 Query query = session.createQuery("from Employee where id=1"); //通过list方法获取结果,这个list会自动将结果封装成对应的domain对象 List<Employee> list = query.list(); for(Employee e : list){ System.out.println(e.getEmail()); } ts.commit();
这个接口用的比较少,案例如下:
ts = session.beginTransaction(); Criteria cri = session.createCriteria(Employee.class); cri.setMaxResults(2); cri.addOrder(Order.desc("id")); List<Employee> list = cri.list(); for(Employee e : list){ System.out.println(e.getId()); } ts.commit();
下面介绍,如何使用Eclipse进行Hibernate的快速开发:
之前的开发,都是现在数据库中建好表,然后手写domain对象和对象关系映射文件:DB(table)->手写domain对象->对象关系映射文件
现在我们希望用工具完成domain对象和对象关系映射文件的工作。但是前提是在DB中已经建立好了表。
1. 创建web项目
2. 通过MyEclipse提供的数据库浏览器(MyEclipse Database Explorer)连接我们Oracle数据库
3. 引入hibernate开发包,同时自动创建hibernate.cfg.xml文件
4. 使用MyEclipse提供的逆向工程,自动创建domain类和对象关系映射文件
点击finish
这样,就自动生成了domain类和对象关系映射文件。
注:自动生成以后,还要配置对象映射文件的主键生成方式。