- 浏览: 60580 次
- 性别:
- 来自: 上海
文章分类
最新评论
一个User 属性id的类型定义错(定义为String)出项了错误,应为int,在many2one的工程中出项了异常,且数据库操作也发生了异常。 下面介绍一下hibernate的配置问题: 1、新建java项目 2、创建User Library,加入如下jar <!DOCTYPE hibernate-configuration PUBLIC <hibernate-configuration> <mapping resource="com/bjsxt/hibernate/User.hbm.xml" /> 4、定义实体类 5、定义User类的映射文件User.hbm.xml 6、将User.hbml.xml文件加入到 7、编写hbm2ddl工具类,将实体类生成数据库表 //读取hibernate.cfg.xml文件 8、开发客户端 测试实体对象的生命周期 junit简介: 了解get和load的区别? //不会发出查询sql,因为load方法实现了lazy(懒加载或延迟加载) 实体类---表 采用<class>标签映射成数据库表,通过<property>标签将普通属性映射成表字段 注意:如果实体类和实体类中的属性和sql中的关键字重复,必须采用table或column重新命名 实体类的设计原则: 主键生成策略: 一对一主键关联映射:让两个实体对象的id保持相同,这样可以避免多余的字段被创建 具体映射: <id name="id"> 需要在idcard映射文件中加入<one-to-one>标签指向person,指示hibernate如何加载person Person.hbm.xml <?xml version="1.0"?> 一对唯一外键关联映射是多对一关联映射的特例 可以采用<many-to-one>标签,指定多的一端的unique=true,这样就限制了多的一端的 多重性为一。 主要是unique属性的设置。 其中IdCard.hbm.xml Person.hbm.xml <?xml version="1.0"?> 一对一唯一外键关联双向,需要在另一端(idcard),添加<one-to-one>标签,指示hibernate如何加载 Person.hbm.xml <?xml version="1.0"?> IdCard.hbm.xml <?xml version="1.0"?> session flush测试: session flush方法主要做了两件事: //因为user的主键生成策略为native,所以调用session.save后,将执行insert语句,返回有数据库生成的id //因为user的主键生成侧路采用的是uuid,所以调用完成save后,只是将user纳入到了session的管理 //因为user的主键生成策略为native,所以调用session.save后,将执行insert语句,返回有数据库生成的id //////////////////////////////////////// User3 user = new User3(); User3 user = new User3(); //////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ ////////////////////////////////// //////////////////////////// //////////////////////////////// ////////////////////////////////// 多对一关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是多指向一 也就是说一对多和多对一的映射策略是一样的,只是站的角度不同。 * 因为不是在student这一端维护关系,所以student不知道是哪个班的, 所以需要发出多余的update语句来更新关系 hihernate一对多关联映射(双向Classes<----->Student) 一对多双向关联映射: inverse的值有两种,“true”和“false”。inverse="false"是默认的值 我们说inverse设立不当会导致性能低下,其实是说inverse设立不当,会产生多余重复的SQL语句甚至致使JDBC exception的throw。这是我们在建立实体类关系时必须需要关注的地方。一般来说,inverse=true是推荐使用,双向关联中双方都设置 inverse=false的话,必会导致双方都重复更新同一个关系。但是如果双方都设立inverse=true的话,双方都不维护关系的更新,这也是 不行的,好在一对多中的一端:many-to-one默认是inverse=false,避免了这种错误的产生。但是多对多就没有这个默认设置了,所以很 多人经常在多对多的两端都使用inverse=true,结果导致连接表的数据根本没有记录,就是因为他们双分都没有责任维护关系。所以说,双向关联中最 好的设置是一端为inverse=true,一端为inverse=false。一般inverse=false会放在多的一端,那么有人提问了, many-to-many两边都是多的,inverse到底放在哪儿?其实hibernate建立多对多关系也是将他们分离成两个一对多关系,中间连接一个连接表。所以通用存在一对多的关系,也可以这样说:一对多是多对多的基本组成部分。 关于inverse属性: Student.hbm.xml <?xml version="1.0"?> User.hbm.xml hibernate支持lazy策略只有在session打开状态下有效 <class>标签上的lazy特性只对普通属性起作用 //////////////////////////////////////// class Student class.hbf.xml test1 test2 设置<class>标签上的lazy=false,集合的lazy为默认(true) test3 设置集合上的lazy=false,其它默认 test4 test5 test6 <class>标签上的lazy不会影响到单端关联上的lazy特性 1、理解如何映射 2、理解如何存储 get支持多态查询 那么,将每个具体类都映射成一张表,即生成t_bird和t_pig表分别含有字段 <class name="Animal" abstract="true"> margin-top: 1em; margin-right: 0px; margin-bottom: 0.5em; margin-left: 0px; p
Hibernate初始了解笔记汇集 收藏
String做主键用uuid整数做主键用native
第一个hibernate项目
* HIBERNATE_HOME/hibernate3.jar
* HIBERNATE_HOME/lib/*.jar
* MySql jdbc驱动
3、创建hibernate配置文件hibernate.cfg.xml,为了便于调试最好加入log4j配置文件
如果不加入log4j的话,会出现异常。
下面是hibernate.cfg.xml文件的内容。
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<session-factory>
<property name="hibernate.connection.url">
jdbc:mysql://localhost/hibernate_first
</property>
<property name="hibernate.connection.driver_class">
com.mysql.jdbc.Driver
</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">sunyuan</property>
<property name="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name="hibernate.show_sql">true</property>
</session-factory>
</hibernate-configuration>
<?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>
<class name="com.sy.hibernate.User">
<id name="id">
<generator class="uuid"/><!-- 主键设置方式,String类型的为uuid Int的是native-->
</id>
<property name="name"/>
<property name="password"/>
<property name="createTime"/>
<property name="expireTime"/>
</class>
</hibernate-mapping>hibernate.cfg.xml文件中其实就是<mapping resource="com/sy/hibernate/User.hbm.xml" />
主要代码:
Configuration cfg = new Configuration().configure();
SchemaExport export = new SchemaExport(cfg);
export.create(true, true);
为了方便跟踪sql执行,在hibernate.cfg.xml文件中加入<property name="hibernate.show_sql">true</property>
* 编写测试类xxxTest,需要继承TestCase即,junit.framework.TestCase
* 编写单元测试方法,测试方法必须以test开头,测试方法不能含有参数和返回值,如:
public void testHello1() {}
* 最好单元测试的代码单独建立一个目录,解决这个问题可以采用新建一个SourceFolder,然后再建一个和源文件一样的名字的包即可。
了解Hibernate中CRUD操作
* get不支持lazy,load支持lazy
就是说,//马上发出查询sql,加载User对象
User user = (User)session.get(User.class, "402880d01b9bf210011b9bf2a2ff0001");
//延迟加载:只有真正使用这个对象的时候,才加载(发出sql语句)如:System.out.println("user.name=" + user.getName());才加载。
//hibernate延迟加载实现原理是代理方式
User user = (User)session.load(User.class, "402880d01b9bf210011b9bf2a2ff0001");
* 采用get加载数据,如果没有匹配的数据,返回null,而load则抛出异常
transient状态的特征?
* 在数据库中没有与之匹配的数据
* 没有纳入session的管理
persistent状态的特征?
* persistent状态的对象在数据库中有与之匹配的数据
* 纳入了session的管理
* 在清理缓存(脏数据检查)的时候,会和数据库同步
detached状态的特征?
* 在数据库中有与之匹配的数据
* 没有纳入session的管理
//手动构造的detached状态的对象即将id设为数据库中存在的即可。
User user = new User();
user.setId("43553545");//这里的id必须在数据库中存在。否则抛出org.hibernate.StaleObjectStateException
hibernate基本映射
实体类中的普通属性---表字段
所谓普通属性指不包括自定义类、集合和数组等
* 实现一个默认的(即无参数的)构造方法(constructor)
* 提供一个标识属性(identifier property)(可选)
* 使用非final的类 (可选)
* 为持久化字段声明访问器(accessors)
uuid、native和assigned
hibernate一对一主键关联映射(单向关联Person---->IdCard)
<!-- person的主键来源idCard,也就是共享idCard的主键 -->
<generator class="foreign">
<param name="property">idCard</param>
</generator>
</id>
<property name="name"/>
<!-- one-to-one标签的含义,指示hibernate怎么加载它的关联对象,默认根据主键加载,
constrained="true", 表明当前主键上存在一个约束,person的主键作为外键参照了idCard
-->
<one-to-one name="idCard" constrained="true"/>
hibernate一对一主键关联映射(双向关联Person<---->IdCard)
默认根据主键加载
如:IdCard.hbm.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>
<class name="com.bjsxt.hibernate.IdCard" table="t_idcard">
<id name="id">
<generator class="native"/>
</id>
<property name="cardNo"/>
<one-to-one name="person"/>
</class>
</hibernate-mapping>
<!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.bjsxt.hibernate.Person" table="t_person">
<id name="id">
<generator class="foreign">
<param name="property">idCard</param>
</generator>
</id>
<property name="name"/>
<one-to-one name="idCard" constrained="true"/>
</class>
</hibernate-mapping>
如果为双向的映射,其实就是在原来单项映射的基础上,在idcard映射文件中加入<one-to-one>标签指向person,指示hibernate如何加载即:<one-to-one name="person"/>,其实两个相关联的实体相关的.hbm.xml文件,是相互的,无论哪一个写的具体,哪一个写的简单,都是可以的。就是所谓的此消彼长吧。
hibernate一对一唯一外键关联映射(单向关联Person---->IdCard)
<class name="Person" table="t_person">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<many-to-one name="idCard" unique="true"/>
</class>
<?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>
<class name="com.bjsxt.hibernate.IdCard" table="t_idcard">
<id name="id">
<generator class="native"/>
</id>
<property name="cardNo"/>
</class>
</hibernate-mapping>
<!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.bjsxt.hibernate.Person" table="t_person">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<many-to-one name="idCard" unique="true" column="asd"/>
</class>
</hibernate-mapping>
hibernate一对一唯一外键关联映射(双向关联Person<---->IdCard)
其关联对象,默认根据主键加载person,外键关联映射中,因为两个实体采用的是person的外键维护的关系,
所以不能指定主键加载person,而要根据person的外键加载,所以采用如下映射方式:
<one-to-one name="person" property-ref="idCard"/>
<!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.bjsxt.hibernate.Person" table="t_person">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<many-to-one name="idCard" unique="true"/>
</class>
</hibernate-mapping>
<!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.bjsxt.hibernate.IdCard" table="t_idcard">
<id name="id">
<generator class="native"/>
</id>
<property name="cardNo"/>
<one-to-one name="person" property-ref="idCard"/>
</class>
</hibernate-mapping>
* 清理缓存
* 执行sql
session在什么情况下执行flush
* 默认在事务提交时
* 显示的调用flush
* 在执行查询前,如:iterate
hibernate按照save(insert),update、delete顺序提交相关操作
//因为user的主键生成侧路采用的是uuid,所以调用完成save后,只是将user纳入到了session的管理
//不会发出insert语句,但是id已经生成,session中existsInDatebase状态为false
session.save(user);
//调用flush,hibernate会清理缓存,执行sql
//如果数据库的隔离级别设置为为提交读,那么我们可以看到flush过的数据
//并且session中existsInDatebase状态为true
session.flush();
//提交事务
//默认情况下commit操作会先执行flush清理缓存,所以不用显示的调用flush
//commit后数据是无法回滚的
tx.commit();
//纳入了session的管理,修改了session中existsInDatebase状态为true
//如果数据库的隔离级别设置为为提交读,那么我们可以看到save过的数据
session.save(user);
tx.commit();
//因为user的主键生成侧路采用的是uuid,所以调用完成save后,只是将user纳入到了session的管理
//不会发出insert语句,但是id已经生成,session中existsInDatebase状态为false
session.save(user);
//将user对象从session中逐出,即session的EntityEntries属性中逐出
session.evict(user);
//无法成功提交,因为hibernate在清理缓存时,在session的insertions集合中取出user对象进行insert操作后
//需要更新entityEntries属性中的existsInDatabase为true,而我们采用evict已经将user从session的entityEntries
//中逐出了,所以找不到相关数据,无法更新,抛出异常
tx.commit();
//不会发出insert语句,但是id已经生成,session中existsInDatebase状态为false
session.save(user);
//flush后hibernate会清理缓存,会将user对象保存到数据库中,将session中的insertions中的user对象
//清除,并且设置session中existsInDatebase的状态为true
session.flush();
//将user对象从session中逐出,即session的EntityEntries属性中逐出
session.evict(user);
//可以成功提交,因为hibernate在清理缓存时,在session的insertions集合中无法找到user对象
//所以就不会发出insert语句,也不会更新session中的existsInDatabase的状态
tx.commit();
//纳入了session的管理,修改了session中existsInDatebase状态为true
//如果数据库的隔离级别设置为为提交读,那么我们可以看到save过的数据
session.save(user);
//将user对象从session中逐出,即session的EntityEntries属性中逐出
session.evict(user);
//可以成功提交,因为hibernate在清理缓存时,在session的insertions集合中无法找到user对象
//所以就不会发出insert语句,也不会更新session中的existsInDatabase的状态
tx.commit();
user.setId("001");
user.setName("张三");
session.save(user);
user.setName("王五");
session.update(user);
User3 user3 = new User3();
user3.setId("002");
user3.setName("李四");
session.save(user3);
//////////////////////////////////////
//Hibernate: insert into t_user3 (name, password, create_time, expire_time, user_id) values (?, ?, ?, ?, ?)
//Hibernate: insert into t_user3 (name, password, create_time, expire_time, user_id) values (?, ?, ?, ?, ?)
//Hibernate: update t_user3 set name=?, password=?, create_time=?, expire_time=? where user_id=?
//hibernate按照save(insert),update、delete顺序提交相关操作,意思是无论上述的顺序怎么样,即使update在save前面,始终hibernate按照save(insert) ,update,delete的顺序执行。最后是delete
///////////////////////////////////////////////////////////////////////////////
user.setId("003");
user.setName("张三");
session.save(user);
user.setName("王五");
session.update(user);
session.flush();
User3 user3 = new User3();
user3.setId("004");
user3.setName("李四");
session.save(user3);
//Hibernate: insert into t_user3 (name, password, create_time, expire_time, user_id) values (?, ?, ?, ?, ?)
//Hibernate: update t_user3 set name=?, password=?, create_time=?, expire_time=? where user_id=?
//Hibernate: insert into t_user3 (name, password, create_time, expire_time, user_id) values (?, ?, ?, ?, ?)
//因为我们在session.udpate(user)后执行了flush,所以在清理缓存时执行flush前的sql不会生成
//sql会按照我们的意愿执行
tx.commit();
这时,会执行按顺序。主要在于flush方法的执行。
hihernate一对多关联映射(单向Classes----->Student)
/////////////////////////////////
public class Classes {
private int id;
private String name;
private Set students;
//////////////////////////////////
public class Student {
private int id;
private String name;
Classes.hbm.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="com.bjsxt.hibernate">
<class name="Classes" table="t_classes">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="students">
<key column="classesid"/>
<one-to-many class="Student"/>
</set>
</class>
</hibernate-mapping>
Student.hbm.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>
<class name="com.bjsxt.hibernate.Student" table="t_student">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
</class>
</hibernate-mapping>
生成的表为Student和Classes两个表,其中Student表中包含属性有name id classid
Classes表中包含属性有name id
这是怎么做到的映射呢?下面主要介绍一下文件的配置。在Classes.hbm.xml中怎么将class的id映射到Student表中呢?
主要用到<set name="students">
<key column="classesid"/>
<one-to-many class="Student">
</set>这里的students是Classes类的属性。
而在Student.hbm.xml中实际要三个属性标签,而只写了两个属性,而classesid在Classes.hbm.xml中已经关联了。
改天再把hibernate映射的源码看看。
一对多关联映射利用了多对一关联映射原理
一对多关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是一指向多
在一一端维护关系的缺点:
* 如果将t_student表里的classesid字段设置为非空,则无法保存
////////////////////////////////////////////////////////////////////////////////
* 在一一端的集合上使用<key>,在对方表中加入一个外键指向一一端
* 在多一端采用<many-to-one>
注意:<key>标签指定的外键字段必须和<many-to-one>指定的外键字段一致,否则引用字段的错误
如果在”一“一端维护一对多关联关系,hibernate会发出多余的udpate语句,所以我们一般在多
的一端来维护关联关系
inverse的作用:在hibernate中是通过inverse的设置来决定是有谁来维护表和表之间的关系的。
inverse主要用在一对多和多对多双向关联上,inverse可以被设置到集合标签<set>上,
默认inverse为false,所以我们可以从”一“一端和”多“一端维护关联关系,
如果设置成inverse为true,则我们只能从多一端来维护关联关系
注意:inverse属性,只影响数据的存储,也就是持久化
inverse和cascade
* inverse是关联关系的控制方向
* cascade操作上的连锁反应
双向关联:
////////////////////////////////////////
<!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.bjsxt.hibernate.Student" table="t_student">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<many-to-one name="classes" column="classesid"/>
</class>
</hibernate-mapping>
////////////////////////////////////////
Class.hbm.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="com.bjsxt.hibernate">
<class name="Classes" table="t_classes">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="students" inverse="true" cascade="all">
<key column="classesid"/>
<one-to-many class="Student"/>
</set>
</class>
</hibernate-mapping>
////////////////////////////////////////
hibernate多对多关联映射(单向User---->Role)
///////////////////////////////////////
User.hbm.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>
<class name="com.bjsxt.hibernate.User" table="t_user">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="roles" table="t_user_role">
<key column="userid"/>
<many-to-many class="com.bjsxt.hibernate.Role" column="roleid"/>
</set>
</class>
</hibernate-mapping>
////////////////////////////////////////Role.hbm.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>
<class name="com.bjsxt.hibernate.Role" table="t_role">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
</class>
</hibernate-mapping>
////////////////////////////////////////
hibernate多对多关联映射(双向User<---->Role)
////////////////////////////////////////
////////////////////////////////////////
<?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>
<class name="com.bjsxt.hibernate.User" table="t_user">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="roles" table="t_user_role">
<key column="userid"/>
<many-to-many class="com.bjsxt.hibernate.Role" column="roleid"/>
</set>
</class>
</hibernate-mapping>
////////////////////////////////////////
Role.hbm.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>
<class name="com.bjsxt.hibernate.Role" table="t_role">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="users" table="t_user_role" order-by="userid">
<key column="roleid"/>
<many-to-many class="com.bjsxt.hibernate.User" column="userid"/>
</set>
</class>
</hibernate-mapping>
////////////////////////////////////////映射方法:
<set name="roles" table="t_user_role">
<key column="userid"/>
<many-to-many class="com.bjsxt.hibernate.Role" column="roleid"/>
</set>
table属性值必须和单向关联中的table属性值一致
<key>中column属性值要与单向关联中的<many-to-many>标签中的column属性值一致
在<many-to-many>中的column属性值要与单向关联中<key>标签的column属性值一致
////////////////////////////////////////
hibernate lazy策略可以使用在:
* <class>标签上,可以取值:true/false
* <property>标签上,可以取值:true/false需要类增强工具
* <set><list>标签上,可以取值:true/false/extra
* <one-to-one><many-to-one>单端关联上,可以取值:false/proxy/noproxy
lazy概念:只有真正使用该对象时,才会创建,对于hibernate而言,正真使用的时候才会发出sql
例如:
Session session = null;
Group group = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
group = (Group)session.load(Group.class, 1);
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
//不能正确输出,抛出LazyInitializationException 异常,因为session已经关闭
//hibernate支持lazy策略只有在session打开状态下有效
System.out.println("group.name=" + group.getName());
////////////////////////////////////////
class Classes
int id;String name;Set students;
int id;String name;Classes classes;
<hibernate-mapping package="com.bjsxt.hibernate">
<class name="Classes" table="t_classes">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="students" inverse="true" cascade="all" >
<key column="classesid"/>
<one-to-many class="Student"/>
</set>
</class>
</hibernate-mapping>
设置<class>标签上的lazy=true,或者默认TRUE。其它默认
<class name="Classes" table="t_classes" lazy="true">
//不发sql
Classes classes = (Classes)session.load(Classes.class, 1);
//发sql,查询class
System.out.println("classes.name=" + classes.getName());
//不发sql
Set students = classes.getStudents();
//发sql,查询全部符合条件student的语句
for (Iterator iter=students.iterator(); iter.hasNext();) {
Student student = (Student)iter.next();
System.out.println("student.name=" + student.getName());
}
//不发sql
Classes classes = (Classes)session.load(Classes.class, 1);
//发sql,查询class
System.out.println("classes.name=" + classes.getName());
//不发sql
Set students = classes.getStudents();
//发sql,查询全部符合条件student的语句
System.out.println("student.count=" + students.size());
<class name="Classes" table="t_classes" lazy="false">
//发sql,查询student
Classes classes = (Classes)session.load(Classes.class, 1);
//不发sql
System.out.println("classes.name=" + classes.getName());
//不发sql
Set students = classes.getStudents();
//发sql,查询符合条件的student语句
for (Iterator iter=students.iterator(); iter.hasNext();) {
Student student = (Student)iter.next();
System.out.println("student.name=" + student.getName());
}
<set name="students" inverse="true" cascade="all" lazy="false">
<key column="classesid"/>
<one-to-many class="Student"/>
</set>
//不发sql
Classes classes = (Classes)session.load(Classes.class, 1);
//不发sql
System.out.println("classes.name=" + classes.getName());
//发sql,分别查询出classes和student
Set students = classes.getStudents();
//不发sql
for (Iterator iter=students.iterator(); iter.hasNext();) {
Student student = (Student)iter.next();
System.out.println("student.name=" + student.getName());
}
Classes classes = (Classes)session.load(Classes.class, 1);
//不发sql
System.out.println("classes.name=" + classes.getName());
//发sql,分别查询出classes和student
Set students = classes.getStudents();
//不发sql
System.out.println("student.count=" + students.size());
设置集合上的lazy=extra,其它默认
<set name="students" inverse="true" cascade="all" lazy="extra">
<key column="classesid"/>
<one-to-many class="Student"/>
</set>
//不发sql
Classes classes = (Classes)session.load(Classes.class, 1);
//发sql,查询出classes
System.out.println("classes.name=" + classes.getName());
//不发sql
Set students = classes.getStudents();
//发sql,查询出student
for (Iterator iter=students.iterator(); iter.hasNext();) {
Student student = (Student)iter.next();
System.out.println("student.name=" + student.getName());
}
test7
//不发sql
Classes classes = (Classes)session.load(Classes.class, 1);
//发sql,查询出classes
System.out.println("classes.name=" + classes.getName());
//不发sql
Set students = classes.getStudents();
//发sql,智能的sql语句,查询出数目
System.out.println("student.count=" + students.size());
////////////////////////////////////////
hibernate在单端关联上的lazy策略,可以取值:false/proxy/noproxy
////////////////////////////////////////
下面的User.hbm.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>
<class name="com.bjsxt.hibernate.User" table="t_user" lazy="false">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<!--
<many-to-one name="group" column="groupid" cascade="all"/>
-->
<many-to-one name="group" column="groupid" />
</class>
</hibernate-mapping>
则这里的 <many-to-one name="group" column="groupid" lazy=""/>中lazy不受class中lazy的关联,就是说class中lazy的属性值与many-to-one中的lazy无关。如果,lazy设为false,那么在执行//不会发出sql
User user = (User)session.load(User.class, 1);
//会发出sql,发出两条sql分别加载User和Group
System.out.println("user.name=" + user.getName());
时,会发出两条sql语句。lazy的延迟机制在这里不做解释了。
//////////////////////////////////////// 原先看到在Hibernate3之后可以在Many to one 的关系映射中设置lazy属性,
<many-to-one name="brother" cascade="none" lazy="no-proxy" insert="true" column="brotherId" outer-join="false" update="false">
还以为和one to many一样,只要将lazy设为true就可以在不加载关联的对象呢,结果这个lazy的属性值只有proxy no-proxy 和false,试了其中任何一个值,结果都还是加载了关联的对象,后来想起class可以设置lazy的属性,就把关联的brother对象的类的lazy属性设为true,然后many to one中的lazy设为no-proxy后就实现了延迟加载,如果将many to one中的lazy属性设为false,系统还是会自动初始化brother对象。
</many-to-one><class name="com.demo.bean.Brother" lazy="true" table="brother">
//////////////////////////////////////////
总之,class中的lazy只会对普通属性相关联,与集合,many-to-one one-to-many 都无关。//////////////////////////////////////
每棵继承树映射成一张表
因为类继承树肯定是对应多个类,要把多个类的信息存放在一张表中,必须有某种机制来区分哪些记录是属于哪个类的。
这种机制就是,在表中添加一个字段,用这个字段的值来进行区分。用hibernate实现这种策略的时候,有如下步骤:
父类用普通的<class>标签定义
在父类中定义一个discriminator,即指定这个区分的字段的名称和类型
如:<discriminator column=”XXX” type=”string”/>
子类使用<subclass>标签定义,在定义subclass的时候,需要注意如下几点:
Subclass标签的name属性是子类的全路径名
在Subclass标签中,用discriminator-value属性来标明本子类的discriminator字段(用来区分不同类的字段)
的值Subclass标签,既可以被class标签所包含(这种包含关系正是表明了类之间的继承关系),也可以与class标
签平行。 当subclass标签的定义与class标签平行的时候,需要在subclass标签中,添加extends属性,里面的值
是父类的全路径名称。子类的其它属性,像普通类一样,定义在subclass标签的内部。
存储的时候hibernate会自动将鉴别字段值插入到数据库中,在加载数据的时候,hibernate能根据这个鉴别值
正确的加载对象
多态查询:在hibernate加载数据的时候能鉴别出正真的类型(instanceOf)
load只有在lazy=false,才支持多态查询
hql支持多态查询
////////////////////////////////////////
在这个试验中,有三个类Animal、Bird、Pig,它们的关系是,Animal是基类,其他两个是子类,Brid除了Animal的属性外,还有一个属性height,Pig有weight,在hibernate中生成一个表t_animal
对应的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="com.bjsxt.hibernate">
<class name="Animal" table="t_animal" lazy="false">
<id name="id">
<generator class="native"/>
</id>
<discriminator column="type" type="string"/><!--这里type="string"是hibernate自带的,与Java中的String没有关系。且该标签必须紧跟在标签<id>后-->
<property name="name"/>
<property name="sex"/>
<subclass name="Pig" discriminator-value="P">
<property name="weight"/>
</subclass>
<subclass name="Bird" discriminator-value="B">
<property name="height"/>
</subclass>
</class>
</hibernate-mapping>
////////////////////////////////////////
部分代码:
////////////////////////////////////////
session = HibernateUtils.getSession();
session.beginTransaction();
Animal animal = (Animal)session.load(Animal.class, 1);
//因为load默认只是lazy,因为我们看到的是Animal的代理对象
//所以通过instanceof是反应不出正真的对象类型的
//因此load在默认情况下是不支持多态查询的
if (animal instanceof Pig) {
System.out.println(animal.getName());
}else {
System.out.println("不是猪");
}
session.getTransaction().commit();
////////////////////////////////////////
上述中,介绍了怎么生成一张表,但是每个类都生成一个表,包括Animal类对应的表。类的关联和上述一样。
////////////////////////////////////////对应的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="com.bjsxt.hibernate">
<class name="Animal" table="t_animal">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<property name="sex"/>
<joined-subclass name="Pig" table="t_pig">
<key column="pid"/>
<property name="weight"/>
</joined-subclass>
<joined-subclass name="Bird" table="t_bird">
<key column="bid"/>
<property name="height"/>
</joined-subclass>
</class>
</hibernate-mapping>
////////////////////////////////////////
这和生成一张表的区别是:前者用到<joined-subclass>而一张表的是<subclass>其他的细节这里不再叙述。
////////////////////////////////////////
get支持多态查询,load不支持多态查询。只有将lazy设置为false,才支持多态查询,否则实行的是代理proxy
////////////////////////////////////////
id name sex height
id name sex weight
而父类Animal不映射成表。
///////////////////////////////////////
对应的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="com.bjsxt.hibernate">
<id>
<generator class="assigned"/>
</id>
<property name="name"/>
<property name="sex"/>
<union-subclass name="Pig" table="t_pig">
<property name="weight"/>
</union-subclass>
<union-subclass name="Bird" table="t_bird">
<property name="height"/>
</union-subclass>
</class>
</hibernate-mapping>
////////////////////////////////////////发表评论
相关推荐
在深入探讨《hibernate笔记.txt》所提及的关键知识点前,我们先来解析一下标题和描述中的核心概念。“自上而下的依赖,单向依赖,层与层之间最好依赖抽象”,这一描述实际上触及了软件架构设计中的关键原则,特别是...
《韩顺平.2011版.hibernate笔记》是一份针对Hibernate框架的详细学习资料,由知名IT讲师韩顺平在2011年编撰而成。Hibernate是Java开发领域中广泛使用的对象关系映射(ORM)框架,它极大地简化了数据库操作,使开发者...
【传智播客 Hibernate 笔记】是一份深入学习 Hibernate ORM 框架的资源集合,包括了 word 笔记、pdf 讲义、源代码以及相关分析图表和 jar 包,旨在帮助开发者全面理解并掌握 Hibernate 的核心概念与实际应用。...
《Hibernate笔记完整版》 在Web开发领域,Hibernate作为三大框架之一,扮演着至关重要的角色。本文将全面介绍Hibernate,包括其数据持久化的概念、优缺点对比,以及Hibernate的核心概念和编程步骤。 对象持久化是...
《韩顺平Hibernate笔记》是一份详尽记录了著名IT讲师韩顺平关于Hibernate框架讲解内容的资料集合。Hibernate作为Java领域中广泛使用的对象关系映射(ORM)框架,极大地简化了数据库操作,使得开发者可以更加专注于...
《韩顺平Hibernate笔记》是一份详尽的关于Hibernate框架的学习资料,由知名IT教育专家韩顺平编撰。Hibernate是Java开发中的一个强大的对象关系映射(ORM)框架,它简化了数据库与Java对象之间的交互,使得开发者可以...
Hibernate 是一个开源的对象关系映射(ORM)框架,它允许Java开发者使用面向对象的方式来操作数据库。这个框架将数据库操作转化为对Java对象的操作,简化了数据持久化的复杂度。以下是对Hibernate的一些关键知识点的...
### 尚学堂Hibernate笔记知识点详解 #### 一、项目初始化与环境搭建 1. **新建项目**:在IDE中创建一个新的Java项目。 2. **构建用户库并添加所需的JAR包**: - 右键点击项目 -> `Build Path` -> `Configure ...
培训期间的hibernate笔记 hibernate笔记 达内培训
hibernate笔记.pdf
总结起来,"韩顺平hibernate笔记及图解"涵盖了Hibernate的基础概念、核心组件、对象关系映射、查询机制、事务管理以及实体间的关系等内容。通过学习这份笔记,开发者能深入理解Hibernate的工作原理和使用技巧,提升...
【Spring+Hibernate笔记】这篇文档主要涵盖了在Web开发中使用Spring和Hibernate的基础知识。首先,我们从Spring的Hello World开始,了解如何配置JSP运行环境。 1.1. 配置JSP运行环境是开发Web应用的第一步。这包括...
【马士兵Hibernate笔记】是一份面向初学者的教程,旨在帮助读者深入了解Hibernate这一持久化框架。Hibernate是一个基于Java的ORM(对象关系映射)工具,它允许开发者将数据库操作转换为面向对象的方式,从而简化了...