- 浏览: 1346435 次
- 性别:
- 来自: 成都
-
文章分类
- 全部博客 (471)
- 原创文章 (4)
- Database (84)
- J2SE (63)
- Web (26)
- Javascript (30)
- Lucene (11)
- os (13)
- 算法 (8)
- Webservice (1)
- Open projects (18)
- Hibernate (18)
- Spring (15)
- Css (2)
- J2ee (2)
- 综合技术 (18)
- 安全管理 (13)
- PatternsInJava (27)
- NIO (5)
- Ibatis (2)
- 书籍收藏 (1)
- quartz (7)
- 并发编程 (15)
- oracle问题 (2)
- ios (60)
- coco2d-iphone (3)
- C++ (6)
- Zookeeper (2)
- golang (4)
- animation (2)
- android (1)
最新评论
-
dandingge123:
【引用】限制UITextField输入长度的方法 -
qja:
...
对List顺序,逆序,随机排列实例代码 -
安静听歌:
现在在搞这个,,,,,哎~头都大了,,,又freemarker ...
通用大型网站页面静态化解决方案(一) -
springdata-jpa:
java quartz定时任务demo教程源代码下载,地址:h ...
Quartz 配置参考 -
马清天:
[b][/b][list][*]引用[u][/u][/list ...
通用大型网站页面静态化解决方案(一)
当关系数据库试图在一个单一表中存储数 TB 的数据时,总性能经常会降低。显然,对所有数据编索引不仅对于读而且对于写都很耗时。因为 NoSQL 数据商店尤其适合存储大型数据(如 Google 的 Bigtable),显然 NoSQL 是一种非关系数据库方法。对于倾向于使用 ACID-ity 和实体结构关系数据库的开发人员及需要这种结构的项目来说,切分是一个令人振奋的可选方法。
切分 是数据库分区的一个分支,但是它不是本地数据库技术 — 切分发生在应用程序级别。在各种切分实现中,Hibernate Shards 是 Java™ 技术世界中最受欢迎的一个。这个灵活绝妙的项目可以让您使用映射至逻辑数据库的 POJO 对切分数据集进行几乎无缝操作(我将在下文简要介绍 “几乎” 的原因)。使用 Hibernate Shards 时,您无须将您的 POJO 特别映射至切分 — 您可以像使用 Hibernate 方法对任何常见关系数据库进行映射时一样对其进行映射。Hibernate Shards 可以为您管理低级别的切分任务。
到目前为止,在本 系列 中,我已经使用了一个基于比赛和参赛者类推关系的简单域展示了各种数据库存储技术。本月,我将继续使用这个熟悉的示例介绍一种实用的切分技术,然后在 Hibernate Shards 中对其进行实现。注意:与切分相关的主要工作与 Hibernate 没有太大关系;事实上,Hibernate Shards 的编码工作比较简单。其中关键的部分在于判断 如何进行切分以及对什么进行切分。
关于本系列
自 Java 技术首次诞生以来,Java 开发格局已发生了翻天覆地的变化。得益于成熟的开源框架和可靠的租赁部署基础设施,现在可以迅速而经济地组装、测试、运行和维护 Java 应用程序。在 本系列 中,Andrew Glover 探索使这种新的 Java 开发风格成为可能的各种技术和工具。
数据库切分 是一个固有的关系流程,可以通过一些逻辑数据块将一个表的行分为不同的小组。例如,如果您正在根据时间戳对一个名为 foo 的超大型表进行分区,2010 年 8 月之前的所有数据都将进入分区 A,而之后的数据则全部进入分区 B。分区可以加快读写速度,因为它们的目标是单独分区中的较小型数据集。
分区功能并不总是可用的(MySQL 直到 5.1 版本后才支持),而且其需要的商业系统的成本也让人望而却步。更重要的是,大部分分区实现在同一个物理机上存储数据,所以受到硬件基础的影响。除此之外,分区也不能鉴别硬件的可靠性或者说缺乏可靠性。因此,很多智慧的人们开始寻找进行伸缩的新方法。
切分 实质上是数据库级别的分区:它不是通过数据块分割数据表的行,而是通过一些逻辑数据元素对数据库本身进行分割(通常跨不同的计算机)。也就是说,切分不是将数据表 分割成小块,而是将整个数据库 分割成小块。
切分的一个典型示例是基于根据区域对一个存储世界范围客户数据的大型数据库进行分割:切分 A 用于存储美国的客户信息,切分 B 用户存储亚洲的客户信息,切分 C 欧洲,等。这些切分分别处于不同的计算机上,且每个切分将存储所有相关数据,如客户喜好或订购历史。
切分的好处(如分区一样)在于它可以压缩大型数据:单独的数据表在每个切分中相对较小,这样就可以支持更快速的读写速度,从而提高性能。切分还可以改善可靠性,因为即便一个切分意外失效,其他切分仍然可以服务数据。而且因为切分是在应用程序层面进行的,您可以对不支持常规分区的数据库进行切分处理。资金成本较低同样也是一个潜在优势。
像很多其他技术一样,进行切分时也需要作出部分妥协。因为切分不是一项本地数据库技术 — 也就是说,必须在应用程序中实现 —在开始切分之前需要制定出您的切分策略。进行切分时主键和跨切分查询都扮演重要角色,主要通过定义您不可以做什么实现。
主键
切分利用多个数据库,其中所有数据库都独立起作用,不干涉其他切分。因此,如果您依赖于数据库序列(如自动主键生成),很有可能在一个数据库集中将出现同一个主键。可以跨分布式数据库协调序列,但是这样会增加系统的复杂程度。避免相同主键最安全的方法就是让应用程序(应用程序将管理切分系统)生成主键。
跨切分查询
大部分切分实现(包括 Hibernate Shards)不支持跨切分查询,这就意味着,如果您想利用不同切分的两个数据集,就必须处理额外的长度。(有趣的是,Amazon 的 SimpleDB 也禁止跨域查询)例如,如果将美国客户信息存储在切分 1 中,还需要将所有相关数据存储在此。如果您尝试将那些数据存储在切分 2 中,情况就会变得复杂,系统性能也可能受影响。这种情况还与之前提到的一点有关 — 如果您因为某种原因需要进行跨切分连接,最好采用一种可以消除重复的方式管理键!
很明显,在建立数据库前必须全面考虑切分策略。一旦选择了一个特定的方向之后,您差不多就被它绑定了 — 进行切分后很难随便移动数据了。
避免不成熟切分
切分最好在后期实现。如不成熟优化一样,基于预期数据增长的切分可能是灾难的温床。成功的切分实现基于对于应用程序数据随时间增长的理解,以及之后对于未来的推断。一旦对数据进行切分后,移动数据会非常困难。
因为切分将您绑定在一个线型数据模型中(也就是说,您无法轻松连接不同切分中的数据),您必须对如何在每个切分中对数据进行逻辑组织有一个清晰的概念。这可以通过聚焦域中的主要节点实现。如在一个电子商务系统中,主要节点可以是一个订单或者一个客户。因此,如果您选择 “客户” 作为切分策略的节点,那么与客户有关的所有数据将移动至各自的切分中,但是您仍然必须选择将这些数据移动至哪个切分。
对于客户来说,您可以根据所在地(欧洲、亚洲、非洲等)切分,或者您也可以根据其他元素进行切分。这由您决定。但是,您的切分策略应该包含将数据均匀分布至所有切分的方法。切分的总体概念是将大型数据集分割为小型数据集;因此,如果一个特定的电子商务域包含一个大型的欧洲客户集以及一个相对小的美国客户集,那么基于客户所在地的切分可能没有什么意义。
现在让我们回到我经常提到的赛跑应用程序示例中,我可以根据比赛或参赛者进行切分。在本示例中,我将根据比赛进行切分,因为我看到域是根据参加不同比赛的参赛者进行组织的。因此,比赛是域的根。我也将根据比赛距离进行切分,因为比赛应用程序包含不同长度和不同参赛者的多项比赛。
请注意:在进行上述决定时,我已经接受了一个妥协:如果一个参赛者参加了不止一项比赛,他们分属不同的切分,那该怎么办呢?Hibernate Shards (像大多数切分实现一样)不支持跨切分连接。我必须忍受这些轻微不便,允许参赛者被包含在多个切分中 — 也就是说,我将在参赛者参加的多个比赛切分中重建该参赛者。
为了简便起见,我将创建两个切分:一个用于 10 英里以下的比赛;另一个用于 10 英里以上的比赛。
Hibernate Shards 几乎可以与现有 Hibernate 项目无缝结合使用。唯一问题是 Hibernate Shards 需要一些特定信息和行为。比如,需要一个切分访问策略、一个切分选择策略和一个切分处理策略。这些是您必须实现的接口,虽然部分情况下,您可以使用默认策略。我们将在后面的部分逐个了解各个接口。
执行查询时,Hibernate Shards 需要一个决定首个切分、第二个切分及后续切分的机制。Hibernate Shards 无需确定查询什么(这是 Hibernate Core 和基础数据库需要做的),但是它确实意识到,在获得答案之前可能需要对多个切分进行查询。因此,Hibernate Shards 提供了两种极具创意的逻辑实现方法:一种方法是根据序列机制(一次一个)对切分进行查询,直到获得答案为止;另一种方法是并行访问策略,这种方法使用一个线程模型一次对所有切分进行查询。
为了使问题简单,我将使用序列策略,名称为 SequentialShardAccessStrategy
。我们将稍后对其进行配置。
当创建一个新对象时(例如,当通过 Hibernate 创建一个新 Race
或 Runner
时),Hibernate Shards 需要知道需将对应的数据写入至哪些切分。因此,您必须实现该接口并对切分逻辑进行编码。如果您想进行默认实现,有一个名为 RoundRobinShardSelectionStrategy
的策略,它使用一个循环策略将数据输入切分中。
对于赛跑应用程序,我需要提供根据比赛距离进行切分的行为。因此,我们需要实现 ShardSelectionStrategy
接口并提供依据 Race
对象的 distance
采用 selectShardIdForNewObject
方法进行切分的简易逻辑。(我将稍候在 Race
对象中展示。)
运行时,当在我的域对象上调用某一类似 save
的方法时,该接口的行为将被深层用于 Hibernate 的核心。
import org.hibernate.shards.ShardId; import org.hibernate.shards.strategy.selection.ShardSelectionStrategy; public class RacerShardSelectionStrategy implements ShardSelectionStrategy { public ShardId selectShardIdForNewObject(Object obj) { if (obj instanceof Race) { Race rce = (Race) obj; return this.determineShardId(rce.getDistance()); } else if (obj instanceof Runner) { Runner runnr = (Runner) obj; if (runnr.getRaces().isEmpty()) { throw new IllegalArgumentException("runners must have at least one race"); } else { double dist = 0.0; for (Race rce : runnr.getRaces()) { dist = rce.getDistance(); break; } return this.determineShardId(dist); } } else { throw new IllegalArgumentException("a non-shardable object is being created"); } } private ShardId determineShardId(double distance){ if (distance > 10.0) { return new ShardId(1); } else { return new ShardId(0); } } } |
如您在 清单 1 中所看到的,如果持久化对象是一场 Race
,那么其距离被确定,而且(因此)选择了一个切分。在这种情况下,有两个切分:0 和 1,其中切分 1 中包含 10 英里以上的比赛,切分 0 中包含所有其他比赛。
如果持久化一个 Runner
或其他对象,情况会稍微复杂一些。我已经编码了一个逻辑规则,其中有三个原则:
- 一名
Runner
在没有对应的Race
时无法存在。 - 如果
Runner
被创建时参加了多场Race
s,这名Runner
将被持久化到寻找到的首场Race
所属的切分中。(顺便说一句,该原则对未来有负面影响。) - 如果还保存了其他域对象,现在将引发一个异常。
然后,您就可以擦掉额头的热汗了,因为大部分艰难的工作已经搞定了。随着比赛应用程序的增长,我所使用的逻辑可能会显得不够灵活,但是它完全可以顺利地完成这次演示!
当通过键搜索一个对象时,Hibernate Shards 需要一种可以决定首个切分的方法。将需要使用 SharedResolutionStrategy
接口对其进行指引。
如我之前提到的那样,切分迫使您重视主键,因为您将需要亲自管理这些主键。幸运的是,Hibernate 在提供键或 UUID 生成方面表现良好。因此 Hibernate Shards 创造性地提供一个 ID 生成器,名为 ShardedUUIDGenerator
,它可以灵活地将切分 ID 信息嵌入到 UUID 中。
如果您最后使用 ShardedUUIDGenerator
进行键生成(我在本文中也将采取这种方法),那么您也可以使用 Hibernate Shards 提供的创新 ShardResolutionStrategy
实现,名为 AllShardsShardResolutionStrategy
,这可以决定依据一个特定对象的 ID 搜索什么切分。
配置好 Hibernate Shards 工作所需的三个接口后,我们就可以对切分示例应用程序的第二步进行实现了。现在应该启动 Hibernate 的 SessionFactory
了。
Hibernate 的其中一个核心接口对象是它的 SessionFactory
。Hibernate 的所有神奇都是在其配置 Hibernate 应用程序过程中通过这个小对象实现的,例如,通过加载映射文件和配置。如果您使用了注释或 Hibernate 珍贵的 .hbm 文件,那么您还需要一个 SessionFactory
来让 Hibernate 知道哪些对象是可以持久化的,以及将它们持久化到 哪里。
因此,使用 Hibernate Shards 时,您必须使用一个增强的 SessionFactory
类型来配置多个数据库。它可以被命名为 ShardedSessionFactory
,而且它当然是 SessionFactory
类型的。当创建一个 ShardedSessionFactory
时,您必须提供之前配置好的三个切分实现类型(ShardAccessStrategy
、ShardSelectionStrategy
和 ShardResolutionStrategy
)。您还需提供 POJO 所需的所有映射文件。(如果您使用一个基于备注的 Hibernate POJO 配置,情况可能会有所不同。)最后,一个 ShardedSessionFactory
示例需要每个切分都对应多个 Hibernate 配置文件。
我已经创建了一个 ShardedSessionFactoryBuilder
类型,它有一个主要方法 createSessionFactory
,可以创建一个配置合理的 SessionFactory
。之后,我将将所有的一切都与 Spring 连接在一起(现在谁不使用一个 IOC 容器?)。现在,清单 2 显示了 ShardedSessionFactoryBuilder
的主要作用:创建一个 Hibernate 配置
:
private Configuration getPrototypeConfig(String hibernateFile, List<String> resourceFiles) { Configuration config = new Configuration().configure(hibernateFile); for (String res : resourceFiles) { configs.addResource(res); } return config; } |
如您在 清单 2 中所看到的,可以从 Hibernate 配置文件中创建了一个简单的 Configuration
。该文件包含如下信息,如使用的是什么类型的数据库、用户名和密码等,以及所有必须的资源文件,如 POJO 所用的 .hbm 文件。在进行切分的情况下,您通常需要使用多个数据库配置,但是 Hibernate Shards 支持您仅使用一个 hibernate.cfg.xml 文件,从而简化了整个过程(但是,如您在 清单 4 中所看到的,您将需要对使用的每一个切分准备一个 hibernate.cfg.xml 文件)。
下一步,在清单 3 中,我将所有的切分配置都收集到了一个 List
中:
List<ShardConfiguration> shardConfigs = new ArrayList<ShardConfiguration>(); for (String hibconfig : this.hibernateConfigurations) { shardConfigs.add(buildShardConfig(hibconfig)); } |
在 清单 3 中,对 hibernateConfigurations
的引用指向了 String
s List
,其中每个 String 都包含了 Hibernate 配置文件的名字。该 List
通过 Spring 自动连接。清单 4 是我的 Spring 配置文件中的一段摘录:
<bean id="shardedSessionFactoryBuilder" class="org.disco.racer.shardsupport.ShardedSessionFactoryBuilder"> <property name="resourceConfigurations"> <list> <value>racer.hbm.xml</value> </list> </property> <property name="hibernateConfigurations"> <list> <value>shard0.hibernate.cfg.xml</value> <value>shard1.hibernate.cfg.xml</value> </list> </property> </bean> |
如您在 清单 4 中所看到的,ShardedSessionFactoryBuilder
正在与一个 POJO 映射文件和两个切分配置文件连接。清单 5 中是 POJO 文件的一段摘录:
<class name="org.disco.racer.domain.Race" table="race"dynamic-update="true" dynamic-insert="true"> <id name="id" column="RACE_ID" unsaved-value="-1"> <generator class="org.hibernate.shards.id.ShardedUUIDGenerator"/> </id> <set name="participants" cascade="save-update" inverse="false" table="race_participants" lazy="false"> <key column="race_id"/> <many-to-many column="runner_id" class="org.disco.racer.domain.Runner"/> </set> <set name="results" inverse="true" table="race_results" lazy="false"> <key column="race_id"/> <one-to-many class="org.disco.racer.domain.Result"/> </set> <property name="name" column="NAME" type="string"/> <property name="distance" column="DISTANCE" type="double"/> <property name="date" column="DATE" type="date"/> <property name="description" column="DESCRIPTION" type="string"/> </class> |
请注意,清单 5 中的 POJO 映射的唯一独特方面是 ID 的生成器类 — 这就是 ShardedUUIDGenerator
,它(如您想象的一样)将切分 ID 信息嵌入到 UUID 中。这就是我的 POJO 映射中切分的唯一独特方面。
下一步,如清单 6 中所示,我已经配置了一个切分 — 在本示例中,除切分 ID 和连接信息外,切分 0 和切分 1 的文件是一样的。
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory name="HibernateSessionFactory0"> <property name="dialect">org.hibernate.dialect.HSQLDialect</property> <property name="connection.driver_class">org.hsqldb.jdbcDriver</property> <property name="connection.url"> jdbc:hsqldb:file:/.../db01/db01 </property> <property name="connection.username">SA</property> <property name="connection.password"></property> <property name="hibernate.connection.shard_id">0</property> <property name="hibernate.shard.enable_cross_shard_relationship_checks">true </property> </session-factory> </hibernate-configuration> |
如其名字所示,enable_cross_shard_relationship_checks
属性对跨切分关系进行了检查。根据 Hibernate Shards 文档记录,该属性非常耗时,在生成环境中应该关闭。
最后,ShardedSessionFactoryBuilder
通过创建 ShardStrategyFactory
,然后添加三个类型(包括 清单 1 中的 RacerShardSelectionStrategy
),将一切都整合到了一起,如清单 7 中所示:
private ShardStrategyFactory buildShardStrategyFactory() { ShardStrategyFactory shardStrategyFactory = new ShardStrategyFactory() { public ShardStrategy newShardStrategy(List<ShardId> shardIds) { ShardSelectionStrategy pss = new RacerShardSelectionStrategy(); ShardResolutionStrategy prs = new AllShardsShardResolutionStrategy(shardIds); ShardAccessStrategy pas = new SequentialShardAccessStrategy(); return new ShardStrategyImpl(pss, prs, pas); } }; return shardStrategyFactory; } |
最后,我执行了那个名为 createSessionFactory
的绝妙方法,在本示例中创建了一个 ShardedSessionFactory
,如清单 8 所示:
清单 8. 创建 ShardedSessionFactory
public SessionFactory createSessionFactory() { Configuration prototypeConfig = this.getPrototypeConfig (this.hibernateConfigurations.get(0), this.resourceConfigurations); List<ShardConfiguration> shardConfigs = new ArrayList<ShardConfiguration>(); for (String hibconfig : this.hibernateConfigurations) { shardConfigs.add(buildShardConfig(hibconfig)); } ShardStrategyFactory shardStrategyFactory = buildShardStrategyFactory(); ShardedConfiguration shardedConfig = new ShardedConfiguration( prototypeConfig, shardConfigs,shardStrategyFactory); return shardedConfig.buildShardedSessionFactory(); } |
现在可以深呼吸一下了,因为我们马上就成功了。到目前为止,我已经创建一个可以合理配置 ShardedSessionFactory
的生成器类,其实就是实现 Hibernate 无处不在的 SessionFactory
类型。ShardedSessionFactory
完成了切分中所有的神奇。它利用我在 清单 1 中所部署的切分选择策略,并从我配置的两个切分中读写数据。(清单 6 显示了切分 0 和切分 1 的配置几乎相同。)
现在我需要做的就是连接我的域对象,在本示例中,因为它们依赖于 Hibernate,需要一个 SessionFactory
类型进行工作。我将仅使用我的 ShardedSessionFactoryBuilder
提供一种 SessionFactory
类型,如清单 9 中所示:
<bean id="mySessionFactory" factory-bean="shardedSessionFactoryBuilder" factory-method="createSessionFactory"> </bean> <bean id="race_dao" class="org.disco.racer.domain.RaceDAOImpl"> <property name="sessionFactory"> <ref bean="mySessionFactory"/> </property> </bean> |
如您在 清单 9 中所看到的,我首先在 Spring 中创建了一个类似工厂的 bean;也就是说,我的 RaceDAOImpl
类型有一个名为 sessionFactory
的属性,是 SessionFactory
类型。之后,mySessionFactory
引用通过在 ShardedSessionFactoryBuilder
上调用 createSessionFactory
方法创建了一个 SessionFactory
示例,如 清单 4 中所示。
当我为我的 Race
对象示例使用 Spring(我主要将其作为一个巨型工厂使用,以返回预配置的对象)时,一切事情就都搞定了。虽然没有展示,RaceDAOImpl
类型是一个利用 Hibernate 模板进行数据存储和检索的对象。我的 Race
类型包含一个 RaceDAOImpl
示例,它将所有与数据商店相关的活动都推迟至此。很默契,不是吗?
请注意,我的 DAO 与 Hibernate Shards 在代码方面并没有绑定,而是通过配置进行了绑定。配置(如 清单 5 中的)将它们绑定在一个特定切分 UUID 生成方案中,也就是说了我可以在需要切分时从已有 Hibernate 实现中重新使用域对象。
接下来,我需要验证我的切分实现可以工作。我有两个数据库并通过距离进行切分,所以当我创建一场马拉松时(10 英里以上的比赛),该 Race
示例应在切分 1 中找到。一个小型的比赛,如 5 公里的比赛(3.1 英里),将在切分 0 中找到。创建一场 Race
后,我可以检查单个数据库的记录。
在清单 10 中,我已经创建了一场马拉松,然后继续验证记录确实是在切分 1 中而非切分 0 中。使事情更加有趣(和简单)的是,我使用了 easyb,这是一个基于 Groovy 的行为驱动开发架构,利用自然语言验证。easyb 也可以轻松处理 Java 代码。即便不了解 Groovy 或 easyb,您也可以通过查看清单 10 中的代码,看到一切如期进行。(请注意,我帮助创建了 easyb,并且在 developerWorks 中对这个话题发表过文章。)
清单 10. 一个验证切分正确性的 easyb 故事中一段摘录
scenario "races greater than 10.0 miles should be in shard 1 or db02", { given "a newly created race that is over 10.0 miles", { new Race("Leesburg Marathon", new Date(), 26.2, "Race the beautiful streets of Leesburg!").create() } then "everything should work fine w/respect to Hibernate", { rce = Race.findByName("Leesburg Marathon") rce.distance.shouldBe 26.2 } and "the race should be stored in shard 1 or db02", { sql = Sql.newInstance(db02url, name, psswrd, driver) sql.eachRow("select race_id, distance, name from race where name=?", ["Leesburg Marathon"]) { row -> row.distance.shouldBe 26.2 } sql.close() } and "the race should NOT be stored in shard 0 or db01", { sql = Sql.newInstance(db01url, name, psswrd, driver) sql.eachRow("select race_id, distance, name from race where name=?", ["Leesburg Marathon"]) { row -> fail "shard 0 contains a marathon!" } sql.close() } } |
当然,我的工作还没有完 — 我还需要创建一个短程比赛,并验证其位于切分 0 中而非切分 1 中。您可以在本文提供的 代码下载 中看到该验证操作!
切分可以增加应用程序的读写速度,尤其是如果您的应用程序包含大量数据 — 如数 TB — 或者您的域处于无限制发展中,如 Google 或 Facebook。
在进行切分之前,一定要确定应用程序的规模和增长对其有利。切分的成本(或者说缺点)包括对如何存储和检索数据的特定应用程序逻辑进行编码的成本。进行切分后,您多多少少都被锁定在您的切分模型中,因为重新切分并非易事。
如果能够正确实现,切分可以用于解决传统 RDBMS 规模和速度问题。切分对于绑定于关系基础架构、无法继续升级硬件以满足大量可伸缩数据存储要求的组织来说是一个非常成本高效的决策。
<!-- CMA ID: 551775 --><!-- Site ID: 10 --><!-- XSLT stylesheet used to transform this file: dw-article-6.0-beta.xsl -->
本文样例代码 | j-javadev2-11.zip | 15KB | HTTP |
学习
-
Java 开发 2.0 :本 developerWorks 系列探讨了可以重新解释 Java 开发前景的技术和工具,包括 NoSQL(2010 年 5 月)、SimpleDB(2010 年 6 月)和 CouchDB (2009 年 11 月)。
- “使用 Max Ross 切分:Hibernate Shards”(JavaWorld,2008 年 7 月):Andy Glover 与 Hibernate Shards 创始人探讨项目背后的动机以及如何有效利用切分。
- “切分之前要三思”Andrew Glover,thediscoblog.com,2008 年 6 月):切分与风险同在,提前了解切分中的风险。
- “一个非传统的数据库设计方法:切分的来临”(Todd Hoff,HighScalability.com,2009 年 8 月):从专注于管理大型数据的基础架构的站点看切分。
- “构建可伸缩数据库:各种数据库切分方案的利弊”(Dare Obasanjo,25HoursADay.com,2009 年 1 月):使用 Facebook 作为开发切分策略的一个真实示例。
- “重新思考传统 DAO 模式”(Andrew Glover,thediscoblog.com,2008 年 6 月):了解关于将 DAO 添加到正常域对象的更多信息,a la Grails and Rails。
- “使用 easyb 驱动开发”(Andrew Glover,developerWorks,2008 年 11 月):来自基础架构创建人的 easyb 教程简介。
- 浏览 Java 技术书店 获得有关这些主题和其他技术主题的图书。
-
developerWorks Java 技术专区:查找数百篇有关 Java 编程各个方面的文章。
获得产品和技术
-
Hibernate Shards:旨在通过将对水平分区的支持添加到 Hibernate Core 从而压缩数据并把数据复杂性降到最低。
-
easyb:通过使用一个基于规格的域特定语言,easyb 旨在支持可执行、可读取文档。
讨论
- 加入 My developerWorks 中文社区。在浏览面向开发人员的博客、论坛、小组和 wiki 时,与其他 developerWorks 用户联系。
发表评论
-
hibernate ehcache
2010-12-11 21:57 34101.EhCache是什么 EhCache是Hiberna ... -
全面讲解Hibernate二级缓存
2010-12-02 21:37 1202向大家详细介绍Hibernate ... -
深入理解Hibernate日志
2010-12-02 21:33 1948Hibernate中使用什么来记录日志呢?通常Hibern ... -
Hibernate中悲观锁和乐观锁
2010-12-02 21:19 3291Hibernate悲观锁:在数 ... -
解读Hibernate继承映射策略
2010-12-02 20:33 1115Hibernate继承映射的英文是Inheritanc ... -
mysql的text如何dialect mapping
2010-11-17 12:35 2345在开发项目中,遇到了hibernate 的2个bug。导致 ... -
让hibernate支持date_add
2010-11-17 12:30 5239今天做东西的时候想 ... -
Hibernate3一级缓存和二级缓存的理解!
2010-11-04 20:06 17281. Session 级别的缓存,它同 ... -
Hibernate的缓存机制
2010-10-26 21:24 1306核心提示:缓存是位于应用程序与物理数据源之间,用于临时存放 ... -
JPA注解学习总结
2010-10-26 21:02 4309核心提示:JPA 注解的几个要点 1.设置Pojo为实体 ... -
EHCache 缓存全接触
2010-10-26 21:01 2063EHCache 是一个纯java的,在Hibernate2.1 ... -
Hibernate cascade和inverse实例分析
2010-10-26 20:59 1511首先引用另一个blog的说 ... -
Hibernate的拦截器和监听器
2010-10-26 20:57 1525最近项目需要,用到了Hibernate的拦截器和监听器,有些小 ... -
Hibernate Shards 数据的水平、垂直切割 Hibernate测试环境
2010-10-24 11:15 1252http://www.cnblogs.com/RicCC/ar ... -
Hibernate Shards - 关系数据库水平分割解决方案框架
2010-10-24 10:41 33861。水平分割:按记录进分分割,不同的记录可以分开保存,每个子表 ... -
hibernate的保存
2010-04-21 17:43 2183hibernate的保存 hibernate对于对象的保存提 ... -
hibernate 调用存储过程
2010-02-07 14:05 7374第 17 章 Native SQL查询 你也可以使用 ...
相关推荐
本文档主要讨论了 Java 开发 2.0 中的数据库切分技术,特别是使用 Hibernate Shards 实现数据库切分。文章首先介绍了数据库切分的概念和优点,接着讨论了 Hibernate Shards 的使用方法和优点。最后,文章还讨论了...
内容概要:本文详细介绍了应用于电镀生产线的西门子S7-300 PLC控制系统的程序设计、硬件配置以及调试过程中积累的实际经验。主要内容涵盖温度控制、条码记录、行车定位、故障排查等方面的技术细节。文中展示了多个关键功能模块的具体实现方法,如PID温度控制、条码数据处理、行车定位判断等,并分享了一些实用的调试技巧和注意事项。此外,还讨论了硬件配置中的重要细节,如模块地址分配、网络拓扑设计等。 适合人群:从事自动化控制领域的工程师和技术人员,尤其是对PLC编程有一定基础的人群。 使用场景及目标:适用于需要深入了解和掌握电镀生产线自动化控制技术的专业人士。目标是帮助读者理解S7-300 PLC在电镀生产线中的具体应用,提高实际项目的开发效率和可靠性。 其他说明:文章不仅提供了详细的程序代码示例,还分享了许多来自一线的真实案例和实践经验,对于解决实际工程中的问题具有很高的参考价值。
内容概要:本文详细介绍了使用COMSOL Multiphysics进行固体超声导波的二维仿真过程。作者通过建立一个10mm×100mm的铝板模型,应用汉宁窗调制的5周期200kHz正弦激励信号,研究了超声导波在铝板中的传播特性及其模式转换现象。文中涵盖了从模型构建、材料参数设置、网格划分、边界条件设定、激励信号施加到求解设置以及结果分析的完整流程。特别强调了汉宁窗调制的作用,即减少频谱泄漏并提高信号质量。 适合人群:从事超声检测、材料科学、物理学等相关领域的研究人员和技术人员,尤其是那些希望深入了解COMSOL仿真工具及其在超声导波研究中应用的人群。 使用场景及目标:适用于需要精确模拟超声波在固体介质中传播的研究项目,旨在验证理论预测、优化实验设计、评估不同材料和结构对超声波的影响。此外,还可以用于教学目的,帮助学生掌握COMSOL软件的操作方法和超声导波的基础知识。 其他说明:文中提供了详细的参数设置指导和代码片段,有助于读者快速复现仿真过程。同时,作者分享了一些实用技巧,如如何正确设置网格大小、选择合适的窗函数等,以确保仿真结果的准确性。
离职人员分析仪表盘.xlsx
内容概要:本文详细介绍了如何利用LabVIEW搭建一个多功能的虚拟函数信号发生器及其信号分析功能。首先,文章展示了如何通过LabVIEW的前面板和程序框图创建各种常见波形(如正弦波、方波、三角波等),并深入探讨了波形生成的具体实现方法,包括三角波的周期性和斜率计算、白噪声的生成以及自定义公式的解析。接着,文章讨论了信号处理的关键技术,如自相关分析、频谱分析、积分和微分运算,并提供了具体的实现代码和注意事项。此外,文中还分享了一些实用的经验和技术细节,如避免频谱泄漏的方法、处理多频波的技术、防止内存泄漏的措施等。 适用人群:从事信号处理、电子工程、自动化控制等领域的工作技术人员,尤其是那些熟悉或希望学习LabVIEW编程的人士。 使用场景及目标:适用于实验室环境或教学环境中,用于替代传统物理信号发生器进行信号生成和分析实验。主要目标是提高信号生成和分析的灵活性和便捷性,减少对昂贵硬件设备的依赖。 其他说明:本文不仅提供了详细的代码示例,还分享了许多作者在实践中积累的经验教训,帮助读者更好地理解和应用LabVIEW进行信号处理。
线性代数
大雾至尊版V56泛滥无密码.zip
员工生日关怀方案
试用期情况跟踪表.xls
员工激励机制与技巧
员工晋升的自我评价.doc
基于51单片机protues仿真的多功能婴儿车控制器(仿真图、源代码、AD原理图) 该设计为51单片机protues仿真的多功能婴儿车控制器,实现温湿度,音乐,避障,声音监测控制; 1、温湿度检测,婴儿尿湿时会有提醒。 2、声音检测,当婴儿啼哭时也会有提醒。 3、小车避障,小车遇到障碍会后退左转。 4、音乐播放。 5、仿真图、源代码、AD原理图;
内容概要:本文档详细介绍了计算机求职笔试的内容与解答,涵盖编程语言基础、数据结构与算法、编程实践与调试、系统设计与软件工程以及综合题型与开放题五个方面。编程语言基础部分强调了语法规则、数据类型与运算符、面向对象编程的核心概念;数据结构与算法部分讲解了常见数据结构(如线性结构、树与图、哈希表)和高频算法(如排序算法、动态规划、递归与回溯);编程实践与调试部分关注编码能力和调试技巧;系统设计与软件工程部分探讨了设计模式、模块化设计、数据库与网络知识;综合题型与开放题部分则提供了场景题和逻辑思维题的示例。最后给出了备考建议,包括知识体系构建、刷题策略和模拟实战的方法。 适合人群:即将参加计算机相关职位笔试的求职者,特别是对编程语言、数据结构、算法设计有初步了解的应届毕业生或初级工程师。 使用场景及目标:①帮助求职者系统复习计算机基础知识,提升笔试通过率;②通过例题和解答加深对编程语言、数据结构、算法的理解;③提供模拟实战环境,提高时间管理和抗压能力。 阅读建议:建议按照文档提供的知识体系顺序进行系统复习,重点攻克高频题型,利用在线平台刷题练习,并结合实际项目经验进行综合应用,同时注意时间管理和抗压能力的训练。
SecureCRT安装包
物流业人才流失与紧缺现象的对策研究
招聘渠道费用仪表盘P10.pptx
内容概要:本文详细介绍了五相永磁同步电机在Simulink环境下的PI双闭环SVPWM矢量控制建模过程及其优化方法。首先阐述了五相电机相比三相电机的优势,如更小的转矩脉动和更强的容错能力。接着探讨了复杂的Simulink模型搭建,涉及电机本体模块、坐标变换模块、SVPWM模块和PI调节器模块等多个组件。文中提供了具体的Clark变换和PI调节器的代码示例,解释了双闭环控制的工作原理,并详细描述了SVPWM与十扇区划分的具体实现方式。最后展示了模型的性能表现,包括良好的波形质量和快速的动态响应特性。 适合人群:从事电机控制领域的研究人员和技术人员,尤其是对五相永磁同步电机和Simulink建模感兴趣的读者。 使用场景及目标:适用于希望深入了解五相永磁同步电机控制原理并掌握具体实现方法的研究人员和技术人员。目标是帮助读者理解五相电机的特殊性和复杂性,掌握PI双闭环SVPWM矢量控制的建模技巧,提高电机控制系统的设计水平。 其他说明:文章不仅提供了理论知识,还包括了大量的代码片段和实践经验分享,有助于读者更好地理解和应用相关技术。
员工离职交接表-模板.doc
离职率高"冰山"下的真相?你知道多少?
内容概要:本文详细介绍了光伏系统中最大功率点跟踪(MPPT)的一种常见方法——恒定电压法,并探讨了其与PID控制相结合的应用。恒定电压法通过将光伏板的输出电压固定在一个预设值附近,以期接近最大功率点。然而,由于光照和温度的变化,单纯依靠恒定电压法难以精确跟踪最大功率点。因此,引入PID控制器进行动态调整,能够显著提高系统的响应速度和稳定性。文中提供了具体的MATLAB和Python代码示例,展示了如何构建和优化这样的控制系统。同时,还讨论了在Simulink环境中建模时需要注意的关键技术和参数选择。 适合人群:从事光伏系统设计、开发以及维护的技术人员,尤其是希望深入了解MPPT算法原理并掌握具体实现方法的专业人士。 使用场景及目标:适用于需要快速实现MPPT功能的小型光伏系统,特别是在成本受限的情况下。通过学习本文,读者可以掌握恒定电压法的基本概念,学会利用PID控制提升性能的方法,从而更好地应对实际工程项目中的挑战。 其他说明:尽管恒定电压法加上PID控制可以在一定程度上改善MPPT的效果,但它并非最优解。对于更加复杂的环境条件,仍需采用更为先进的算法如电导增量法等。此外,文中提到的一些技巧和注意事项有助于避免常见的错误,确保仿真的准确性。