Hibernate概述与入门

来源:互联网 发布:java输出等腰三角形 编辑:程序博客网 时间:2024/06/02 04:03

一:HIbernate概述

二:Hibernate入门

Hibernate是个JavaSE项目,也适合JavaEE项目(JavaWeb)

Hibernate包歌文件说明:

1>documentation:存放Hibernate的相关文档,包括参考文档和API文档;

2>lib:存放hibernate编译与运行所依赖的jar包,其中required子目录下包含了运行Hibernate项目所必需的jar包;

3>project:存放了hibernate各种相关的源代码;

Hibernate的执行流程:

Configuration-->SessionFactory-->Session-->Transaction-->(save,delete,update,get)-->完成

1>Configuration是创建Configuration类的实例,以读取并解析配置文件(如Hibernate.cfg.xml),一个Configuration实例代表hibernate所有的Java类到sql数据库映射的集合

2>创建SessionFactory,以读取并解析映射信息,将Configuration对象的所有配置信息拷贝到SessionFactory的缓存中

对实体类的补充:

实体类必须包含一些属性,对应数据表的字段;

<span style="font-size:18px;">        @Column(name="aaaaa")private int age;private int TYPe;</span>
例如这两个属性,age属性加了@Column这个属性,那数据表的字段名字就是这个指定的,如果不加这个注解,比如TYPe,那个数据表生成的字段名就是这个属性名字;

实体类还要加与之对应的getXXX和setXXX方法,还包括无参构造器,这里是想强调,如果添加有参构造器的时候,一定要把无参构造器也写出来;

映射文件的解析:

实体类:

<span style="font-size:18px;">package com.anlw.entity;public class Users {private Integer id;private String loginName;private String logPwd;public Users(){}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getLoginName() {return loginName;}public void setLoginName(String loginName) {this.loginName = loginName;}public String getLogPwd() {return logPwd;}public void setLogPwd(String logPwd) {this.logPwd = logPwd;}}</span>

映射文件:

<span style="font-size:18px;"><?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping><class name="com.anlw.entity.Users" table="user" catalog="bookshop"><id name="id" type="java.lang.Integer"><column name="Id" /><generator class="native" /></id><property name="loginName" type="java.lang.String"><column name="LoginName" length="50" /></property><property name="loginPwd" type="java.lang.String"><column name="LoginPwd" length="255" /></property></class></hibernate-mapping></span>
解释:

这个文件中,每个class节点配置一个实体类的映射信息,<class>节点的name属性对应实体类的名字,是类全名,有包名,table属性对应数据库表的名字,catalog对应数据库的名字;

在<class>节点下,必须有一个<id>节点,用于定义实体的标识属性(对应数据库表的主键),<id>节点的name的name属性对应实体类的属性,type是该属性的java类型,例如这里的id为实体类Users中的属性,该属性类型为Integer,<column>用于指定对应数据库表的主键,<generator>节点用于指定主键的生成策略;

Hibernate提供的常用主键的生成器策略:

1>increment:对象标识符由Hibernate以递增方式生成,如果有多个应用实例向同一张表插入数据时,则会出现重复的主键,应当谨慎使用;

2>identity:对象标识符由底层数据库的自增主键生成机制产生,要求底层数据库支持自增字段类型;如mysql的auto_increament类型主键和sql server的identity类型主键,还适用于DB2,Sybase和Hypersonic SQL;

3>sequence:对象标识符由底层数据库的序列生成机制产生,要求底层数据库支持序列,如Oracle数据库的序列,还适用于DB2,PostgreSQL,SAP DB,McKoi等;

4>hilo:对象标识符由Hibernate按照高/低位算法生成,该算法从特定表的字段读取高位值,默认情况下选用hibernate_unique_key表的next_hi字段,高/低位算法生成的标识符仅在一个特定的数据库中是唯一的;

5>native:根据底层数据库对自动生成标识符的支持能力,选择identity,sequence或hilo,适合跨数据库平台的开发;

6>assigned:对象标识符由应用程序产生,如果不能指定<generator>节点,则默认使用该生成器策略;

大部分数据库,如MySQL,Oracle,DB2等,都提供了易用的主键生成机制(identity字段或sequence),因此可以在数据库提供的主键生成机制上,采用<generator class="native">的主键生成方式;

<class>节点下除了<id>子节点,还包括<prooerty>子节点,用于映射普通属性;

<property>节点与<id>节点类似,只是不能包括<generator>子节点,每个<property>节点指定一对属性和字段的对应关系;


session核心代码:

