2008年4月30日
#
其实就是关键一句话:
window.opener.document.getElementById("XXX").value=“123456”;
例程如下:
http://www.blogjava.net/Files/junglesong/ParentChildWnd20080520140659.rar
类之间关联的Hibernate表现
在Java程序中,类之间存在多种包含关系,典型的三种关联关系有:一个类拥有另一个类的成员,一个类拥有另一个类的集合的成员;两个类相互拥有对象的集合的成员.在Hibernate中,我们可以使用映射文件中的many-to-one, one-to-many, many-to-many来实现它们.这样的关系在Hibernate中简称为多对一,一对多和多对多.
多对一的类代码
事件与地点是典型的多对一关系,多个事件可以在一个地点发生(时间不同),一个地点可发生多个事件.它们的对应关系是(多)事件对(一)地点.
两个类的代码如右:
public class Event{
private String id;
private String name;
private Location location;
}
public class Location{
private String id;
private String name;
}
多对一的映射文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.hibernate.auction">
<class name="com.sitinspring.domain.Event"
table="Event_TB">
<id name="id" column="ID" >
<generator class="uuid.hex"/>
</id>
<property name="name" column="name" />
<many-to-one name="location" column="locationId" class="com.sitinspring.domain.Location"/>
</class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.hibernate.auction">
<class name="com.sitinspring.domain.Location"
table="Location_TB">
<id name="id" column="ID" >
<generator class="uuid.hex"/>
</id>
<property name="name" column="name" />
</class>
</hibernate-mapping>
多对一的表数据
一对多的类代码
如果一个用户有多个权限,那么User类和Privilege类就构成了一对多的关系,User类将包含一个Privilege类的集合.
public class User{
private String id;
private String name;
private Set<Privilege> privileges=new LinkedHashSet<Privilege>();
}
public class Privilege{
private String id;
private String userId;
private int privilegeLevel;
}
一对多的映射文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.hibernate.auction">
<class name="com.sitinspring.domain.User"
table="User_TB">
<id name="id" column="ID" >
<generator class="uuid.hex"/>
</id>
<property name="name" column="name" />
<set name="privileges">
<key column="userId"/>
<one-to-many class="com.sitinspring.domain.Privilege"/>
</set>
</class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.hibernate.auction">
<class name="com.sitinspring.domain.Privilege"
table="Privilege_TB">
<id name="id" column="ID" >
<generator class="uuid.hex"/>
</id>
<property name="userId" column="userId" />
<property name="privilegeLevel" column="privilegeLevel" />
</class>
</hibernate-mapping>
一对多的表数据
多对多
多对多关系 是指两个类相互拥有对方的集合,如文章和标签两个类,一篇文章可能有多个标签,一个标签可能对应多篇文章.要实现这种关系需要一个中间表的辅助.
类代码如右:
public class Article{
private String id;
private String name;
private Set<Tag> tags = new HashSet<Tag>();
}
public class Tag{
private String id;
private String name;
private Set<Article> articles = new HashSet<Article>();
}
多对多的映射文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.hibernate.auction">
<class name="com.sitinspring.domain.Article" table="ARTICLE_TB">
<id name="id" column="ID" >
<generator class="uuid.hex"/>
</id>
<property name="name" column="NAME" />
<set name="tags" table="ARTICLETAG_TB" cascade="all" lazy="false">
<key column="ARTICLEID" />
<many-to-many column="TAGID" class="com.sitinspring.domain.Tag" />
</set>
</class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.hibernate.auction">
<class name="com.sitinspring.domain.Tag" table="TAG_TB">
<id name="id" column="ID" >
<generator class="uuid.hex"/>
</id>
<property name="name" column="NAME" />
<set name="articles" table="ARTICLETAG_TB" cascade="all" lazy="false">
<key column="TAGID" />
<many-to-many column="ARTICLEID" class="com.sitinspring.domain.Article" />
</set>
</class>
</hibernate-mapping>
多对多的表数据
源码下载:
http://www.blogjava.net/Files/junglesong/HibernateMapping20080430203526.rar
Criteria查询
Hibernate中的Criteria API提供了另一种查询持久化的方法。它让你能够使用简单的API动态的构建查询,它灵活的特性通常用于搜索条件的数量可变的情况。
Criteria查询之所以灵活是因为它可以借助Java语言,在Java的帮助下它拥有超越HQL的功能。Criteria查询也是Hibernate竭力推荐的一种面向对象的查询方式。
Criteria查询的缺点在于只能检索完整的对象,不支持统计函数,它本身的API也抬高了一定的学习坡度。
Criteria查询示例代码
Session session=HibernateUtil.getSession();
Criteria criteria=session.createCriteria(User.class);
// 条件一:名称以关开头
criteria.add(Restrictions.like("name", "关%"));
// 条件二:email出现在数组中
String[] arr={"1@2.3","2@2.3","3@2.3"};
criteria.add(Restrictions.in("email", arr));
// 条件三:password等于一
criteria.add(Restrictions.eq("password", "1"));
// 排序条件:按登录时间升序
criteria.addOrder(Order.asc("lastLoginTime"));
List<User> users=(List<User>)criteria.list();
System.out.println("返回的User实例数为"+users.size());
for(User user:users){
System.out.println(user);
}
HibernateUtil.closeSession(session);
Criteria查询实际产生的SQL语句
select
this_.ID as ID0_0_,
this_.name as name0_0_,
this_.pswd as pswd0_0_,
this_.email as email0_0_,
this_.lastLoginTime as lastLogi5_0_0_,
this_.lastLoginIp as lastLogi6_0_0_
from
USERTABLE_OKB this_
where
this_.name like '关%'
and this_.email in (
'1@2.3', '2@2.3', '3@2.3'
)
and this_.pswd='1'
order by
this_.lastLoginTime asc
注:参数是手工加上的。
HQL介绍
Hibernate中不使用SQL而是有自己的面向对象查询语言,该语言名为Hibernate查询语言(Hibernate Query Language).HQL被有意设计成类似SQL,这样开发人员可以利用已有的SQL知识,降低学习坡度.它支持常用的SQL特性,这些特性被封装成面向对象的查询语言,从某种意义上来说,由HQL是面向对象的,因此比SQL更容易编写.
本文将逐渐介绍HQL的特性.
查询数据库中所有实例
要得到数据库中所有实例,HQL写为”from 对象名”即可,不需要select子句,当然更不需要Where子句.代码如右.
Query query=session.createQuery("from User");
List<User> users=(List<User>)query.list();
for(User user:users){
System.out.println(user);
}
限制返回的实例数
设置查询的maxResults属性可限制返回的实例(记录)数,代码如右:
Query query=session.createQuery("from User order by name");
query.setMaxResults(5);
List<User> users=(List<User>)query.list();
System.out.println("返回的User实例数为"+users.size());
for(User user:users){
System.out.println(user);
}
分页查询
分页是Web开发的常见课题,每种数据库都有自己特定的分页方案,从简单到复杂都有.在Hibernate中分页问题可以通过设置firstResult和maxResult轻松的解决.
代码如右:
Query query=session.createQuery("from User order by name");
query.setFirstResult(3);
query.setMaxResults(5);
List<User> users=(List<User>)query.list();
System.out.println("返回的User实例数为"+users.size());
for(User user:users){
System.out.println(user);
}
条件查询
条件查询只要增加Where条件即可.
代码如右:
Hibernate中条件查询的实现方式有多种,这种方式的优点在于能显示完整的SQL语句(包括参数)如下.
select
user0_.ID as ID0_,
user0_.name as name0_,
user0_.pswd as pswd0_,
user0_.email as email0_,
user0_.lastLoginTime as lastLogi5_0_,
user0_.lastLoginIp as lastLogi6_0_
from
USERTABLE_OKB user0_
where
user0_.name like '何%'
public static void fetchByName(String prefix){
Session session=HibernateUtil.getSession();
Query query=session.createQuery("from User where name like'"+prefix+"%'");
List<User> users=(List<User>)query.list();
System.out.println("返回的User实例数为"+users.size());
for(User user:users){
System.out.println(user);
}
HibernateUtil.closeSession(session);
}
位置参数条件查询
HQL中也可以象jdbc中PreparedStatement一样为SQL设定参数,但不同的是下标从0开始.
代码如右:
public static void fetchByPos(String prefix){
Session session=HibernateUtil.getSession();
Query query=session.createQuery("from User where name=?");
// 注意下标是从0开始,和jdbc中PreparedStatement从1开始不同
query.setParameter(0, prefix);
List<User> users=(List<User>)query.list();
System.out.println("返回的User实例数为"+users.size());
for(User user:users){
System.out.println(user);
}
HibernateUtil.closeSession(session);
}
命名参数条件查询
使用位置参数条件查询最大的不便在于下标与?号位置的对应上,如果参数较多容易导致错误.这时采用命名参数条件查询更好.
使用命名参数时无需知道每个参数的索引位置,这样就可以节省填充查询参数的时间.
如果有一个命名参数出现多次,那在每个地方都会设置它.
public static void fetchByNamedParam(){
Session session=HibernateUtil.getSession();
Query query=session.createQuery("from User where name=:name");
query.setParameter("name", "李白");
List<User> users=(List<User>)query.list();
System.out.println("返回的User实例数为"+users.size());
for(User user:users){
System.out.println(user);
}
HibernateUtil.closeSession(session);
}
命名查询
命名查询是嵌在XML映射文件中的查询。通常,将给定对象的所有查询都放在同一文件中,这种方式可使维护相对容易些。命名查询语句写在映射定义文件的最后面。
执行代码如下:
Session session=HibernateUtil.getSession();
Query query=session.getNamedQuery("user.sql");
List<User> users=(List<User>)query.list();
System.out.println("返回的User实例数为"+users.size());
for(User user:users){
System.out.println(user);
}
HibernateUtil.closeSession(session);
映射文件节选:
<hibernate-mapping package="org.hibernate.auction">
<class name="com.sitinspring.domain.User"
table="USERTABLE_OKB" lazy="false">
<id name="id" column="ID" >
<generator class="uuid.hex"/>
</id>
<property name="name" column="name" />
<property name="password" column="pswd" />
<property name="email" column="email" />
<property name="lastLoginTime" column="lastLoginTime" />
<property name="lastLoginIp" column="lastLoginIp" />
</class>
<query name="user.sql">
<![CDATA[from User where email='2@2.3']]>
</query>
</hibernate-mapping>
主要的Hibernate组件
Configuration类
Configuration类启动Hibernate的运行环境部分,用于加载映射文件以及为它们创建一个SessionFacotry。完成这两项功能后,就可丢弃Configuration类。
// 从hibernate.cfg.xml创建SessionFactory 示例
sessionFactory = new Configuration().configure()
.buildSessionFactory();
SessionFactory类
Hibernate中Session表示到数据库的连接(不止于此),而SessionFactory接口提供Session类的实例。
SessionFactory实例是线程安全的,通常在整个应用程序中共享。
从Configuration创建SessionFacotry的代码如右。
// 从hibernate.cfg.xml创建SessionFactory 示例
SessionFactory sessionFactory = new Configuration().configure()
.buildSessionFactory();
Session类
Session表示到数据库的连接,session类的实例是到Hibernate框架的主要接口,使你能够持久化对象,查询持久化以及将持久化对象转换为临时对象。
Session实例不是线程安全的,只能将其用于应用中的事务和工作单元。
创建Session实例的代码如右:
SessionFactory sessionFactory = new Configuration().configure()
.buildSessionFactory();
Session session=sessionFactory.openSession();
保存一个对象
用Hibernate持久化一个临时对象也就是将它保存在Session实例中:
对user实例调用save时,将给该实例分配一个生成的ID值,并持久化该实例,在此之前实例的id是null,之后具体的id由生成器策略决定,如果生成器类型是assignd,Hibernate将不会给其设置ID值。
Flush()方法将内存中的持久化对象同步到数据库。存储对象时,Session不会立即将其写入数据库;相反,session将大量数据库写操作加入队列,以最大限度的提高性能。
User user=new User(“Andy”,22);
Session session=sessionFatory.openSession();
session.save(user);
session.flush();
session.close();
保存或更新一个对象
Hibernate提供了一种便利的方法用于在你不清楚实例对应的数据在数据库中的状态时保存或更新一个对象,也就是说,你不能确定具体是要保存save还是更新update,只能确定需要把对象同步到数据库中。这个方法就是saveOrUpdate。
Hibernate在持久化时会查看实例的id属性,如果其为null则判断此对象是临时的,在数据库中找不到对应的实例,其后选择保存这个对象;而不为空时则意味着对象已经持久化,应该在数据库中更新该对象,而不是将其插入。
User user=。。。;
Session session=sessionFatory.openSession();
session.saveOrUpdate(user);
Session.flush();
session.close();
删除一个对象
从数据库删除一个对象使用session的delete方法,执行删除操作后,对象实例依然存在,但数据库中对应的记录已经被删除。
User user=。。。;
Session session=sessionFatory.openSession();
session.delete(user);
session.flush();
session.close();
以ID从数据库中取得一个对象
如果已经知道一个对象的id,需要从数据库中取得它,可以使用Session的load方法来返回它。代码如右.
注意此放在id对应的记录不存在时会抛出一个HibernateException异常,它是一个非检查性异常。对此的正确处理是捕获这个异常并返回一个null。
使用此想法如果采用默认的懒惰加载会导致异常,对此最简单的解决方案是把默认的懒惰加载属性修改为false。如右:
User user=(User)session.load(User.class,"008");
session.close();
-----------------------------------------------
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.hibernate.auction">
<class name="com.sitinspring.domain.User"
table="USERTABLE_OKB" lazy="false">
<id name="id" column="ID" >
<generator class="uuid.hex"/>
</id>
。。。。
</class>
</hibernate-mapping>
检索一批对象
检索一批对象需要使用HQL,session接口允许你创建Query对象以检索持久化对象,HQL是面向对象的,你需要针对类和属性来书写你的HQL而不是表和字段名。
从数据库中查询所有用户对象如下:
Query query=session.createQuery(“from User”);// 注意这里User是类名,from前没有select。
List<User> users=(List<User>)query.list();
从数据库中查询名为“Andy”的用户如下:
String name=“Andy”;
Query query=session.createQuery(“from User where name=‘”+name+”’”);
List<User> users=(List<User>)query.list();
以上方法类似于Statement的写法,你还可以如下书写:
Query query=session.createQuery("from User user where user.name = :name");
query.setString("name", “Andy");
List<User> users=(List<User>)query.list();
Hibernate的映射文件
映射文件也称映射文档,用于向Hibernate提供关于将对象持久化到关系数据库中的信息.
持久化对象的映射定义可全部存储在同一个映射文件中,也可将每个对象的映射定义存储在独立的文件中.后一种方法较好,因为将大量持久化类的映射定义存储在一个文件中比较麻烦,建议采用每个类一个文件的方法来组织映射文档.使用多个映射文件还有一个优点:如果将所有映射定义都存储到一个文件中,将难以调试和隔离特定类的映射定义错误.
映射文件的命名规则是,使用持久化类的类名,并使用扩展名hbm.xml.
映射文件需要在hibernate.cfg.xml中注册,最好与领域对象类放在同一目录中,这样修改起来很方便.
领域对象和类
public class User{
// ID
private String id;
// 名称
private String name;
// 密码
private String password;
// 邮件
private String email;
// 上次登录时间
private String lastLoginTime;
// 上次登录ip
private String lastLoginIp;
public User(String name,String password,String email){
this.name=name;
this.password=password;
this.email=email;
}
}
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping package="org.hibernate.auction">
<class name="com.sitinspring.domain.User"
table="USERTABLE_OKB" lazy="false">
<id name="id" column="ID" >
<generator class="uuid.hex"/>
</id>
<property name="name" column="name" />
<property name="password" column="pswd" />
<property name="email" column="email" />
<property name="lastLoginTime" column="lastLoginTime" />
<property name="lastLoginIp" column="lastLoginIp" />
</class></hibernate-mapping>
hibernate.cfg.xml中的映射文件设置
<?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 name="java:comp/env/hibernate/SessionFactory">
<!-- JNDI数据源设置 -->
<property name="connection.datasource">
java:comp/env/jdbc/myoracle
</property>
<!-- SQL方言,org.hibernate.dialect.OracleDialect适合所有Oracle数据库 -->
<property name="dialect">
org.hibernate.dialect.OracleDialect
</property>
<!-- 显示SQL语句 -->
<property name="show_sql">true</property>
<!-- SQL语句整形 -->
<property name="format_sql">true</property>
<!-- 启动时创建表.这个选项在第一次启动程序时放开,以后切记关闭 -->
<!-- <property name="hbm2ddl.auto">create</property> -->
<!-- 持久化类的映射文件 -->
<mapping resource="com/sitinspring/domain/User.hbm.xml" />
<mapping resource="com/sitinspring/domain/Privilege.hbm.xml" />
<mapping resource="com/sitinspring/domain/Article.hbm.xml" />
<mapping resource="com/sitinspring/domain/Record.hbm.xml" />
</session-factory>
</hibernate-configuration>
映射文件物理位置示例
映射文件的基本结构
映射定义以hibernate-mapping元素开始, package属性设置映射中非限定类名的默认包.设置这个属性后,对于映射文件中列出的其它持久化类,只需给出类名即可.要引用指定包外的持久化类,必须在映射文件中提供全限定类名.
在hibernate-mapping标签之后是class标签.class标签开始指定持久化类的映射定义.table属性指定用于存储对象状态的关系表.class元素有很多属性,下面将逐个介绍.
ID
Id元素描述了持久化类的主码以及他们的值如何生成.每个持久化类必须有一个ID元素,它声明了关系表的主码.如右:
Name属性指定了持久化类中用于保存主码值的属性,该元素表明,User类中有一个名为id的属性.如果主码字段与对象属性不同,则可以使用column属性.
<id name="id" column="ID" >
<generator class="uuid.hex"/>
</id>
生成器
生成器创建持久化类的主码值.Hibernate提供了多个生成器实现,它们采用了不同的方法来创建主码值.有的是自增长式的,有点创建十六进制字符串, 还可以让外界生成并指定对象ID,另外还有一种Select生成器你那个从数据库触发器trigger检索值来获得主码值.
右边使用了用一个128-bit的UUID算法生成字符串类型的标识符, 这在一个网络中是唯一的(使用了IP地址)。UUID被编码为一个32位16进制数字的字符串 .这对字段类型是字符串的id字段特别有效.UUID作为ID字段主键是非常合适的,比自动生成的long类型id方式要好。
UUID示例
<id name="id" column="ID" >
<generator class="uuid.hex"/>
</id>
自动增长的id
<id name="id" column="ID" type="long">
<generator class="native"/>
</id>
属性
在映射定义中,property元素与持久化对象的一个属性对应,name表示对象的属性名,column表示对应表中的列(字段),type属性指定了属性的对象类型,如果type被忽略的话,Hibernate将使用运行阶段反射机制来判断类型.
<property name="name" column="name" />
<property name="password" column="pswd" />
<property name="email" column="email" />
<property name="lastLoginTime" column="lastLoginTime" />
<property name="lastLoginIp" column="lastLoginIp" />
获取Hibernate
在创建Hibernate项目之前,我们需要从网站获得最新的Hibernate版本。Hibernate主页是www.hibernate.org,找到其菜单中的download连接,选择最新的Hibernate版本即可。下载后将其解开到一个目录中。
右边是解开后的主要目录。其中最重要的是hibernate.jar,它包含全部框架代码;lib目录,包括Hibernate的所有依赖库;doc目录,包括JavDocs和参考文档。
Hibernate的配置文件
Hibernate能够与从应用服务器(受控环境,如Tomcat,Weblogic,JBoss)到独立的应用程序(非受控环境,如独立应用程序)的各种环境和谐工作,这在一定程度上要归功于其配置文件hibernate.cfg.xml,通过特定的设置Hibernate就能与各种环境配合。右边是hibernate.cfg.xml的一个示例。
配置Hibernate的所有属性是一项艰巨的任务,下面将依此介绍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 name="java:comp/env/hibernate/SessionFactory">
<!-- JNDI数据源设置 -->
<property name="connection.datasource">
java:comp/env/jdbc/myoracle
</property>
<!-- SQL方言,org.hibernate.dialect.OracleDialect适合所有Oracle数据库 -->
<property name="dialect">
org.hibernate.dialect.OracleDialect
</property>
<!-- 显示SQL语句 -->
<property name="show_sql">true</property>
<!-- SQL语句整形 -->
<property name="format_sql">true</property>
<!-- 启动时创建表.这个选项在第一次启动程序时放开,以后切记关闭 -->
<!-- <property name="hbm2ddl.auto">create</property> -->
<!-- 持久化类的配置文件 -->
<mapping resource="com/sitinspring/domain/User.hbm.xml" />
<mapping resource="com/sitinspring/domain/Privilege.hbm.xml" />
<mapping resource="com/sitinspring/domain/Article.hbm.xml" />
<mapping resource="com/sitinspring/domain/Record.hbm.xml" />
</session-factory>
</hibernate-configuration>
使用Hibernate管理的JDBC连接
右边配置文件中的Database connection settings 部分制定了Hibernate管理的JDBC连接, 这在非受控环境如桌面应用程序中很常见。
其中各项属性为:
connection.driver_class:用于特定数据库的JDBC连接类
connection.url:数据库的完整JDBC URL
connection.username:用于连接到数据库的用户名
connection.password:用户密码
这种方案可用于非受控环境和基本测试,但不宜在生产环境中使用。
<?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">org.hsqldb.jdbcDriver</property>
<property name="connection.url">jdbc:hsqldb:hsql://localhost</property>
<property name="connection.username">sa</property>
<property name="connection.password"></property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.HSQLDialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
。。。。。。。。
</session-factory>
</hibernate-configuration>
使用JNDI 数据源
在受控环境中,我们可以使用容器提供的数据源,这将使数据库访问更加快捷,右边就是使用Tomcat提供的数据源的配置部分。
附:Server.Xml中的数据源设置
<Context path="/MyTodoes" reloadable="true" docBase="E:\Program\Programs\MyTodoes" workDir="E:\Program\Programs\MyTodoes\work" >
<Resource name="jdbc/myoracle" auth="Container"
type="javax.sql.DataSource" driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:@192.168.104.173:1521:orcl"
username="hy" password="123456" maxActive="20" maxIdle="10"
maxWait="-1"/>
</Context>
<?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 name="java:comp/env/hibernate/SessionFactory">
<!-- JNDI数据源设置 -->
<property name="connection.datasource">
java:comp/env/jdbc/myoracle
</property>
<!-- SQL方言,org.hibernate.dialect.OracleDialect适合所有Oracle数据库 -->
<property name="dialect">
org.hibernate.dialect.OracleDialect
</property>
</hibernate-configuration>
数据库方言
Dialect属性能告知Hibernate执行特定的操作如分页时需要使用那种SQL方言,如MySql的分页方案和Oracle的大相径庭,如设置错误或没有设置一定会导致问题。
附录:常见的数据库方言
DB2 :org.hibernate.dialect.DB2Dialect
MySQL :org.hibernate.dialect.MySQLDialect
Oracle (any version) :org.hibernate.dialect.OracleDialect
Oracle 9i/10g :org.hibernate.dialect.Oracle9Dialect
Microsoft SQL Server :org.hibernate.dialect.SQLServerDialect
Sybase Anywhere :org.hibernate.dialect.SybaseAnywhereDialect
<?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 name="java:comp/env/hibernate/SessionFactory">
<!-- JNDI数据源设置 -->
<property name="connection.datasource">
java:comp/env/jdbc/myoracle
</property>
<!-- SQL方言,org.hibernate.dialect.OracleDialect适合所有Oracle数据库 -->
<property name="dialect">
org.hibernate.dialect.OracleDialect
</property>
<!-- 显示SQL语句 -->
<property name="show_sql">true</property>
<!-- SQL语句整形 -->
<property name="format_sql">true</property>
</hibernate-configuration>
其它属性
show_sql:它可以在程序运行过程中显示出真正执行的SQL语句来,建议将这个属性始终打开,它将有益于错误诊断。
format_sql:将这个属性设置为true能将输出的SQL语句整理成规范的形状,更方便用于查看SQL语句。
hbm2ddl.auto:将其设置为create能在程序启动是根据类映射文件的定义创建实体对象对应的表,而不需要手动去建表,这在程序初次安装时很方便。
如果表已经创建并有数据,切记关闭这个属性,否则在创建表时也会清除掉原有的数据,这也许会导致很严重的后果。
从后果可能带来的影响来考虑,在用户处安装完一次后就应该删除掉这个节点
<hibernate-configuration>
<session-factory name="java:comp/env/hibernate/SessionFactory">
。。。。。。
<!-- 显示SQL语句 -->
<property name="show_sql">true</property>
<!-- SQL语句整形 -->
<property name="format_sql">true</property>
<!-- 启动时创建表.这个选项在第一次启动程序时放开,以后切记关闭 -->
<!-- <property name="hbm2ddl.auto">create</property> -->
。。。。。。
</hibernate-configuration>
映射定义
在hibernate.cfg.xml中,还有一个重要部分就是映射定义,这些文件用于向Hibernate提供关于将对象持久化到关系数据库的信息。
一般来说,领域层有一个领域对象就有一个映射文件,建议将它们放在同一目录(domain)下以便查阅和修改,映射文件的命名规则是:持久化类的类名+.hbm.xml
<?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 name="java:comp/env/hibernate/SessionFactory">
<!-- JNDI数据源设置 -->
<property name="connection.datasource">
java:comp/env/jdbc/myoracle
</property>
。。。。。。
<!-- 持久化类的配置文件 -->
<mapping resource="com/sitinspring/domain/User.hbm.xml" />
<mapping resource="com/sitinspring/domain/Privilege.hbm.xml" />
<mapping resource="com/sitinspring/domain/Article.hbm.xml" />
<mapping resource="com/sitinspring/domain/Record.hbm.xml" />
</session-factory>
</hibernate-configuration>
本文假定读者已经熟知以下知识
能够熟练使用JDBC创建Java应用程序;
创建过以数据库为中心的应用
理解基本的关系理论和结构化查询语言SQL (Strutured Query Language)
Hibernate
Hibernate是一个用于开发Java应用的对象/关系映射框架。它通过在数据库中为开发人员存储应用对象,在数据库和应用之间提供了一座桥梁,开发人员不必编写大量的代码来存储和检索对象,省下来的精力更多的放在问题本身上。
持久化与关系数据库
持久化的常见定义:使数据的存活时间超过创建该数据的进程的存活时间。数据持久化后可以重新获得它;如果外界进程没有修改它,它将与持久化之前相同。对于一般应用来说,持久化指的是将数据存储在关系数据库中。
关系数据库是为管理数据而设计的,它在存储数据方面很流行,这主要归功于易于使用SQL来创建和访问。
关系数据库使用的模型被称为关系模型,它使用二维表来表示数据。这种数据逻辑视图表示了用户如何看待包含的数据。表可以通过主码和外码相互关联。主码唯一的标识了表中的一行,而外码是另一个表中的主码。
对象/关系阻抗不匹配
关系数据库是为管理数据设计的,它适合于管理数据。然而,在面向对象的应用中,将对象持久化为关系模型可能会遇到问题。这个问题的根源是因为关系数据库管理数据,而面向对象的应用是为业务问题建模而设计的。由于这两种目的不同,要使这两个模型协同工作可能具有挑战性。这个问题被称为 对象/关系阻抗不匹配(Object/relational impedance mismatch)或简称为阻抗不匹配
阻抗不匹配的几个典型方面
在应用中轻易实现的对象相同或相等,这样的关系在关系数据库中不存在。
在面向对象语言的一项核心特性是继承,继承很重要,因为它允许创建问题的精确模型,同时可以在层次结构中自上而下的共享属性和行为。而关系数据库不支持继承的概念。
对象之间可以轻易的实现一对一,一对多和多对多的关联关系,而数据库并不理解这些,它只知道外码指向主码。
对象/关系映射
前页列举了一些阻抗不匹配的问题,当然开发人员是可以解决这些问题,但这一过程并不容易。对象/关系映射(Object/Relational Mapping)就是为解决这些问题而开发的。
ORM在对象模型和关系模型之间架起了一座桥梁,让应用能够直接持久化对象,而不要求在对象和关系之间进行转换。Hibernate就是ORM工具中最成功的一种。它的主要优点是简单,灵活,功能完备和高效。
Hibernate的优点之一:简单
Hibernate不像有些持久化方案那样需要很多的类和配置属性,它只需要一个运行阶段配置文件已经为每个要持久化的应用对象指定一个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">
<hibernate-mapping package="org.hibernate.auction">
<class name="com.sitinspring.domain.User"
table="USERTABLE_OKB" lazy="false">
<id name="id" column="ID" >
<generator class="uuid.hex"/>
</id>
<property name="name" column="name" />
<property name="password" column="pswd" />
<property name="email" column="email" />
<property name="lastLoginTime" column="lastLoginTime" />
<property name="lastLoginIp" column="lastLoginIp" />
</class>
</hibernate-mapping>
Hibernate的优点之二:功能完备
Hibernate支持所有的面向对象特性,包括继承,自定义对象类型和集合。它可以让你创建模型时不必考虑持久层的局限性。
Hibernate提供了一个名为HQL的查询语言,它与SQL非常相似,只是用对象属性名代替了表的列。很多通过SQL实现的常用功能都能用HQL实现。
Hibernate的优点之三:高效
Hibernate使用懒惰加载提高了性能,在Hibernate并不在加载父对象时就加载对象集合,而只在应用需要访问时才生成。这就避免了检索不必要的对象而影响性能。
Hibernate允许检索主对象时选择性的禁止检索关联的对象,这也是一项改善性能的特性。
对象缓存在提高应用性能方面也发挥了很大的作用。Hibernate支持各种开源和缓存产品,可为持久化类或持久化对象集合启用缓存。
总结
在同一性,继承和关联三方面,对象模型和关系模型存在着阻抗不匹配,这是众多ORM框架致力解决的问题,hibernate是这些方案中最成功的一个,它的主要优点是简单,灵活,功能完备和高效。
使用Hibernate不要求领域对象实现特别的接口或使用应用服务器,它支持集合,继承,自定义数据类型,并携带一种强大的查询语言HQL,能减少很多持久化方面的工作量,使程序员能把更多精力转移到问题本身上来。