- 浏览: 21504078 次
- 性别:
博客专栏
-
跟我学spring3
浏览量:2418686
-
Spring杂谈
浏览量:3008790
-
跟开涛学SpringMVC...
浏览量:5639490
-
Servlet3.1规范翻...
浏览量:259916
-
springmvc杂谈
浏览量:1597323
-
hibernate杂谈
浏览量:250220
-
跟我学Shiro
浏览量:5858959
-
跟我学Nginx+Lua开...
浏览量:702008
-
亿级流量网站架构核心技术
浏览量:785224
文章分类
- 全部博客 (329)
- 跟我学Nginx+Lua开发 (13)
- 跟我学spring (54)
- 跟开涛学SpringMVC (34)
- spring4 (16)
- spring杂谈 (50)
- springmvc杂谈 (22)
- 跟我学Shiro (26)
- shiro杂谈 (3)
- hibernate杂谈 (10)
- java开发常见问题分析 (36)
- 加速Java应用开发 (5)
- Servlet 3.1规范[翻译] (21)
- servlet3.x (2)
- websocket协议[翻译] (14)
- websocket规范[翻译] (1)
- java web (6)
- db (1)
- js & jquery & bootstrap (4)
- 非技术 (4)
- reminder[转载] (23)
- 跟叶子学把妹 (8)
- nginx (2)
- 架构 (19)
- flume架构与源码分析 (4)
最新评论
-
xxx不是你可以惹得:
认真看错误代码,有时候重启电脑就行了 醉了 我把数据库配置写死 ...
第十六章 综合实例——《跟我学Shiro》 -
dagger9527:
holyselina 写道您前面说到能获取调用是的参数数组,我 ...
【第六章】 AOP 之 6.6 通知参数 ——跟我学spring3 -
xxx不是你可以惹得:
Access denied for user 'root'@' ...
第十六章 综合实例——《跟我学Shiro》 -
dagger9527:
只有@AspectJ支持命名切入点,而Schema风格不支持命 ...
【第六章】 AOP 之 6.5 AspectJ切入点语法详解 ——跟我学spring3 -
dagger9527:
支持虽然会迟到,但永远不会缺席!
【第四章】 资源 之 4.3 访问Resource ——跟我学spring3
《Hibernate 关系映射》是我很早之前收集、总结整理的,在此也发上来 希望对大家有用。因为是很早之前写的,不当之处请指正。
一、概念:
关系:名词,事物之间相互作用、相互联系的状态。
关联:名词:表示对象(数据库表)之间的关系;动词:将对象(数据库表)之间通过某种方式联系起来。
映射:将一种形式转化为另一种形式,包括关系。
级联:动词,有关系的双方中操作一方,另一方也将采取一些动作。
值类型:对象不具备数据库同一性,属于一个实体实例其持久化状态被嵌入到所拥有的实体的表行中,没有标识符。
实体类型:具有数据库标识符。
二、数据库:
1、关系
2.1.1、一对一、一对多、多对多
2.1.2、如何表示? 外键+索引
2、级联:
2.2.1、级联删除
三、面向对象语言中(Java中):
1、关系
3.1.1、一对一、一对多、多对多
3.1.2、如何表示? 实例变量(对象+集合)
2、级联:
3.2.1、级联删除
3.2.2、级联更新
3.2.3、级联保存
四、如何把数据库关系表示为面向对象中的关系:
1、关联:将数据库表之间的关系转化为对象之间的关系;在Hibernate中总指实体之间的关系。
2、映射:完成java对象到数据库表的双向转换。
3、级联(可选):将数据库中的级联转化为对象中的级联(两者(对象和数据库表)没关系)。
4、Hibernate的表和对象的映射:
1、实体类型映射:
4.1.1、主键之间的映射
4.1.2、类属性与表字段的映射
4.1.3、组件映射
4.1.4、集合映射
2、实体关联关系映射:
4.2.1、关联关系映射
五、Hibernate映射示例:
5.1、实现
5.1.1、数据库表定义(主表)
5.1.1.1、用户表
CREATE TABLE TBL_USER ( UUID NUMBER(10) NOT NULL, NAME VARCHAR2(100), AGE NUMBER(10) NOT NULL, PROVINCE VARCHAR2(100), CITY VARCHAR2(100), STREET VARCHAR2(100), CONSTRAINT PK_USER PRIMARY KEY(UUID));
5.1.1.2、用户普通信息表(一个用户有一个资料)
CREATE TABLE TBL_USER_GENERAL ( UUID NUMBER(10) NOT NULL, REALNAME VARCHAR2(10), GENDER VARCHAR2(10), BIRTHDAY NUMBER(10), HEIGHT NUMBER(10), WEIGHT NUMBER(10) , CONSTRAINT PK_USER_GENERAL PRIMARY KEY(UUID), CONSTRAINT FK_USER_GENERAL FOREIGN KEY(UUID) REFERENCES TBL_USER(UUID));
5.1.1.3、农场表(一个用户有多个农场)
CREATE TABLE TBL_FARM ( UUID NUMBER(10) NOT NULL, NAME VARCHAR2(10), FK_USER_ID NUMBER(10), CONSTRAINT PK_FARM PRIMARY KEY(UUID), CONSTRAINT FK_USER_FARM FOREIGN KEY(FK_USER_ID) REFERENCES TBL_USER(UUID));
5.1.2、对象定义
5.1.2.1、用户地址Model
package cn.javass.h3test.model; public class AddressModel implements java.io.Serializable { private String province;//省 private String city;//市 private String street;//街道 }
5.1.2.2、用户Model
package cn.javass.h3test.model; import java.util.HashSet; import java.util.Set; public class UserModel implements java.io.Serializable { private int uuid; private String name;//名称 private int age;//年龄 private AddressModel address;//地址 private UserGeneralModel userGeneral;//用户普通信息 private Set<FarmModel> farms = new HashSet<FarmModel>();//拥有的农场 }
5.1.2.3、用户普通信息Model
package cn.javass.h3test.model; public class UserGeneralModel implements java.io.Serializable { private int uuid; private String realname;//真实姓名 private String gender;//性别 private String birthday;//生日 private int weight;//体重 private int height;//身高 private UserModel user;//所属用户 }
5.1.2.4、农场Model
package cn.javass.h3test.model; public class FarmModel implements java.io.Serializable { private int uuid; private String name;//农场的名称 private UserModel user;//所属用户 }
5.2、配置
5.2.1、实体类型映射:
5.2.1.1、主键的映射(UserModel.hbm.xml)
<id name="uuid"> <generator class="sequence"> <param name="sequence">user_uuid</param> </generator> </id>
5.2.1.2、类属性与表字段的映射(UserModel.hbm.xml)
<property name="name"/>
5.2.1.3、组件映射(UserModel.hbm.xml)
<component name="address" class="cn.javass.h3test.model.AddressModel"> <property name="province"/> <property name="city"/> <property name="street"/> </component>
5.2.1.4、集合映射(Set、List、Map) (都是通过外键连接的,,,默认延迟抓取)
Set:
private Set<String> farmSet = new HashSet<String>();
<set name="farmSet" table="TBL_FARM" > <key column="fk_user_id"/><!—该外键是tbl_farm的--> <element type="string" column="name"/> </set>
private List<String> farmList = new ArrayList<String>();
<list name="farmList" table="TBL_FARM"> <key column="fk_user_id"/> <list-index column="uuid"></list-index> <element type="string" column="name"/> </list>
private Map<Integer, String> farmMap = new HashMap<Integer, String>();
<map name="farmMap" table="TBL_FARM"> <key column="fk_user_id"/> <map-key type="int" column="uuid"/> <element type="string" column="name"></element> </map>
对于集合类型默认是延迟加载的,且只能单向导航,不能双向。
5.2.2、实体关联关系映射:
5.2.2.1、单向关联关系映射,不演示。
5.2.2.2、双向关联关系映射
单向 定义:不知道另一端什么情况,获取一端另一端自动获取,因为单向,你不知道另一侧是什么。 如 class A{ B b;} class B{ } 只能从A导航到B,不能从B导航到A 关系维护:另一端维护,如B维护 双向 定义:知道另一端(两个单向),从一端获取另一端,从另一端也能获取一端 如 class A{ B b;} class B{ A a;} 只能从A导航到B,也能从B导航到A 关系维护:两端,对关联的一侧所作的改变,会立即影响到另一侧 关联的多样性: 从一侧看是多对一,从另一侧看是一对多 另外还有一对一、多对多 EJB CMP:天生双向,对关联的一侧所作的改变,会立即影响到另一侧, 如userGeneral.set(user),则自动调用user.setUserGeneral(userGeneral) Hibernate、JPA:天生单向,两侧关系的维护是不同的关联,必须手工维护 如userGeneral.set(user),则需要手工调用user.setUserGeneral(userGeneral)。
5.2.2.3、一对一主键关系映射(非延迟抓取)
配置1(UserModel.hbm.xml)
<one-to-one name="userGeneral" cascade="all"/>
配置2(UserGeneralModel.hbm.xml)
<id name="uuid"> <generator class="foreign"> <param name="property">user</param> </generator> </id> <one-to-one name="user" class="cn.javass.h3test.model.UserModel"/>
关联的对象所对应的数据库表之间,通过一个外键引用对主键进行约束。
测试:保存对象,只需保存user,自动级联保存用户信息Model
UserModel user = new UserModel(); user.setName("昵称"); UserGeneralModel userGeneral = new UserGeneralModel(); userGeneral.setRealname("真实姓名"); userGeneral.setUser(user); user.setUserGeneral(userGeneral); session.save(user); //若没有cascade="all",这句必须 //session.save(userGeneral);
1、一对一必须手工维护双向关系。
2、cascade="all":表示保存user时自动保存userGeneral,否则还需要一条save(userGeneral)
3、constrained:添加把userGeneral表的主键映射到user主键的外键约束
5.2.2.4、一对多关系映射(父/子关系映射)
配置1(UserModel.hbm.xml)
<set name="farms" cascade="all"> <key column="fk_user_id"/> <one-to-many class="cn.javass.h3test.model.FarmModel"/> </set>
配置2(FarmModel.hbm.xml)
<many-to-one name="user" column="fk_user_id" class="cn.javass.h3test.model.UserModel">
测试:保存对象,只需保存user,自动级联保存用户信息Model
UserModel user = new UserModel(); user.setName("昵称"); UserGeneralModel userGeneral = new UserGeneralModel(); userGeneral.setRealname("真实姓名"); userGeneral.setUser(user); user.setUserGeneral(userGeneral); FarmModel farm = new FarmModel(); farm.setName("farm1"); farm.setUser(user); user.getFarms().add(farm); //session.save(farm);//若没有cascade=all的话需要这条语句 session.save(user);
以上配置有问题:
insert into TBL_USER (name, age, province, city, street, uuid) values (?, ?, ?, ?, ?, ?) insert into TBL_USER_GENERAL (realname, gender, birthday, weight, height, uuid) values (?, ?, ?, ?, ?, ?) insert into TBL_FARM (name, fk_user_id, uuid) values (?, ?, ?) update TBL_FARM set fk_user_id=? where uuid=?
1、持久化user(UserModel);
2、持久化user的一对一关系,即userGeneral(UserGeneralModel);
3、持久化user的一对多关系,即farms(Set<FarmModel>);
3.1、首先发现farm是TO,级联save;(因为在这可能是PO,PO的话就应该update,而不是save);
3.2、其次发现farm在farms集合中,因此需要更新外键(fk_user_id),即执行“update TBL_FARM set fk_user_id=? where uuid=? “。
解决这个问题:
告诉Hibernate应该只有一端来维护关系(外键),另一端不维护;通过指定<set>端的inverse=”true”,表示关系应该由farm端维护。即更新外键(fk_user_id)将由farm端维护。
配置修改(UserModel.hbm.xml)
<set name="farms" cascade="all" inverse="true"> <key column="fk_user_id"/> <one-to-many class="cn.javass.h3test.model.FarmModel"/> </set>
再测试:保存对象,只需保存user,自动级联保存用户信息Model
UserModel user = new UserModel(); user.setName("昵称"); UserGeneralModel userGeneral = new UserGeneralModel(); userGeneral.setRealname("真实姓名"); userGeneral.setUser(user); user.setUserGeneral(userGeneral); FarmModel farm = new FarmModel(); farm.setName("farm1"); farm.setUser(user); user.getFarms().add(farm); //session.save(farm);//若没有cascade=all的话需要这条语句 session.save(user);
更新外键,需要修改FarmModel的外键并update:
insert into TBL_USER (name, age, province, city, street, uuid) values (?, ?, ?, ?, ?, ?) insert into TBL_USER_GENERAL (realname, gender, birthday, weight, height, uuid) values (?, ?, ?, ?, ?, ?) insert into TBL_FARM (name, fk_user_id, uuid) values (?, ?, ?)
级联删除
1、当删除user时自动删除user下的farm
user = (UserModel) session.get(UserModel.class, 1); session.delete(user);
结果:
Hibernate: delete from TBL_USER_GENERAL where uuid=? Hibernate: delete from TBL_FARM where uuid=? Hibernate: delete from TBL_USER where uuid=?
2、删除user中的farms的一个元素
UserModel user = (UserModel) session.get(UserModel.class, 118); FarmModel farm = (FarmModel) user.getFarms().toArray()[user.getFarms().size() - 1]; user.getFarms().remove(farm);//1.必须先从集合删除 session.delete(farm);//2.然后才能删除
结果:
Hibernate: delete from TBL_FARM where uuid=?
如果将子对象从集合中移除,实际上我们是想删除它。要实现这种要求,就必须使用cascade="all-delete-orphan"
。无需再调用session.delete(farm)
5.2.2.5、多对多关系映射:不用
为什么不使用多对多:当添加新字段时给谁?
那实际项目如何用:拆成两个一对多。
六、涉及的SQL语句会按照下面的顺序发出执行:
1、查询
1、所有对实体进行插入的语句,其顺序按照对象执行Session.save()的时间顺序
2、所有对实体进行更新的语句
3、所有进行集合插入的语句 (实体类型)
4、所有对集合元素进行删除、更新或插入的语句 (值类型)
5、所有进行集合删除的语句 (实体类型)
6、所有对实体进行删除的语句,其顺序按照对象执行Session.delete()的时间顺序
(有一个例外是,如果对象使用native方式来生成ID(持久化标识)的话,它们一执行save就会被插入。)
七、影响关系映射抓取的cfg配置:
hibernate.max_fetch_depth |
为单向关联(一对一, 多对一)的外连接抓取(outer join fetch)树设置最大深度. 值为0意味着将关闭默认的外连接抓取. 取值 建议在0到3之间取值 |
hibernate.default_batch_fetch_size |
为Hibernate关联的批量抓取设置默认数量. 取值 建议的取值为4, 8, 和16 |
如果你的数据库支持ANSI, Oracle或Sybase风格的外连接, 外连接抓取通常能通过限制往返数据库次数 (更多的工作交由数据库自己来完成)来提高效率. 外连接抓取允许在单个SELECTSQL语句中, 通过many-to-one, one-to-many, many-to-many和one-to-one关联获取连接对象的整个对象图.
将hibernate.max_fetch_depth设为0能在全局 范围内禁止外连接抓取. 设为1或更高值能启用one-to-one和many-to-one外连接关联的外连接抓取, 它们通过 fetch="join"来映射.
八、抓取策略
1、抓取策略定义
抓取策略(fetching strategy)
是指:当应用程序需要在(Hibernate实体对象图的)关联关系间进行导航的时候, Hibernate如何获取关联对象的策略。抓取策略可以在O/R映射的元数据中声明,也可以在特定的HQL
或条件查询(Criteria
Query)
中重载声明。
2、Hibernate3 定义了如下几种抓取策略:
连接抓取(Join fetching) - Hibernate通过 在SELECT
语句使用OUTER JOIN
(外连接)来
获得对象的关联实例或者关联集合。 默认非延迟加载
集合抓取需要通过配置fetch="join"来指定。下行数据太多(冗余),IO
//配置 fetch="join"( lazy="true"不起作用了) session.get(UserModel.class, 118);//是获取对象的 Hibernate: select … from TBL_USER usermodel0_, TBL_FARM farms1_ where usermodel0_.uuid=farms1_.fk_user_id(+) and usermodel0_.uuid=?
查询抓取(Select fetching) - 另外发送一条 SELECT
语句抓取当前对象的关联实体或集合。除非你显式的指定lazy="false"
禁止延迟抓取(lazy fetching),否则只有当你真正访问关联关系的时候,才会执行第二条select语句。
////配置 lazy=”true”默认(或者lazy="false" fetch="select") session.get(UserModel.class, 118);//是获取对象的 Hibernate: select … from TBL_USER usermodel0_ where usermodel0_.uuid=? Hibernate: select … from TBL_FARM farms0_ where farms0_.fk_user_id=?
默认用于lazy="true"情况的集合抓取,如果lazy="false",
需要指定fetch="select"来通过查询抓取。会造成DB的CPU利用率非常高,计算密集
子查询抓取(Subselect fetching) - 另外发送一条SELECT
语句抓取在前面查询到(或者抓取到)的所有实体对象的关联集合。除非你显式的指定lazy="false"
禁止延迟抓取(lazy fetching),否则只有当你真正访问关联关系的时候,才会执行第二条select语句。
当通过Query等接口查询多个实体时,如果指定fetch="subselect"则将通过子查询获取集合
////配置fetch="subselect" Query q = session.createQuery("from UserModel"); System.out.println(q.list()); Hibernate: select …… from TBL_USER usermodel0_ Hibernate: select …… from TBL_FARM farms0_ where farms0_.fk_user_id in (select usermodel0_.uuid from TBL_USER usermodel0_)
批量抓取(Batch fetching) - 对查询抓取的优化方案, 通过指定一个主键或外键列表,Hibernate使用单条SELECT
语句获取一批对象实例或集合。
当通过Query等接口查询多个实体时,如果指定farm的batch-size="……"则将通过使用单条SELECT
语句获取一批对象实例或集合。
Query q = session.createQuery("from UserModel"); List<UserModel> userList = q.list(); System.out.println(userList); Hibernate: select … TBL_USER usermodel0_ Hibernate: select … from TBL_FARM farms0_ where farms0_.fk_user_id in (?, ?)
可指定全局批量抓取策略: hibernate.default_batch_fetch_size,取值:建议的取值为4, 8, 和16。
如果batch-size="4",而某个user有19个农场,Hibernate将只需要执行五次查询,分别为4、4、4、4、3。
测试必须数据量足够多,,如果只有一条不行
3、使用延迟属性抓取(Using lazy property fetching)
属性的延迟载入要求在其代码构建时加入二进制指示指令(bytecode instrumentation),如果你的持久类代码中未含有这些指令, Hibernate将会忽略这些属性的延迟设置,仍然将其直接载入。
Hibernate3对单独的属性支持延迟抓取,这项优化技术也被称为组抓取(fetch groups)。 请注意,该技术更多的属于市场特性。在实际应用中,优化行读取比优化列读取更重要。但是,仅载入类的部分属性在某些特定情况下会有用,例如在原有表中拥有几百列数据、数据模型无法改动的情况下。
4、Hibernate在抓取时会lazy区分下列各种情况:
立即抓取 - 当宿主被加载时,关联、集合或属性被立即抓取。
Lazy collection fetching,延迟集合抓取- 直到应用程序对集合进行了一次操作时,集合才被抓取。(对集合而言这是默认行为。)
Extra-lazy" collection fetching,"Extra-lazy"集合抓取 -对集合类中的每个元素而言,都是直到需要时才去访问数据库。除非绝对必要,Hibernate不会试图去把整个集合都抓取到内存里来(适用于非常大的集合)。
// lazy="extra" Query q = session.createQuery("from UserModel"); Iterator it = q.iterate(); System.out.println(((UserModel)it.next()).getFarms().size()); //或 List<UserModel> userList = q.list(); System.out.println(userList.get(0).getFarms().size()); Hibernate: select usermodel0_.uuid as col_0_0_ from TBL_USER usermodel0_ Hibernate: select … from TBL_USER usermodel0_ where usermodel0_.uuid=? Hibernate: select count(uuid) from TBL_FARM where fk_user_id =? //或 Hibernate: select … from TBL_USER usermodel0_ Hibernate: select count(uuid) from TBL_FARM where fk_user_id =?
对于调用size()、contains、isEmpty是一种优化,不读取所有级联,而是按条件生产不同的sql。
Proxy fetching,代理抓取 - 对返回单值的关联而言,当其某个方法被调用,而非对其关键字进行get操作时才抓取。
//默认 <many-to-one name="user" ……lazy="false"/> FarmModel farm = (FarmModel) session.get(FarmModel.class, 121); System.out.println(farm.getUser().getUuid()); Hibernate: select … from TBL_FARM farmmodel0_ where farmmodel0_.uuid=? Hibernate: select … from TBL_USER usermodel0_ where usermodel0_.uuid=? 118
// <many-to-one name="user" ……lazy="proxy"/> FarmModel farm = (FarmModel) session.get(FarmModel.class, 121); System.out.println(farm.getUser().getUuid()); Hibernate: select … from TBL_FARM farmmodel0_ where farmmodel0_.uuid=? 118
注:如果constrained="false"或基于主键的一对一
, 不可能使用代理,Hibernate会采取预先抓取!
"No-proxy" fetching,非代理抓取 - 对返回单值的关联而言,当实例变量被访问的时候进行抓取。与上面的代理抓取相比,这种方法没有那么“延迟”得厉害(就算只访问标识符,也会导致关联抓取)但是更加透明,因为对应用程序来说,不再看到proxy。这种方法需要在编译期间进行字节码增强操作,因此很少需要用到。
Lazy attribute fetching,属性延迟加载 - 对属性或返回单值的关联而言,当其实例变量被访问的时候进行抓取。需要编译期字节码强化,因此这一方法很少是必要的。
这里有两个正交的概念:关联何时被抓取,以及被如何抓取(会采用什么样的SQL语句)。不要混淆它们!我们使用抓取
来改善性能。我们使用延迟
来定义一些契约,对某特定类的某个脱管的实例,知道有哪些数据是可以使用的。
九、抓取优化
1、集合N+1:
可以使用batch-size来减少获取次数,即如batch-size=”10”,则是N/10+1。
开启二级缓存。
对于集合比较小且一定会用到的可采用fetch=”join”,这样只需一条语句。
2、笛卡尔积问题:
<set name="farms" cascade="all,all-delete-orphan" inverse="true" fetch="join"> <key column="fk_user_id"/> <one-to-many class="cn.javass.h3test.model.FarmModel"/> </set> <set name="hourses" cascade="all,all-delete-orphan" inverse="true" fetch="join"> <key column="fk_user_id"/> <one-to-many class="cn.javass.h3test.model.HourseModel"/> </set>
如上配置产生笛卡尔积问题。
select user.*,farm.*,hourse.* from UserModel user, FarmModel farm, HourseModel hourse
where user.uuid=farm.fk_user.uuid(+) and
user.uuid=hourse.fk_user.uuid(+)
解决方案:
1、fetch=”subselect”,子查询,每个User查询一套笛卡尔积
2、完全不采用关系映射。
3、大集合采用批处理,按块获取集合数据
4、复杂SQL太复杂太慢:找DBA优化,索引等是否有效,是否加载了过多的无用数据,拆分SQL,按需获取数据。
5、按需获取1对多中的集合。
6、缓存
……
不当之处,请多多指正!
评论
执行Query q = session.createQuery("from UserModel"); 后
因为UserGeneralModel的主键关联关系,导致如下状态:给每个user都查询了一次tbl_user_general表,而不是直接用join方式一次取到User和UserGeneralModel,不知是什么原因?
Hibernate:
select
usergenera0_.uuid as uuid2_1_,
usergenera0_.realname as realname2_1_,
usergenera0_.gender as gender2_1_,
usergenera0_.birthday as birthday2_1_,
usergenera0_.weight as weight2_1_,
usergenera0_.height as height2_1_,
usermodel1_.uuid as uuid1_0_,
usermodel1_.name as name1_0_,
usermodel1_.age as age1_0_,
usermodel1_.province as province1_0_,
usermodel1_.city as city1_0_,
usermodel1_.street as street1_0_
from
tbl_user_general usergenera0_,
tbl_user usermodel1_
where
usergenera0_.uuid=usermodel1_.uuid(+)
and usergenera0_.uuid=?
2014-06-13 09:14:54 [org.hibernate.type.IntegerType]-[DEBUG] binding '25' to parameter: 1
2014-06-13 09:14:54 [org.hibernate.type.IntegerType]-[DEBUG] returning '25' as column: uuid1_0_
2014-06-13 09:14:54 [org.hibernate.type.StringType]-[DEBUG] returning '萧峰' as column: realname2_1_
2014-06-13 09:14:54 [org.hibernate.type.StringType]-[DEBUG] returning null as column: gender2_1_
2014-06-13 09:14:54 [org.hibernate.type.StringType]-[DEBUG] returning null as column: birthday2_1_
2014-06-13 09:14:54 [org.hibernate.type.IntegerType]-[DEBUG] returning '0' as column: weight2_1_
2014-06-13 09:14:54 [org.hibernate.type.IntegerType]-[DEBUG] returning '0' as column: height2_1_
Hibernate:
select
usergenera0_.uuid as uuid2_1_,
usergenera0_.realname as realname2_1_,
usergenera0_.gender as gender2_1_,
usergenera0_.birthday as birthday2_1_,
usergenera0_.weight as weight2_1_,
usergenera0_.height as height2_1_,
usermodel1_.uuid as uuid1_0_,
usermodel1_.name as name1_0_,
usermodel1_.age as age1_0_,
usermodel1_.province as province1_0_,
usermodel1_.city as city1_0_,
usermodel1_.street as street1_0_
from
tbl_user_general usergenera0_,
tbl_user usermodel1_
where
usergenera0_.uuid=usermodel1_.uuid(+)
and usergenera0_.uuid=?
2014-06-13 09:14:54 [org.hibernate.type.IntegerType]-[DEBUG] binding '26' to parameter: 1
2014-06-13 09:14:54 [org.hibernate.type.IntegerType]-[DEBUG] returning '26' as column: uuid1_0_
2014-06-13 09:14:54 [org.hibernate.type.StringType]-[DEBUG] returning '萧峰' as column: realname2_1_
2014-06-13 09:14:54 [org.hibernate.type.StringType]-[DEBUG] returning null as column: gender2_1_
2014-06-13 09:14:54 [org.hibernate.type.StringType]-[DEBUG] returning null as column: birthday2_1_
2014-06-13 09:14:54 [org.hibernate.type.IntegerType]-[DEBUG] returning '0' as column: weight2_1_
2014-06-13 09:14:54 [org.hibernate.type.IntegerType]-[DEBUG] returning '0' as column: height2_1_
Hibernate:
select
usergenera0_.uuid as uuid2_1_,
usergenera0_.realname as realname2_1_,
usergenera0_.gender as gender2_1_,
usergenera0_.birthday as birthday2_1_,
usergenera0_.weight as weight2_1_,
usergenera0_.height as height2_1_,
usermodel1_.uuid as uuid1_0_,
usermodel1_.name as name1_0_,
usermodel1_.age as age1_0_,
usermodel1_.province as province1_0_,
usermodel1_.city as city1_0_,
usermodel1_.street as street1_0_
from
tbl_user_general usergenera0_,
tbl_user usermodel1_
where
usergenera0_.uuid=usermodel1_.uuid(+)
and usergenera0_.uuid=?
2014-06-13 09:14:54 [org.hibernate.type.IntegerType]-[DEBUG] binding '27' to parameter: 1
2014-06-13 09:14:54 [org.hibernate.type.IntegerType]-[DEBUG] returning '27' as column: uuid1_0_
2014-06-13 09:14:54 [org.hibernate.type.StringType]-[DEBUG] returning '萧峰' as column: realname2_1_
2014-06-13 09:14:54 [org.hibernate.type.StringType]-[DEBUG] returning null as column: gender2_1_
2014-06-13 09:14:54 [org.hibernate.type.StringType]-[DEBUG] returning null as column: birthday2_1_
2014-06-13 09:14:54 [org.hibernate.type.IntegerType]-[DEBUG] returning '0' as column: weight2_1_
2014-06-13 09:14:54 [org.hibernate.type.IntegerType]-[DEBUG] returning '0' as column: height2_1_
//A 和 B 是一对一关系
class A {
B b;
//getter setter
}
class B {
A a;
//getter setter
}
A a = new A();
B b = new B();
a.setB(b);
b.setA(a); // 每次都需要这样写,不知道有没有办法在 a.setB(b) 的时候自动调用
session.save(a);
@Entity @Table(".....") public class A{ private String mid; //主键是自定义的 private String mName; private B b;// 位置信息 \ private String status; //省略部分getter setter方法 @ManyToOne @joinColumn(name="b") public B getB(){ return b; } } @Entity @Table(".....") public class B{ private Long id; private String locationName; private String remark; }
关系如上所示:整个过程中我是针对Hibernate的Criteria封装,现在的场景描述:在前台页面中<input name='b.id'>传入后台在使用是Criteria如下所示:
Criteria c=session.createCriteria(A.class); c.add(Restrictions.eq("b.id",传入的值) ) c.list;
总是提示String类型转换Long类型错误
我想知道在b.id的类型是怎么判断的,从而来手动对传入的值进行转换,求解!!
这个可以考虑先写到 entity中,然后再获取 这是最简单的办法
比如!!
先绑定到A上,比如使用BeanWrapper
好的,我试试吧,这个没有使用过的!!
@Entity @Table(".....") public class A{ private String mid; //主键是自定义的 private String mName; private B b;// 位置信息 \ private String status; //省略部分getter setter方法 @ManyToOne @joinColumn(name="b") public B getB(){ return b; } } @Entity @Table(".....") public class B{ private Long id; private String locationName; private String remark; }
关系如上所示:整个过程中我是针对Hibernate的Criteria封装,现在的场景描述:在前台页面中<input name='b.id'>传入后台在使用是Criteria如下所示:
Criteria c=session.createCriteria(A.class); c.add(Restrictions.eq("b.id",传入的值) ) c.list;
总是提示String类型转换Long类型错误
我想知道在b.id的类型是怎么判断的,从而来手动对传入的值进行转换,求解!!
这个可以考虑先写到 entity中,然后再获取 这是最简单的办法
比如!!
先绑定到A上,比如使用BeanWrapper
@Entity @Table(".....") public class A{ private String mid; //主键是自定义的 private String mName; private B b;// 位置信息 \ private String status; //省略部分getter setter方法 @ManyToOne @joinColumn(name="b") public B getB(){ return b; } } @Entity @Table(".....") public class B{ private Long id; private String locationName; private String remark; }
关系如上所示:整个过程中我是针对Hibernate的Criteria封装,现在的场景描述:在前台页面中<input name='b.id'>传入后台在使用是Criteria如下所示:
Criteria c=session.createCriteria(A.class); c.add(Restrictions.eq("b.id",传入的值) ) c.list;
总是提示String类型转换Long类型错误
我想知道在b.id的类型是怎么判断的,从而来手动对传入的值进行转换,求解!!
这个可以考虑先写到 entity中,然后再获取 这是最简单的办法
比如!!
@Entity @Table(".....") public class A{ private String mid; //主键是自定义的 private String mName; private B b;// 位置信息 \ private String status; //省略部分getter setter方法 @ManyToOne @joinColumn(name="b") public B getB(){ return b; } } @Entity @Table(".....") public class B{ private Long id; private String locationName; private String remark; }
关系如上所示:整个过程中我是针对Hibernate的Criteria封装,现在的场景描述:在前台页面中<input name='b.id'>传入后台在使用是Criteria如下所示:
Criteria c=session.createCriteria(A.class); c.add(Restrictions.eq("b.id",传入的值) ) c.list;
总是提示String类型转换Long类型错误
我想知道在b.id的类型是怎么判断的,从而来手动对传入的值进行转换,求解!!
这个可以考虑先写到 entity中,然后再获取 这是最简单的办法
@Entity @Table(".....") public class A{ private String mid; //主键是自定义的 private String mName; private B b;// 位置信息 \ private String status; //省略部分getter setter方法 @ManyToOne @joinColumn(name="b") public B getB(){ return b; } } @Entity @Table(".....") public class B{ private Long id; private String locationName; private String remark; }
关系如上所示:整个过程中我是针对Hibernate的Criteria封装,现在的场景描述:在前台页面中<input name='b.id'>传入后台在使用是Criteria如下所示:
Criteria c=session.createCriteria(A.class); c.add(Restrictions.eq("b.id",传入的值) ) c.list;
总是提示String类型转换Long类型错误
我想知道在b.id的类型是怎么判断的,从而来手动对传入的值进行转换,求解!!
关系映射需要注意的点就是 保证只有一方维护关系即可
嗯,好的,我在实践中试试吧!!
关系映射需要注意的点就是 保证只有一方维护关系即可
遇到一个问题,一直无法解决:
1,实体类通过注解映射,
2,使用spring的管理hibernate的配置文件:添加如下,
<prop key="hibernate.hbm2ddl.auto">create</prop>
其他地方没有明显错误。
我只是在怀疑,使用注解是不是不能像是用hbm.xml上的自动生成数据表啊?
spring的版本是spring3.1.2
hibernate的版本是hibernate3.10
可以自动生成的,没问题
你的是什么问题?
遇到一个问题,一直无法解决:
1,实体类通过注解映射,
2,使用spring的管理hibernate的配置文件:添加如下,
<prop key="hibernate.hbm2ddl.auto">create</prop>
其他地方没有明显错误。
我只是在怀疑,使用注解是不是不能像是用hbm.xml上的自动生成数据表啊?
spring的版本是spring3.1.2
hibernate的版本是hibernate3.10
1.在applicationContext.xml中配置
<bean id="hibernateTemplete" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
然后在dao中
@Autowired
private HibernateTemplate hibernateTemplate;
hibernateTemplate.save(u)
2.
dao extends HibernateDaoSupport
直接使用:
getHibernateTemplate().save(u)
请问这两种用法有什么区别,那种是推荐用法?
谢谢!
2、HibernateDaoSupport 提供了setHibernateTemplate/setSessionFactory方法自动帮你new模板/提供getter方法 省去了我们写setter
1.在applicationContext.xml中配置
<bean id="hibernateTemplete" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
然后在dao中
@Autowired
private HibernateTemplate hibernateTemplate;
hibernateTemplate.save(u)
2.
dao extends HibernateDaoSupport
直接使用:
getHibernateTemplate().save(u)
请问这两种用法有什么区别,那种是推荐用法?
谢谢!
谢谢
还有一种是这个表里面的两个字段只做为复合主键,但是这这张表也要在hibernate里面声称对应的映射文件hbm.xml,然后还有用一个compose-id这个东东,不知道有没有其他的做法了,你一般是怎么处理这个中间表的。
就像你说的一样 处理 拆成两个1对多
那么你一般是用像我说的第一种还是第二种呢,我总觉得,我这里用过的第二种有点代码写得多,有点烦?
我一般选择第二种 这样 当有更多字段时可以放在中间表
哦,呵呵,多谢了,我公司现在就是用的第二种,第一种是我在一个外国网站上面看到一个老外把两个表的主键,既做复合主键也做复合外键的,我照着老外那个试了一下,也还可以,能跑得通。呵呵
你可以看一下SQL反模式,记得是第三章,关于主键设计的! 可以把两个表的主键直接作为中间表的主键和外键来设计,这个有时候我也这么用 看你喜欢哪种了。第二种 多了一个伪主键! 而且(aId, bId)需要建立唯一索引来完成 完整性约束
嗯,好滴,谢谢
还有一种是这个表里面的两个字段只做为复合主键,但是这这张表也要在hibernate里面声称对应的映射文件hbm.xml,然后还有用一个compose-id这个东东,不知道有没有其他的做法了,你一般是怎么处理这个中间表的。
就像你说的一样 处理 拆成两个1对多
那么你一般是用像我说的第一种还是第二种呢,我总觉得,我这里用过的第二种有点代码写得多,有点烦?
我一般选择第二种 这样 当有更多字段时可以放在中间表
哦,呵呵,多谢了,我公司现在就是用的第二种,第一种是我在一个外国网站上面看到一个老外把两个表的主键,既做复合主键也做复合外键的,我照着老外那个试了一下,也还可以,能跑得通。呵呵
你可以看一下SQL反模式,记得是第三章,关于主键设计的! 可以把两个表的主键直接作为中间表的主键和外键来设计,这个有时候我也这么用 看你喜欢哪种了。第二种 多了一个伪主键! 而且(aId, bId)需要建立唯一索引来完成 完整性约束
还有一种是这个表里面的两个字段只做为复合主键,但是这这张表也要在hibernate里面声称对应的映射文件hbm.xml,然后还有用一个compose-id这个东东,不知道有没有其他的做法了,你一般是怎么处理这个中间表的。
就像你说的一样 处理 拆成两个1对多
那么你一般是用像我说的第一种还是第二种呢,我总觉得,我这里用过的第二种有点代码写得多,有点烦?
我一般选择第二种 这样 当有更多字段时可以放在中间表
哦,呵呵,多谢了,我公司现在就是用的第二种,第一种是我在一个外国网站上面看到一个老外把两个表的主键,既做复合主键也做复合外键的,我照着老外那个试了一下,也还可以,能跑得通。呵呵
发表评论
-
spring data jpa bug分析—初始化时EntityManager不关闭原因
2013-06-03 07:31 46924环境 spring 3.2.3 RELEASE spr ... -
我是这样认识注解和XML的
2013-05-30 11:56 16310在使用jpa时,比如我使用hibernate作为实现,默认 ... -
jpa使用validator引发的注解和XML配置的思考
2013-05-30 11:53 0在使用jpa时,比如我使用hibernate作为实现,默认 ... -
测试jpa时需要注意的二级缓存
2013-05-24 06:02 14783最近写集成测试来 ... -
测试jpa时需要注意的二级缓存
2013-05-23 19:39 0最近写集成测试来测试一个实体+集合缓存的程序,单独执行没有问 ... -
hibernate SQLQuery oracle BUG
2013-05-22 16:41 5685数据库: oracle 测试的有问题的版本: ... -
混合jpa和jdbc集成测试时Connection第二次执行sql时被关闭原因及解决方案
2013-05-03 07:10 18194在继承AbstractTransactionalJUnit ... -
Hibernate自定义类型 集合--->字符串 存储
2013-04-21 09:30 7556场景: 角色[1]-----[*](资源[1]---[*] ... -
Hibernate自定义类型 对象--->序列化为字符串 存储
2013-04-21 09:22 4911在有些时候 我们可能序列化存储对象为字符串形式,比如会话序 ... -
Hibernate 二级缓存 总结整理
2012-05-13 07:50 35337和《Hibernate 关系映射 ... -
Hibernate存取JSON数据(换一种思路来存取数据)
2012-04-25 12:05 21792一、场景 public class OrderMo ...
相关推荐
1.2 Hibernate 关系映射 总结整理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 1.3 Hibernate 二级缓存 总结整理 . . . . . . . . . . . ....
1.2 Hibernate 关系映射 总结整理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 1.3 Hibernate 二级缓存 总结整理 . . . . . . . . . . . ....
2. **Hibernate关系映射总结整理** Hibernate支持多种关系映射,如一对一(OneToOne)、一对多(OneToMany)、多对一(ManyToOne)、多对多(ManyToMany)。每种关系映射都有其适用场景,理解并熟练运用这些关系...
**Hibernate 二级缓存总结整理** 在Java的持久化框架中,Hibernate是一个广泛使用的ORM(对象关系映射)工具,它极大地简化了数据库操作。在处理大数据量或高并发的场景下,为了提高性能和减少数据库负载,...
Hibernate作为一款强大的对象关系映射(ORM)框架,它提供了与多种连接池的集成,如C3P0、DBCP、HikariCP等。本篇将详细介绍如何在Hibernate中配置这些连接池,并探讨其工作原理和优势。 **一、C3P0连接池** C3P0...
Hibernate 是一个流行的对象关系映射(ORM)框架,它允许 Java 开发者用面向对象的方式来处理数据库交互。Hibernate 自动处理 SQL 转换和数据库访问,使得开发人员可以专注于业务逻辑而不是底层数据库操作。通过对象...
首先,Spring框架的核心是依赖注入(DI),它通过XML配置或注解方式来管理对象的生命周期和依赖关系。在调试时,我们需要关注bean的定义是否正确,包括bean的id、class、属性注入等。同时,Spring的AOP(面向切面...
Hibernate是一种开源的对象关系映射(ORM)框架,它允许Java开发者将数据库操作转换为对Java对象的操作,极大地简化了数据访问层的代码。在这个"hibernate整理"中,我们将深入探讨Hibernate的核心概念,包括...
Hibernate是一个开源的对象关系映射(ORM)框架,它简化了Java应用程序与数据库之间的交互。以下是Hibernate的一些关键知识点: 1. **对象关系映射(ORM)**: ORM是将数据库中的表映射为Java对象的技术,Hibernate...
- 解释Hibernate如何支持Java中的继承关系,并映射到数据库表。 - **4.3 实现`equals()`和`hashCode()`** - 讲解为何持久化类应该重写这两个方法,以及如何正确实现它们。 - **4.4 动态模型(Dynamicmodels)** -...
1. **资源管理**:Hibernate简化了与数据库的交互过程,通过对象关系映射(ORM)技术,提供了比JDBC更高级的数据访问抽象。 2. **持久化层**:Hibernate充当应用程序和数据库之间的桥梁,减少了开发者在数据持久化...
`Struts2`是一个强大的MVC框架,负责处理用户请求并展示结果,而`Hibernate3`则作为对象关系映射(ORM)工具,简化了数据库操作。在本文中,我们将探讨`Struts2 + Hibernate3`开发中常见的问题以及解决方案。 首先...
- **Hibernate中的实现**:通过ORM(对象关系映射)技术实现对象与数据库表之间的映射。 #### 1.3 ORM - **概念**:Object Relational Mapping,即对象关系映射。 - **作用**:将面向对象的数据模型与关系型数据库...
- **数据关联**:Hibernate支持多种类型的数据关联,例如一对一、一对多、多对多关系,并提供了多种策略来处理这些关联。 - **数据访问**:介绍了POJO(Plain Old Java Object)和VO(Value Object)的概念及其在...
Hibernate 是一款开源的对象关系映射(ORM)框架,它允许开发人员将 Java 对象映射到数据库表中的记录,从而极大地简化了数据访问层的开发工作。本文档基于魔乐科技李兴华老师的 Hibernate 教程笔记进行整理与扩展,...
Hibernate是一个对象关系映射(ORM)框架,它允许开发者用面向对象的方式处理数据库操作。Hibernate通过提供API和映射文件,将Java对象与数据库表进行绑定,简化了数据库操作。在Lib1中,可能包含hibernate-core、...