<span style="font-size:18px;">package com.anlw.util;import org.hibernate.HibernateException;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.boot.registry.StandardServiceRegistryBuilder;import org.hibernate.cfg.Configuration;import org.hibernate.service.ServiceRegistry;public class HibernateSessionFactory {// 指定Hibernate配置文件路径private static String CONFIG_FILE_LOCALTION = "/hibernate.cfg.xml";// 创建ThreadLocal对象private static final ThreadLocal<Session> sessionThreadLocal = new ThreadLocal<Session>();// 创建Configuration对象private static Configuration configuration = new Configuration();// 定义SessionFactory对象private static SessionFactory sessionFactory;// 定义configFile属性并赋值private static String configFile = CONFIG_FILE_LOCALTION;static {try {// 读取配置文件hibernate.cfg.xmlconfiguration.configure();// 生成一个注册机对象ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();// 使用注册机对象serviceRegistry创建sessuinFactorysessionFactory = configuration.buildSessionFactory(serviceRegistry);} catch (HibernateException e) {}}// 创建无参的HibernateSessionFactory构造器private HibernateSessionFactory() {}// 获得SessionFactory对象public static SessionFactory getSessionFactory() {return sessionFactory;}// 重建SessionFactorypublic static void rebuildSessionFactory() {synchronized (sessionFactory) {try {configuration.configure(configFile);ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();// 使用注册机对象serviceRegistry创建sessuinFactorysessionFactory = configuration.buildSessionFactory(serviceRegistry);} catch (HibernateException e) {}}}// 获得Session对象public static Session getSession() {// 获得ThreadLocal对象管理的Session对象Session session = (Session) sessionThreadLocal.get();try {// 判断Session对象是否存在或者已经打开if (session == null || !session.isOpen()) {// 如果Session对象为空或者未打开,再判断sessionFactory对象是否为空if (sessionFactory == null) {// 如果sessionFactory为空,则创建SessionFactoryrebuildSessionFactory();}// 如果sessionFRactory不为空,则打开Sessionsession = (sessionFactory != null) ? sessionFactory.openSession() : null;sessionThreadLocal.set(session);}} catch (HibernateException e) {}return session;}//关闭Session对象public static void closeSession(){Session session = sessionThreadLocal.get();sessionThreadLocal.set(null);try{if(session != null && session.isOpen()){session.close();}}catch(HibernateException e){}}//configFile属性的set方法public static void setConfigFile(String configFile){HibernateSessionFactory.configFile = configFile;sessionFactory = null;}//configuration属性的get方法public static Configuration getConfiguration(){return configuration;}}</span>
这个类中,首先通过一个静态代码块来启动,该代码只在类被加载时执行一次,用于创建SessionFactory,即这个SessionFactory是线程安全的,只能被实例化一次,
save()方法和saveOrUpdate()方法的区别:

如果使用save,一个对象如果已经被持久化了,此时如果再次调用save方法,会出现异常,此时使用saveOrUpdate就可以解决这个问题,因为它会自动判断该对象是否已经持久化,如果已经持久化,将执行更新操作,否则执行添加操作,如果标识(主键)的生成策略是自增型的,则使用Session对象的save和saveOrUpdate方法是完全相同的;

session的save,saveOrUpdate方法(crud)除了查询,都必须是在事务环境中完成的,并需要commit方法提交事务,记录才能成功添加到数据表中;如果不提交commit事务,则这一次的id会被占用,但是写不到数据库;


Hibernate对象的三种状态:

1>瞬时态(Transient)(VO,Value Object)

2>持久态(Persistent)(PO,Persisence Object)

3>托管态(Detached)(VO,Value Object)

由new关键字创建的对象,如果他与数据库中的数据没有任何关联,也没有通过Session实例进行任何持久化操作,则该对象处于瞬时态,瞬时对象一旦不再被其他对象引用,那么很快被java虚拟机回收;

通过save和saveOrUpdate方法,可以将瞬时对象转变为持久对象,同时将对象中携带的数据插入到数据库的表中,处于持久态的对象在数据库中具有相应的记录,并拥有一个持久化标识,持久态对象位于一个session实例的缓存中,即总是与一个session实例相关联,当session清理缓存时,会根据持久对象的属性的变化同步更新到数据库;

持久对象的相关联的session实例执行delete方法后,持久态对象转变为瞬时态,同时删除数据库中相对应的记录,该对象不再与数据库的记录相关联;

当持久态对象相关联的的session实例执行close方法,clear或者evict方法后,持久对象转变为托管对象,此后,如果这个对象中的属性值发生变化,不会再将变化同步到数据库中;

托管状态对象如果不在被任何对象引用,将很快被垃圾回收,如果重新关联到session上时,托管状态再次转变为持久态,托管对象具有数据库记录标识,可以用seassion的update或者saveOrUpdate方法将托管状态转变为持久态,即对象与数据库记录同步

托管对象与瞬时对象的相同之处:如果不再被任何对象引用,将很快被垃圾回收;

托管对象与瞬时对象的不同之处:托管对象有数据库记录标识,瞬时态没有;

瞬时态或托管态转变为持久态的方法:

sava:瞬时态到持久态;.

load,get:获得对象的状态处于持久态;

find:获得的list集合中的对象处于持久态;(这个方法没找到,没有测试)

update,saveOrUpdate,lock方法可以将托管状态转变为持久态;(API提示lock这个方法已经过时)


持久态转变为托管状态的方法:

close:调用后,session的缓存会被清空,缓存中所有的持久态对象状态都转变为托管状态,处于托管状态的对象称为游离对象,当其不在被引用时,会虚拟机回收;

evict:可将session缓存中的一个指定的持久态对象删除,使其转变为托管状态,当缓存中存放大量处于持久态的对象时,为了节省内存空间,可以调用evict方法删除一些持久态对象;

0 0