hibernate的jar包文件
antlr-2.7.6.jar
commons-collections-3.1.jar
dom4j-1.6.1.jar
javassist-3.9.0GA.jar
jta-1.1.jar
slf4j-api-1.5.8.jar //用于日志的slf标准
apislf4j-nop-1.5.8.jar //用于日志的slf实现
hibernate-annotations.jar //注解
ejb3-persistence.jarhibernate-commons-annotations.jar
hibernate除了以上jar包之外还需要数据库驱动jar
持久化就是把数据保存到可掉电式存储设备中供之后使用。各种数据库就是持久化工具。通过它我们将数据持久化到磁盘上。
有了持久化为什么还要持久层呢?
主要是为了解决以下几个问题:
1、如果业务层发生变化,比如需要将客户端程序从C/S迁移到B/S,我们的持久化代码是否要重新编译。
2、如果底层数据持久化机制发上了变化,如从oracle数据库更改成sqlserver或者用于测试的小型数据库mysql,我们的持久化代码是否要重新编译。从本质上讲持久化进化到持久层的目的就是为解决耦合,实现业务逻辑和数据逻辑的分离。
举个很简单的例子:
我们复制文件,有可能复制到软盘/U盘/甚至是网络上的任意一台电脑的硬盘,如果按照开发人员的思维方式就要写一堆if/else来判断设备类型,如果更完善一点还要考虑并发,同一时间不能向一个设备发数据,调度好线程。但是实际上我们只需要Ctrl+C/Ctrl+V就搞定了,操作系统帮我们做好了一个持久化层。将我们的业务逻辑(拷贝文件)和数据逻辑(传输数据)分离了。
设计得好的持久层可以达到以下目的:
1、数据存储逻辑的分离业务层代码不会出现数据操作的代码如insert/update/select,只需要编写业务代码如:
Customer c=newCustomer();
c.setName("jack");
c.setAge(20);
saveandupdate(c);
使得开发人员可以更好的专业划分,另外测试起来也相对容易。
2、更好的性能成熟的持久化层可以提供数据库连接池/语句cache/数据cache,减少数据库的查询压力。
数据库连接池:每次数据库连接都需要建立socket、验证密码/权限、记录日志、分配cpu内存等等,这是相当耗费资源的。如果仅仅为了一条查询语句就要建立连接然后释放连接那就太浪费了。数据库连接池就是将暂时不用的连接不进行关闭,保存下了,以备下次直接使用。
语句cache:一般情况下我们认为update语句很快,也就一眨眼的时间,但是这一眨眼的时间数据库为我们做了很多事——sql语法检查、语义分析、创建执行计划等。大型的系统由成百上千的终端操作数据库,而实际上操作最多的表也就十几个,运行的语句也就几十种。如果将这些语句也缓存起来,性能也能够提高很多。
数据cache:这是最常见的,如果数据库中的数据没有变化那就不用从数据库中select了,直接读内存就好了。减少了网络传输、内存与磁盘数据交换等开销。
ORMaping就是对象关系映射。ORMaping发展到现在已经出现了很多好的成熟的产品,而且很多都是开源的免费的。
采用这些产品可以减少乏味的代码/更加面向对象的设计/更好的性能/更好的移植性。
一般的开发步骤是:
1、编写ORMap配置文件,一般是xml的。这是比较耗时的,但是可以进行迭代开发,一边开发一边修改(建议采用自动测试工具Unit系列,每次修改完成回归测试一下建立信心)。
2、借助工具,根据配置文件生成数据库ddl,以及实体类代码,比如同时生成Customer表和Customer.java源码, 表有字段name,相应的Customer.java有属性name和相应的方法getName()/setName(String)。 对于遗留系统,可以借助工具连接数据库反向生成配置文件和实体类代码,十分方便快捷。
3、编写提供给业务层的方法,其中涉及到事务的处理、异常处理、操作实体类,类似于以前的业务开发,但是 完全不涉及到sql语句(通过配置文件ORMap产品和数据库在底层进行sql交互,对我们来说是透明的),完全的面向对象代码。这步 稍微费点时间但是相对于以前的业务开发便利了太多。
Hibernate中session比较常用的几种方法
1.save,persist 都是用来保存数据的,persist在事务外不会产生insert语句。如果开启事务时两者没有明显的差别,但如果关闭事务时则:
save 方法会产生insert语句,但由于没有开启事务,执行语句会回滚,会删除insert插入数据库中的数据数据,persist则不会产生insert语句,也不会向数据库中插入数据。
2.delete 删除对象。
3.update 更新对象,如果数据库中没有记录,会出现异常。
4.get根据id查,会立刻访问数据库。
注: 查询数据时,因不用对数据库数据进行操作,所以可以不用开启事务。
5.load 根据id查。(返回的是代理,不会立即访问数据库)
6.saveOrUpdate,merge(根据id和version的值来确定是save还是update)调用merge你的对象还是托管的。
7.lock (把对象变成持久对象,但不会同步对象的状态)
Domain Object限制
1.默认的构造方法(必须)
2.有无意义的标识符id(主键)(可选)
3.非final的类修饰符,对懒加载有影响(可选)
实体Studen类
package com.hero.hibernate.model;
public class Student {
private int id;
private String name;
private int age;
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 int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
实体Teacher类
package com.hero.hibernate.model;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
//采用注解的方式标注实体
@Entity
//指定实体与对应的表名
@Table(name="teacher")
public class Teachers {
private int id;
private String name;
private String title;
//设定id号
@Id
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 String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
hibernate配置文档
<?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>
<!-- Database connection settings -->
<!-- 设置数据库连接 -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost/hibernate</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<!-- JDBC connection pool (use the built-in) -->
<!-- <property name="connection.pool_size">1</property> -->
<!-- SQL dialect -->
<!-- 配置数据库方言 -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Enable Hibernate's automatic session context management -->
<!-- <property name="current_session_context_class">thread</property> -->
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<!-- 显示执行sql语句 -->
<property name="show_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">create</property>
<!-- 映射有两种方式 -->
<!-- 方式一:采用xml配置文档形式,约定俗成的命名*.hbm.xml -->
<mapping resource="com/hero/hibernate/model/Student.hbm.xml"/>
<!-- 方式二:采用注解的方式。推荐采用 -->
<!-- <mapping class="com.hero.hibernate.model.Teachers"/> -->
</session-factory>
</hibernate-configuration>
xml映射文档
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 映射方式一xml配置文档 -->
<hibernate-mapping package="com.hero.hibernate.model">
<class name="Student" table="students"><!-- 映射实体和表名 -->
<id name="id"></id><!-- 指定id -->
<property name="name"></property>
<property name="age"></property>
</class>
</hibernate-mapping>
HibernateUtil类
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public final class HibernateUtil {
private static SessionFactory sessionFactory;
private void HibernateUtil() {
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
//鉴于SessionFactory等操作只用创建一次,Configuration的configure()用于读取hibernate的配置文档
static{
Configuration cfg = new Configuration();
cfg.configure();
sessionFactory = cfg.buildSessionFactory();
}
}
测试类TestClass
import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; import org.hibernate.cfg.Configuration; import org.junit.Test; import com.hero.hibernate.model.Student; import com.hero.hibernate.model.Teachers; public class TestClass { @Test //采用junit方式来测试 public void TextStudent(){ //创建一个student对象 Student stu = new Student(); stu.setId(1); stu.setName("student1"); stu.setAge(2); addStudent(stu); } /*@Test //采用junit方式来测试 public void TextTeacher(){ //创建一个student对象 Teachers tea = new Teachers(); tea.setId(1); tea.setName("Teacher1"); tea.setTitle("讲师"); Configuration cfg = new AnnotationConfiguration(); cfg.configure(); SessionFactory sessionFactory = cfg.buildSessionFactory(); //通过sessionfactory对象获取session对象 Session session = sessionFactory.openSession(); //hibernate 中提交需要自己手动开启事务 session.beginTransaction(); session.save(tea); //提交事务 session.getTransaction().commit(); session.close(); sessionFactory.close(); }*/ public static void addStudent(Student stu){ SessionFactory sessionFactory = null; Session session = null; try{ sessionFactory = HibernateUtil.getSessionFactory(); //通过sessionfactory对象获取session对象 session = sessionFactory.openSession(); //hibernate 中提交需要自己手动开启事务 session.beginTransaction(); session.save(stu); //提交事务 session.getTransaction().commit(); }finally{ if(sessionFactory != null || session != null) //关闭session session.close(); //关闭sessionfactory sessionFactory.close(); } } }