- 浏览: 284616 次
- 性别:
- 来自: 湖南岳阳
最新评论
-
ternus:
兄弟,我用boboBrowse 也遇到了排序的问题,上线了讨论 ...
lucene 分组 bobo-Browse 排序的问题 -
luli0822:
Awesome bookmarks of those guru ...
流行的jQuery信息提示插件(jQuery Tooltip Plugin) -
shenbai:
如果你要在前台运行,你应该run得是ElasticSearch ...
ElasticSearch 源码分析 环境入门 -
cl1154781231:
<s:peroperty value="#at ...
关于Struts2中标签的一些心得 -
RonQi:
转载的吗?http://blog.csdn.net/stray ...
利用bobo-browse 实现lucene的分组统计功能
Hibernate的id生成有N种策略, 可以通过hbm文件或者annotation配置.
支持的策略包括:uuid, hilo, assigned, identity, select, sequence, seqhilo, increment, foreign, guid, uuid.hex, sequence-identity.
对应这些策略, 可以在org.hibernate.id包下找到, 其中有一个IdentifierGeneratorFactory类用于根据实体类的配置(hbm文件的<id>元素或@Id,@GeneratedValue注解)来创建相应的策略.
public final class IdentifierGeneratorFactory
{
... //注册所有支持的ID生成策略
private static final HashMap GENERATORS
= new HashMap();
static {
GENERATORS.put( "uuid", UUIDHexGenerator.class );
GENERATORS.put( "hilo", TableHiLoGenerator.class );
GENERATORS.put( "assigned", Assigned.class );
GENERATORS.put( "identity", IdentityGenerator.class );
GENERATORS.put( "select", SelectGenerator.class );
GENERATORS.put( "sequence", SequenceGenerator.class );
GENERATORS.put( "seqhilo", SequenceHiLoGenerator.class );
GENERATORS.put( "increment", IncrementGenerator.class );
GENERATORS.put( "foreign", ForeignGenerator.class );
GENERATORS.put( "guid", GUIDGenerator.class );
GENERATORS.put( "uuid.hex", UUIDHexGenerator.class ); // uuid.hex is deprecated
GENERATORS.put( "sequence-identity", SequenceIdentityGenerator.class );
}
...
public static IdentifierGenerator create
(String strategy, Type type, Properties params, Dialect dialect)
throws MappingException {
try {
Class clazz = getIdentifierGeneratorClass( strategy, dialect );
...
}
public static Class getIdentifierGeneratorClass(String strategy, Dialect dialect) {
Class clazz = ( Class ) GENERATORS
.get( strategy );
...
}
}
显然create()方法是用于创建ID生成器的, 而且用到了参数strategy和dialect. Hibernate在初始化SessionFactory的时候就会准备这些ID生成器. 见以下代码
SessionFactoryImpl(){
...
Iterator classes = cfg.getClassMappings();
while ( classes.hasNext() ) {
PersistentClass model = (PersistentClass) classes.next();
if ( !model.isInherited() ) {
IdentifierGenerator generator = model.getIdentifier().createIdentifierGenerator
(
settings.getDialect(),
settings.getDefaultCatalogName(),
settings.getDefaultSchemaName(),
(RootClass) model
);
identifierGenerators.put( model.getEntityName(), generator );
}
}
model.getIdentifier().createIdentifierGenerator() 最终会引用到
return IdentifierGeneratorFactory.create(
identifierGeneratorStrategy,
getType(),
params,
dialect
);
看来SessionFactory做了太多的工作. 为了能对这么多中ID生成策略有最直观的了解, 下面给出一个各种ID策略的类关系图.
该图分为两部分, 蓝色先左边的ID生成器是不需要借助数据库, 采用本地算法生成的, 而右边的ID生成器则需要借助数据库提供的ID生成能力.
最主要的接口有4个, 图中用蓝色标出.
* IdentifierGenerator: ID生成器接口, 只有一个generate方法, 返回生成的ID.
* PostInsertIdentifierGenerator: 针对MySQL, MSSQL这类能为主键设置自动增长的ID生成器
* PersistentIdentifierGenerator: 针对需要访问DB来生成ID的生成器, 比如GUID.
* Configurable: 用于读取配置信息
具体每个类如何处理:
1) uuid: 是采用128位的算法生成惟一值,支持大部分的数据库
public Serializable generate(SessionImplementor session, Object obj) {
return new StringBuffer(36)
.append( format( getIP
() ) ).append(sep)
.append( format( getJVM
() ) ).append(sep)
.append( format( getHiTime
() ) ).append(sep)
.append( format( getLoTime
() ) ).append(sep)
.append( format( getCount
() ) ) //注: 每次加1, JVM内唯一, 通过synchronized来保证实现
.toString();
}
protected String format(int intval) {
String formatted = Integer.toHexString(intval);
StringBuffer buf = new StringBuffer("00000000");
buf.replace( 8-formatted.length(), 8, formatted );
return buf.toString();
}
protected String format(short shortval) {
String formatted = Integer.toHexString(shortval);
StringBuffer buf = new StringBuffer("0000");
buf.replace( 4-formatted.length(), 4, formatted );
return buf.toString();
2)GUID: 通过使用数据库本身的uuid算法来实现
public class GUIDGenerator implements IdentifierGenerator {
public Serializable generate(SessionImplementor session, Object obj)
throws HibernateException {
final String sql = session.getFactory().getDialect().getSelectGUIDString();
...
}
假如getDialect()返回的是MySQLDialect, 则返回的是
public String getSelectGUIDString() {
return "select uuid()";
}
但是如果不支持uuid的数据库, 则抛出异常
public String getSelectGUIDString() {
throw new UnsupportedOperationException( "dialect does not support GUIDs" );
}
3)increment:
public class IncrementGenerator implements IdentifierGenerator, Configurable {
...
public synchronized
Serializable generate
(SessionImplementor session, Object object)
throws HibernateException {
if (sql!=null) {
getNext( session ); //注:使用了一个sql: "select max(" + column + ") from " + buf.toString();
}
return IdentifierGeneratorFactory.createNumber(next++, returnClass);
}
}
留意这里对generate方法使用了同步, 可想如果所有ID都通过hibernate创建, 则是安全的...
4) foreign key 简而言之, 就是要取到关联的对象的ID
foreign-key的配置稍微繁琐一点, 附上一个例子: 对于帖子(Post)和评论(Comment),
Comment表有一个外键fk_post, comment.post_id关联到Post.id.
那么在Comment.hbm.xml中就可以这样配置
Comment.hbm.xml
------------------------------------------------------------
<hibernate-mapping package="work">
<class name="Comment" lazy="false">
<id name="id">
<generator class="foreign">
<param name="property">post</param>
</generator>
</id>
...
<many-to-one name="post" column="post_id"></many-to-one>
</class>
</hibernate-mapping>
hibernate源代码:
------------------------------------------------------------
public Serializable generate
(SessionImplementor sessionImplementor, Object object
)
throws HibernateException {
//注:这里object是Comment对象
Session session = (Session) sessionImplementor;
//注:这里associatedObject是Post对象
Object associatedObject
= sessionImplementor.getFactory()
.getClassMetadata( entityName )
.getPropertyValue( object
, propertyName, session.getEntityMode() );
if ( associatedObject == null ) {
throw new IdentifierGenerationException(
"attempted to assign id from null one-to-one property: " +
propertyName
);
}
EntityType type = (EntityType) sessionImplementor.getFactory()
.getClassMetadata( entityName )
.getPropertyType( propertyName );
Serializable id;
try {
id = ForeignKeys.getEntityIdentifierIfNotUnsaved(
type.getAssociatedEntityName(),
associatedObject
,
sessionImplementor
);
}
catch (TransientObjectException toe) {
id = session.save( type.getAssociatedEntityName(), associatedObject
);
//注: 尝试保存该对象来生成ID, 这个操作可能触发一系列其他的东西, 如事件, 缓存写入等等
}
if ( session.contains(object) ) {
//abort the save (the object is already saved by a circular cascade)
return IdentifierGeneratorFactory.SHORT_CIRCUIT_INDICATOR;
//throw new IdentifierGenerationException("save associated object first, or disable cascade for inverse association");
}
return id;
}
5) Identity: 利用数据库的自增长方式来生成ID
相比前面的策略, 这是很有意思的ID生成策略, 因为hibernate并不能在insert前预先获得ID, 而是在insert后,
依赖于JDBC API的PreparedStatement.getGeneratedKeys()方法来取得ID,
该方法返回的是一个ResultSet, 只有一列, 名称为GENERATED_KEY. 所以Hibernate也是采用一种后置处理的方式:
即在调用到IdentifierGenerator.getnerate()方法的时候(其实这个时候的实现是IdentityGenerator类) ,
直接返回一个Serilizable对象--IdentifierGeneratorFactory.POST_INSERT_INDICATOR.
接着, 在我们使用session.save(object)方法的时候,
会判断save操作的类型是否为IdentifierGeneratorFactory.POST_INSERT_INDICATOR,再进行相应处理.
save部分代码量太大, 免了. 看一些关键的.
先是"奇怪"的generate()方法
public abstract class AbstractPostInsertGenerator
implements PostInsertIdentifierGenerator {
public Serializable generate(SessionImplementor s, Object obj) {
return IdentifierGeneratorFactory.POST_INSERT_INDICATOR
;
}
}
public class IdentityGenerator
extends AbstractPostInsertGenerator
{
.. //没有覆盖generate()
}
然后是session.save()对应的事件监听器 AbstractSaveEventListener 的saveWithGeneratedId()
protected Serializable saveWithGeneratedId(...){
...
if ( generatedId == null ) {
throw new IdentifierGenerationException( "null id generated for:" + entity.getClass() );
}
else if ( generatedId == IdentifierGeneratorFactory.SHORT_CIRCUIT_INDICATOR ) {
return source.getIdentifier( entity );
}
else if ( generatedId == IdentifierGeneratorFactory.POST_INSERT_INDICATOR
) {
return performSave( entity, null, persister, true, anything, source, requiresImmediateIdAccess );
}
...
}
该方法一直执行到protected Serializable performSaveOrReplicate(...)方法的
if ( useIdentityColumn
) {
EntityIdentityInsertAction insert
= new EntityIdentityInsertAction(
values, entity, persister, source, shouldDelayIdentityInserts
);
if ( !shouldDelayIdentityInserts ) {
log.debug( "executing identity-insert immediately" );
source.getActionQueue().execute( insert
); //这里有文章,hibernate已先把先前的操作先转换成sql执行
经过N多处理后, 最后回到刚才提到的JDBC API上. 在IdentityGenerator.GetGeneratedKeysDelegate子类中
public Serializable executeAndExtract
(PreparedStatement insert
) throws SQLException {
insert.executeUpdate();
ResultSet rs = null;
try {
rs = insert.getGeneratedKeys
();
return IdentifierGeneratorFactory.getGeneratedIdentity(rs,persister.getIdentifierType());
...
}
~_~
不得不佩服Hibernate团队的重构能力, 许多功能都被按照"行为向上集中"的规则处理, 即相同的行为, 放在更高层次的父类去.
调式过程中能看到很多类都是继承于AbstractXXX. 并且每个类的责任很明确. 像EntityPersister, Batcher,
ActionQueue, Executable和它的实现类, 等等...
发表评论
-
Errors running builder 'DeploymentBuilder' on project_java
2014-10-09 11:54 790此问题一般发生在Myeclipse 保存文件并自动部署时候 ... -
MyEclipse的SVN插件的问题
2012-02-27 14:06 1769我的项目都统一使用了UTF-8编码 查看当前版本,还是提 ... -
Eclipse的SVN插件历史版本乱码的问题
2012-02-27 14:04 0我的项目都统一使用了UTF-8编码 查看当前版本,还是提 ... -
java中的io系统详解
2011-09-16 12:09 1162相关读书笔记、心得文章列表 Ja ... -
hibernate表关联注解
2011-08-02 11:39 1432好久就想玩一下hibernate注解了(因为不用hbm文件,维 ... -
TCP/IP传输层,你懂多少?
2011-05-12 17:13 1749你所不知道的传输层 题记:23页的文档上,满满当当的 ... -
关于Struts2中标签的一些心得
2011-05-06 17:21 1748最近在做Struts2+Hibernet的一个项目,在if标签 ... -
This wizard is not available because it requires a valid professional subscripti
2011-04-18 23:05 1877今天用myeclipse学习UML时,打开UML时出现了: ... -
Tomcat内存、连接数等性能参数设置
2011-04-08 09:59 1286默认参数不适合生产环 ... -
Java 垃圾回收策略调优
2011-03-28 17:52 1590JVM参数调优是一个很头 ... -
Eclipse 或 MyEclipse 不能自动编译 class文件(综合)
2011-03-25 11:50 4737有时候用Eclipse或者MyEclipse 的时候,发现不 ... -
AccessController.doPrivileged 小记
2011-03-24 11:43 1072AccessController.doPrivileged ... -
servlet 读取图片
2011-02-17 15:38 1145String path = "F:/wjbo ... -
获取文件长度http,ftp
2011-01-18 16:09 1748ftp: FTPClient ftp = new FTPCl ... -
类的设计原则
2010-12-13 18:14 1095开闭原则 Software entities ... -
收集的网站
2010-12-09 17:12 930NIO.2 入门,第 1 部分: 异步通道 API http ... -
看Hibernate源码 001
2010-12-09 10:40 1105我看书的方式一向是&quo ... -
Hibernate Memcached 配置
2010-12-08 15:39 2151官方网址: http://code.google.com/p/ ... -
tomcat如何配置虚拟目录及虚拟主机
2010-12-02 17:54 2191先说说如何用Eclipse来做servlet开发,那些proj ... -
jaas:授权内幕
2010-11-13 15:48 1407Java 授权内幕: 以代码 ...
相关推荐
Hibernate通过`org.hibernate.id.SequenceGenerator`类来实现序列主键生成器。在`nextValue()`方法中,它会与数据库进行交互,获取序列的下一个值。这个过程涉及到JDBC操作,包括SQL的执行和结果的处理。 3. **...
- @Id:定义主键字段,通常与@IdGenerator配合使用定义主键生成策略。 4. Hibernate的Session操作: - save()和saveOrUpdate():将对象持久化到数据库,如果对象尚未存在,会创建新记录。 - update():更新已...
### Struts2 + Spring2 + Hibernate3 整合实例源码分析 #### 一、概述 随着企业级应用的发展,为了提高开发效率和系统维护性,越来越多的项目开始采用MVC设计模式。其中,Struts2作为MVC框架中的佼佼者,在前端...
在Java世界中,Hibernate是一个非常流行的对象关系映射(ORM)框架,它简化了数据库操作,使得开发者可以使用面向对象的方式来处理数据。本实例将详细讲解如何在Hibernate中实现Many-to-One关系映射,这是一种常见的...
**hibernate学习笔记第四天源码解析** 在hibernate学习的过程中,第四天通常会深入探讨实体类、映射文件、配置文件以及查询语言等方面的内容。...建议结合源码仔细阅读并实践,以便更好地掌握hibernate的使用。
本主题将深入探讨如何使用Hibernate通过主键来实现一对一的单向关联关系,并提供相关的源码分析。 首先,我们需要理解一对一关联关系的基本概念。在数据库中,一对一关系意味着两个表中的每一条记录都对应另一表中...
根据给定的文件信息,以下是对“hibernate3.1.2英文文档(pdf)”的知识点提炼和详细解析: ### 核心知识点:Hibernate 3.1.2 的架构、配置与基本对象关系映射 #### 引言: Hibernate 是一个开放源代码的对象关系...
Hibernate ORM 是一个强大的Java对象关系映射(ORM)框架,它允许开发者将数据库操作与Java对象模型紧密结合,简化了数据库应用程序的开发。在一对一(One-to-One)主键关联关系中,两个实体类之间存在唯一对应的...
《深入理解Hibernate-API及其在项目中的应用》 Hibernate是一个强大的Java持久化框架,它简化了数据库操作,使得开发者可以更加专注于业务逻辑,而非底层的SQL语法。本篇文章将围绕“Hibernate-API打包”这一主题,...
在Eclipse中新建一个Java项目,并创建一个源码文件夹`src`,将`hibernate-3.2.4.sp1`解压后的`hibernate3.jar`及`lib`下的所有JAR包,以及Oracle的驱动包添加到项目的构建路径中。 ##### 配置Hibernate **配置`...
Hibernate是一个开放源码的对象关系映射(ORM)框架,它为Java应用程序提供了一种解决方案,用以处理面向对象编程语言与关系型数据库之间的不匹配问题。Hibernate的主要特点之一是其低侵入性设计,这体现在它不要求...
### 深入理解Hibernate缓存 #### 一、Hibernate缓存概述 Hibernate作为一款流行的Java持久层框架,为开发者提供了高效且灵活的数据访问能力。其中,缓存机制是Hibernate性能优化的重要组成部分之一。理解Hibernate...
### Hibernate学习笔记01 #### 一、Hibernate简介与安装 **Hibernate** 是一款开源的对象关系映射(Object Relational Mapping, ORM)框架,它能够有效地简化Java应用程序与数据库之间的交互,提供了一种更为优雅...
**hibernate 连接数据库基础源码3** 在Java编程中,Hibernate是一个非常流行的对象关系映射(ORM)框架,它简化了数据库操作,使开发者可以使用面向对象的方式来处理数据库事务。本教程将深入探讨Hibernate连接...
了解Hibernate的工作原理时,深入源码分析是非常有价值的。例如,研究`SessionFactory`如何管理会话,`Session`如何执行SQL语句,以及`Entity`状态转换机制等,能帮助我们更好地优化性能和解决问题。 **总结** ...
- **Hibernate**: 是一个开放源码的对象关系映射框架(Object Relational Mapping, ORM),它对JDBC进行了非常轻量级的对象封装,使得Java开发人员可以使用面向对象的方式进行数据库的操作。 #### 二、实现步骤详解...
**hibernate入门实例-源码** 在Java开发中,Hibernate是一个非常流行的对象关系映射(ORM)框架,它简化了数据库操作,使得开发者能够用面向对象的方式处理数据。本实例将带你逐步了解Hibernate的基本使用,包括...
Hibernate是一个开放源码的ORM(Object Relational Mapping,对象关系映射)框架,它为Java应用程序提供了一种将对象模型表示的对象映射到基于SQL的关系型数据库结构中的机制。通过这种映射,开发人员可以专注于业务...
-- id generator配置 --> </id> <one-to-one name="account" class="Account" cascade="all"/> <id name="id" column="ACCOUNT_ID"> <!-- id generator配置 --> </id> <one-to-one name="user" class=...