一、ORM 简介:
ORM 全称是 Object\ Relation Mapping, 即对象\关系映射
ORM 可以理解为一种规范,具体的 ORM 框架可作为应用程序和数据库的桥梁
面向对象程序设计语言与关系型数据库发展不同步时,需要一种中间解决方案,ORM 框架就是这样的解决方案
ORM 不是具体的产品,是一类框架的总称,基本特征:
(1)、完成面向对象的程序设计语言到关系数据库的映射
(2)、基于 ORM 框架完成映射后,即可利用面向对象程序设计语言的简单易用性,又可利用关系型数据库的技术优势
二、hibernate 简介:
1、hibernate 是当前最流行的的 ORM 框架之一, hibernate 采用低侵入式的设计,即采用完全的 Java对象 (POJO,VO) ,而不必继承 hibernate 的某个超类或实现 hibernate 的接口。
2、ORM 规范映射思想:
(1)、一张表映射成一个类
(2)、一行数据(记录)映射成一个对象
(3)、一列数据被映射成对象的属性
ORM 的作用: 负责把面向对象的持久化操作,转换为数据库的标准 SQL 语句执行
3、hibernate 的目录结构:
4、hibernate 工作流程:
5、所需 jar 包:
三、创建 java 工程:
1、持久化类,代码如下:
package learn.hibernate.bean; import java.util.Date; /** * 持久化类设计 * 注意: * 持久化类通常建议要有一个持久化标识符(ID) * 持久化标识符通常建议使用封装类(例如:Integer 因为基本类型存在默认值) * 持久化类通常建议手动添加一个无参构造函数 (因为有些操作是通过放射机制进行的) * 属性通常建议提供 getter/setter 方法 * 持久化类不能使用 final 修饰 * 持久化类中如果使用了集合类型数据,只能使用集合所对应的接口类型来声明(List/Map/Set) * 如下:ArrayList list = new ArrayList(); 不行 * List list = new ArrayList(); 可行 */ public class Person { private Integer id; private String name; private int age; private int passwork; private Date birthday; public Person() { } public Person(String name, int age, int passwork, Date birthday) { super(); this.name = name; this.age = age; this.passwork = passwork; this.birthday = birthday; } @Override public String toString() { return "Person [id=" + id + ", name=" + name + ", age=" + age + ", passwork=" + passwork + ", birthday=" + birthday + "]"; } public Integer getId() { return id; } public void setId(Integer 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; } public int getPasswork() { return passwork; } public void setPasswork(int passwork) { this.passwork = passwork; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } }
2、持久化类所对应的配置文件,代码如下:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <!-- 持久化映射文件(将java对象映射到数据库表) --> <hibernate-mapping package="learn.hibernate.bean"> <!-- 1、name (可选): 持久化类(或者接口)的Java全限定名。 如果这个属性不存在,Hibernate将假定这是一个非POJO的实体映射 2、table (可选 - 默认是类的非全限定名): 对应的数据库表名,生成DDL时数据表名,如果省略,则名称同持久化类名称 --> <class name="Person" table="t_person"> <!-- 主键 name 属性值对应持久化类的属性名; column(可选) 属性值表示在数据库生成的字段名 generator元素中的 class 值表示生成策略 1) assigned:主键由外部程序负责生成,在 save() 之前指定。 2) hilo:通过hi/lo 算法实现的主键生成机制,需要额外的数据库表或字段提供高位值来源。 3) seqhilo:与hilo 类似,通过hi/lo 算法实现的主键生成机制,需要数据库中的 Sequence,适用于支持 Sequence 的数据库,如Oracle。 4) increment:主键按数值顺序递增。此方式的实现机制为在当前应用实例中维持一个变量,以保存着当前的最大值,之后每次需要生成主键的时候将此值加1作为主键。这种方式可能产生的问题是:不能在集群下使用。 5) identity:采用数据库提供的主键生成机制。如DB2、SQL Server、MySQL 中的主键生成机制。 6) sequence:采用数据库提供的 sequence 机制生成主键。如 Oralce 中的Sequence。 7) native:由 Hibernate 根据使用的数据库自行判断采用 identity、hilo、sequence 其中一种作为主键生成方式。 8) uuid.hex:由 Hibernate 基于128 位 UUID 算法 生成16 进制数值(编码后以长度32 的字符串表示)作为主键。 9) uuid.string:与uuid.hex 类似,只是生成的主键未进行编码(长度16),不能应用在 PostgreSQL 数据库中。 10) foreign:使用另外一个相关联的对象的标识符作为主键。 --> <id name="id" column="person_id"> <generator class="native"/> </id> <!-- name(可选):对应的java类的属性名称 column(可选):对应的表中的字段 type(可选):属性的类型,eg.java.lang.String not-null(可选):设置该属性是否为空,为true时表示非空,默认为false length(可选):字段的长度限制 --> <property name="name" column="t_name"/> <property name="age"/> <property name="passwork"/> <property name="birthday"/> </class> </hibernate-mapping>
3、hibernate.cfg.xml 配置文件,代码如下:
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <!--声明Hibernate配置文件的开始--> <hibernate-configuration> <!--表明以下的配置是针对session-factory配置的,SessionFactory是Hibernate中的一个类,这个类主要负责保存HIbernate的配置信息,以及对Session的操作--> <session-factory> <!--hibernate.dialect 只是Hibernate使用的数据库方言,就是要用Hibernate连接那种类型的数据库服务器--> <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property> <!--配置数据库的驱动程序,Hibernate 在连接数据库时,需要用到数据库的驱动程序--> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <!--设置数据库的连接url:jdbc:mysql://localhost/hibernate,其中localhost表示mysql服务器名称,此处为本机, hibernate是数据库名--> <property name="hibernate.connection.url">jdbc:mysql:///hibernate</property> <!--连接数据库是用户名--> <property name="hibernate.connection.username">root</property> <!--连接数据库是密码--> <property name="hibernate.connection.password">123456</property> <!-- 是否自动创建数据库表 他主要有一下几个值: validate:当sessionFactory创建时,自动验证或者schema定义导入数据库。 create:每次启动都drop掉原来的schema,创建新的。 create-drop:当sessionFactory明确关闭时,drop掉schema。 update(常用):如果没有schema就创建,有就更新。 --> <property name="hibernate.hbm2ddl.auto">update</property> <!--是否在后台显示Hibernate用到的SQL语句,开发时设置为true,便于差错,程序运行时可以在Eclipse的控制台显示Hibernate的执行Sql语句。项目部署后可以设置为false,提高运行效率--> <property name="hibernate.show_sql">true</property> <!--指定映射文件 --> <mapping resource="learn\hibernate\bean\Person.hbm.xml"/> </session-factory> </hibernate-configuration>
4、测试类代码:
package learn.hibernate.test; import java.util.Date; import learn.hibernate.bean.Person; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; public class HibernateTest { public static void main(String[] args){ /** * Configuration 是 hibernate 的入口,负责管理 Hibernate 的配置信息, * 这些配置信息都是从配置文件 hibernate.cfg.xml 或者 Hibernate.properties */ /** * 使用configure()方法加载默认的hibernate.cfg.xml配置文件, * 因为配置文件中已经含有数据库映射信息,因此就不需要使用addClass方法加载各个类文件的映射文件 */ Configuration config = new Configuration().configure(); /** * Configuration 的实例会根据当前的配置信息,构造SessionFactory实例。 * SessionFactory 是线程安全的,一般情况下一个应用中数据库共享一个 SessionFactory 实例。 * Hibernate 的 SessionFactory 接口提供 Session 类的实例,Session 类用于完成对数据库的操作。 * 由于 SessionFactory 实例是线程安全的(而 Session 实例不是线程安全的), * 所以每个操作都可以共用同一个 SessionFactory 来获取 Session。 */ SessionFactory sessionFactory = config.buildSessionFactory(); Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); Person person = new Person("hwl",19, 123456, new Date()); session.save(person); tx.commit(); session.close(); sessionFactory.close(); } }
5、在 MySQL 数据库中创建数据库,运行测试代码,会发现在数据库中会生成表和写入一条记录
详解一:Hibernate配置文件分为两种格式,一种是xml格式的配置文件,另一种是属性文件格式的配置文件,因此构建SessionFactory也有两种方法:
1 从XML文件读取配置信息构建SessionFactory从XML文件读取配置信息构建SessionFactory的具体步骤如下。
1) 创建一个Configuration对象,并通过该对象的configura()方法加载Hibernate配置文件,代码如下:
Configuration config = new Configuration().configure();
configure()方法:用于告诉Hibernate加载hibernate.cfg.xml文件。
Configuration在实例化时默认加载classpath中的hibernate.cfg.xml,
当然也可以加载名称不是hibernate.cfg.xml的配置文件,例如myhibernate.cfg.xml,可以通过以下代码实现。
Configuration config = new Configuration().configure("myhibernate.cfg.xml");
2) 完成配置文件和映射文件的加载后,将得到一个包括所有Hibernate运行期参数的Configuration实例,通过Configuration实例的buildSessionFactory()方法可以构建一个惟一的SessionFactory,代码如下:
SessionFactory sessionFactory = config.buildSessionFactory();
构建SessionFactory要放在静态代码块中,因为它只在该类被加载时执行一次。一个典型的构建SessionFactory的代码如下。
public static SessionFactory sessionFactory;
static{
try{
Configuration config = new Configuration();
config.configure();
sessionFactory = config.buildSessionFactory();
}catch(RuntimeException e){e.printStackTrace();throw e;}
}
2 从属性文件读取配置信息构建SessionFactory,从属性文件读取配置信息构建SessionFactory的具体步骤如下:
1) 创建一个Configuration对象,此时Hibernate会默认加载classpath中的配置文件hibernate.properties,代码如下:
Configuration config = new Configuration();
2) 由于在配置文件中缺少相应的配置映射文件的信息,所以此处需要通过编码方式加载,这可以通过Configuration对象的
addClass()方法或者addResource()来实现,具体代码如下:
config.addClass(MyBean.class);或者config.addClass(MyBean.hbm.xml);
注意:这里加载的路径取默认值
3) 完成配置文件和映射文件的加载后,将得到一个包括所有Hibernate运行期参数的Configuration实例,通过Configuration实例
的buildSessionFactory()方法可以构建一个惟一的SessionFactory,代码如下:
SessionFactory sessionFactory = config.buildSessionFactory();
(来自:http://blog.csdn.net/ziliang871118/article/details/6181095)
详解二:Session
- public interface Session extends Serializable
Java应用程序与Hibernate之间的主要运行时接口。它是抽象了持久化服务概念的核心抽象API类。
Session的生命周期绑定在一个物理的事务(tansaction)上面。(长的事务可能跨越多个数据库事物。)
Session的主要功能是提供对映射的实体类实例的创建,读取和删除操作。实例可能以下面三种状态存在:
自由状态(transient): 不曾进行持久化,未与任何Session相关联
持久化状态(persistent): 仅与一个Session相关联
游离状态(detached): 已经进行过持久化,但当前未与任何Session相关联
游离状态的实例可以通过调用save()、persist()或者saveOrUpdate()方法进行持久化。持久化实例可以通过调用 delete()变成游离状态。通过get()或load()方法得到的实例都是持久化状态的。游离状态的实例可以通过调用 update()、0saveOrUpdate()、lock()或者replicate()进行持久化。游离或者自由状态下的实例可以通过调用merge()方法成为一个新的持久化实例。
save()和persist()将会引发SQL的INSERT,delete()会引发SQLDELETE,而update()或merge()会引发SQLUPDATE。对持久化(persistent)实例的修改在刷新提交的时候会被检测到,它也会引起SQLUPDATE。saveOrUpdate()或者replicate()会引发SQLINSERT或者UPDATE。
其具体实现并不一定是线程安全的。每个线程/事务应该从一个SessionFactory获取自己的session实例。
如果其持久化对象类是可序列化的,则Session实例也是可序列化的。
一个典型的事务应该使用下面的形式:
Session sess = factory.openSession(); Transaction tx; try { tx = sess.beginTransaction(); //do some work ... tx.commit(); } catch (Exception e) { if (tx!=null) tx.rollback(); throw e; } finally { sess.close(); }
如果Session抛出了异常, 事务必须回滚而session会被废弃。在异常发生后Session的内部状态可能会与数据库失去同步。
(来自:http://blog.csdn.net/shrek_xu/article/details/740991)
(注意:http://www.blogjava.net/redcoatjk/archive/2011/11/02/362491.html)