- 浏览: 70947 次
- 性别:
- 来自: 武汉
最新评论
-
spring_springmvc:
spring mvc demo教程源代码下载,地址:http: ...
springmvc -
mrhuangok:
文章条理清晰,帮了我大忙。
springmvc -
kunsyliu:
...
get加密 -
JeffreyJia:
为什么使用JMS 就必须使用 MDB呢?没有必要吧?
基于Spring打造简单高效通用的异步任务处理系统
4.6 HQL调优
4.6.1 索引调优
HQL看起来和SQL很相似。从HQL的WHERE子句中通常可以猜到相应的SQL WHERE子句。WHERE子句中的字段决定了数据库将选择的索引。
大多数Hibernate开发者所常犯的一个错误是无论何时,当需要新WHERE子句的时候都会创建一个新的索引。因为索引会带来额外的数据更新开销,所以应该争取创建少量索引来覆盖尽可能多的查询。
4.1节
让
你使用一个集合来处理所有可能的数据搜索条件。如果这不太实际,那么你可以使用后端剖析工具来创建一个针对应用程序涉及的所有
SQL的集合。基于那些搜索条件的分类,你最终会得到一个小的索引集。与此同时,还可以尝试向WHERE子句中添加额外的谓语来匹配其他WHERE子句。
范例7
有两个UI搜索器和一个后端守护进程搜索器来搜索名为iso_deals的表。第一个UI搜索器在unexpectedFlag、dealStatus、tradeDate和isold属性上有谓语。
第二个UI搜索器基于用户键入的过滤器,其中包括的内容除tradeDate和isold以外还有其他属性。开始时所有这些过滤器属性都是可选的。
后端搜索器基于isold、participantCode和transactionType属性。
经过进一步业务分析,发现第二个UI搜索器实际是基于一些隐式的unexpectedFlag和dealStatus值来选择数据的。我们还让tradeDate成为过滤器的必要属性(为了使用数据库索引,每个搜索过滤器都应该有必要属性)。鉴于这一点,我们依次使用unexpectedFlag、dealStatus、tradeDate和isold构造了一个复合索引。两个UI搜 索 器都能共用它。(顺序很重要,如果你的谓语以不同的顺序指定这些属性或在它们前罗列了其他属性,数据库就不会选择该复合索引。)
后端搜索器和UI搜索器区别太大,因此我们不得不为它构造另一个复合索引,依次使用isold、participantCode和transactionType。
4.6.2绑定参数 vs.字符串拼接
既可以使用绑定参数构造HQL的WHERE子句,也可以使用字符串拼接的方法,该决定对性能会有一定影响。使用绑定参数的原因是让数据库一次解析 SQL,对后续的重复请求复用生成好的执行计划,这样做节省了CPU时间和内存。然而,为达到最优的数据访问效率,不同的绑定值可能需要不同的SQL执行 计划。
例如,一小段数据范围可能只返回数据总量的5%,而一大段数据范围可能返回数据总量的90%。前者使用索引更好,而后者则最好使用全表扫描。
建议OLTP使用绑定参数,数据仓库使用字符串拼接,因为OLTP通常在一个事务中重复插入和更新数据,只取少量数据;数据仓库通常只有少量SQL查询,有一个确定的执行计划比节省CPU时间和内存更为重要。
要是你知道你的OLTP搜索对不同绑定值应该使用相同执行计划又该怎么办呢?
Oracle 9i及以后版本在第一次调用绑定参数并生成执行计划时能探出参数值。后续调用不会再探测,而是重用之前的执行计划。
4.6.3聚合及排序
你可以在数据库中进行聚合和“order by”,也可以在应用程序的服务层中事先加载所有数据然后做聚合和“order by”操作。推荐使用前者,因为数据库在这方面通常会比你的应用程序做得好。此外,这样做还能节省网络带宽,这也是一种拥有跨数据库移植性的做法。
当你的应用程序对数据聚合和排序有HQL不支持的特定业务规则时除外。
4.6.4覆盖抓取策略
详见4.7.1节 。
4.6.5本地查询
本地查询调优其实并不直接与HQL有关。但HQL的确可以让你直接向底层数据库传递本地查询。我们并不建议这么做,因为本地查询在数据库间不可移植。
4.7抓取策略调优
抓取策略决定了在应用程序需要访问关联对象时,Hibernate以何种方式以及何时获取关联对象。HRD中的第20章“改善性能” 对该主题作了很好的阐述,我们在此将关注它的使用方法。
4.7.1覆盖抓取策略
不同的用户可能会有不同的数据抓取要求。Hibernate允许在两个地方定义数据抓取策略,一处是在映射元数据中,另一处是在HQL或Criteria中覆盖它。
常见的做法是基于主要的抓取用例在映射元数据中定义默认抓取策略,针对少数用例在HQL和Criteria中覆盖抓取策略。
假设pojoA和pojoB是父子关系实例。如果根据业务规则,只是偶尔需要从实体两端加载数据,那你可以声明一个延迟加载集合或代理抓取 (proxy fetching)。当你需要从实体两端获取数据时,可以用立即抓取(eager fetching)覆盖默认策略,例如使用HQL或Criteria配置连接抓取(join fetching)。
另一方面,如果业务规则在大多数时候需要从实体两端加载数据,那么你可以声明立即抓取并在Criteria中设置延迟加载集合或代理抓取来覆盖它(HQL目前还不支持这样的覆盖)。
4.7.2 N+1模式或是反模式?
select抓取会导致N+1问题。如果你知道自己总是需要从关联中加载数据,那么就该始终使用连接抓取。在下面两个场景中,你可能会把N+1视为一种模式而非反模式。
第一种场景,你不知道用户是否会访问关联对象。如果他/她没有访问,那么你赢了;否则你仍然需要额外的N次select SQL语句。这是一种令人左右为难的局面。
第二种场景,pojoA和很多其他POJO有one-to-many关联,例如pojoB和pojoC。使用立即的内连接或外连接抓取会在结果集中 将pojoA重复很多次。当pojoA中有很多非空属性时,你不得不将大量数据加载到持久层中。这种加载需要很多时间,既有网络带宽的原因,如果 Hibernate的会话是有状态的,其中也会有会话缓存的原因(内存消耗和GC暂停)。
如果你有一个很长的one-to-many关联链,例如从pojoA到pojoB到pojoC以此类推,情况也是类似的。
你也许会去使用HQL中的DISTINCT关键字或Cirteria中的distinct功能或是Java的Set接口来消除重复数据。但所有这些都是在Hibernate(在持久层)中实现的,而非数据库中。
如果基于你的网络和内存配置的测试表明N+1性能更好,那么你可以使用批量抓取、subselect抓取或二级缓存来做进一步调优。
范例8
以下是一个使用批量抓取的HBM文件片段:
<class name ="pojoA " table ="pojoA " > … <set name ="pojoBs " fetch ="select " batch-size ="10 " > <key column ="pojoa_id " /> … </set > </class >以下是多端pojoB生成的SQL:
select … from pojoB where pojoa_id in (?,?,?,?,?, ?,?,?,?,?);问号数量与batch-size值相等。因此N次额外的关于pojoB的select SQL语句被减少到了N/10次。
如果将fetch ="select " 替换成fetch ="subselect " ,pojoB生成的SQL语句就是这样的:
select … from pojoB where pojoa_id in (select id from pojoA where …);尽管N次额外的select减少到1次,但这只在重复运行pojoA的查询开销很低时才有好处。
如果pojoA中的pojoB集合很稳定,或pojoB有pojoA的many-to-one关联,而且pojoA是只读引用数据,那么你可以使用二级缓存来缓存pojoA以消除N+1问题(4.8.1节 中有一个例子)。
4.7.3延迟属性抓取
除非有一张拥有很多你不需要的字段的遗留表,否则不应该使用这种抓取策略,因为它的延迟属性分组会带来额外的SQL。
在业务分析和设计过程中,你应该将不同数据获取或修改分组放到不同的领域对象实体中,而不是使用这种抓取策略。
如果不能重新设计遗留表,可以使用HQL或Criteria提供的投影功能来获取数据。
4.8 二级缓存调优
HRD第20.2节 “二级缓存” 中的描述对大多数开发者来说过于简单,无法做出选择。3.3版及以后版本不再推荐使用基于“CacheProvider”的缓存,而用基于“RegionFactory”的缓存,这也让人更糊涂了。但是就算是最新的3.5参考文档也没有提及如何使用新缓存方法。
出于下述考虑,我们将继续关注于老方法:
- 所有流行的Hibernate二级缓存提供商中只有JBoss Cache 2 、Infinispan 4 和Ehcache 2 支持新方法。OSCache 、SwarmCache 、Coherence 和Gigaspaces XAP-Data Grid 只支持老方法。
- 两种方法共用相同的<cache>配置。例如,它们仍旧使用相同的usage属性值“transactional|read-write|nonstrict-read-write|read-only”。
- 多个cache-region适配器仍然内置老方法的支持,理解它能帮助你快速理解新方法。
4.8.1 基于CacheProvider的缓存机制
理解该机制是做出合理选择的关键。关键的类/接口是CacheConcurrencyStrategy和它针对4中不同缓存使用的实现类,还有EntityUpdate/Delete/InsertAction。
针对并发缓存访问,有三种实现模式:
- 针对“read-only”的只读模式。
- 针对“read-write”和“nonstrict-read-write”的非事务感知(non-transaction-aware)读写模式。
- 针对“transactional”的事务感知读写。
无论是锁还是事务都没影响,因为缓存自数据从数据库加载后就不会改变。
对缓存的更新发生在数据库事务完成后。缓存需要支持锁。
对缓存和数据库的更新被包装在同一个JTA事务中,这样缓存与数据库总是保持同步的。数据库和缓存都必须支持JTA。尽管缓存事务内部依赖于缓存锁,但Hibernate不会显式调用任何的缓存锁函数。
以数据库更新为例。EntityUpdateAction对于事务感知读写、“read-write”的非事务感知读写,还有“nonstrict-read-write”的非事务感知读写相应有如下调用序列:
- 在一个JTA事务中更新数据库;在同一个事务中更新缓存。
- 软锁缓存;在一个事务中更新数据库;在上一个事务成功完成后更新缓存;否则释放软锁。
- 在一个事务中更新数据库;在上一个事务完成前就清除缓存;为了安全起见,无论事务成功与否,在事务完成后再次清除缓存。
软锁只是一种特定的缓存值失效表述方式,在它获得新数据库值前阻止其他事务读写缓存。那些事务会转而直接读取数据库。
缓存必须支持锁;事务支持则不是必须的。如果缓存是一个集群,“更新缓存”的调用会将新值推送给所有副本,这通常被称为“推(push)”更新策略。
既不需要支持缓存锁,也不需要支持事务。如果是缓存集群,“清除缓存”调用会让所有副本都失效,这通常被称为“拉(pull)”更新策略。
对于实体的删除或插入动作,或者集合变更,调用序列都是相似的。
实际上,最后两个异步调用序列仍能保证数据库和缓存的一致性(基本就是“read committed”的隔离了级别),这要归功于第二个序列中的软锁和“更新数据库”后的“更新缓存”,还有最后一个调用序列中的悲观“清除缓存”。
基于上述分析,我们的建议是:
- 如果数据是只读的,例如引用数据,那么总是使用“read-only”策略,因为它是最简单、最高效的策略,也是集群安全的策略。
- 除非你真的想将缓存更新和数据库更新放在一个JTA事务里,否则不要使用“transactional”策略,因为JTA需要漫长的两阶段提交处理,这导致它基本是性能最差的策略。
- 如果你的数据读很多或者很少有并发缓存访问和更新,那么可以使用“nonstrict-read-write”策略。感谢它的轻量级“拉”更新策略,它通常是性能第二好的策略。
- 如果你的数据是又读又写的,那么使用“read-write”策略。这通常是性能倒数第二的策略,因为它要求有缓存锁,缓存集群中使用重量级的“推”更新策略。
依笔者看来,二级缓存并非一级数据源,因此使用JTA也未必合理。实际上最后两个调用序列在大多数场景下是个不错的替代方案,这要归功于它们的数据一致性保障。
范例9
以下是一个ISO收费类型的HBM文件片段:
<class name ="IsoChargeType "> <property name ="isoId " column ="ISO_ID " not-null ="true " /> <many-to-one name ="estimateMethod " fetch ="join " lazy ="false " /> <many-to-one name ="allocationMethod " fetch ="join " lazy ="false " /> <many-to-one name ="chargeTypeCategory " fetch ="join " lazy ="false " /> </class >一些用户只需要ISO收费类型本身;一些用户既需要ISO收费类型,还需要它的三个关联对象。简单起见,开发者会立即加载所有三个关联对象。如果项目中没人负责Hibernate调优,这是很常见的。
4.7.1节 中讲过了最好的方法。因为所有的关联对象都是只读引用数据,另一种方法是使用延迟抓取,打开这些对象的二级缓存以避免N+1问题。实际上前一种方法也能从引用数据缓存中获益。
因为大多数项目都有很多被其他数据引用的只读引用数据,上述两种方法都能改善全局系统性能。
4.8.2 RegionFactory
下表是新老两种方法中对应的主要类/接口:
新方法 |
老方法 |
RegionFactory |
CacheProvider |
Region |
Cache |
EntityRegionAccessStrategy |
CacheConcurrencyStrategy |
CollectionRegionAccessStrategy |
CacheConcurrencyStrategy |
第一个改进是RegionFactory构建了特定的Region,例如EntityRegion和TransactionRegion,而不是使 用一个通用的访问Region。第二个改进是对于特定缓存的“usage”属性值,Region要求构建自己的访问策略,而不是所有Region都一直使 用CacheConcurrencyStrategy的4种实现。
要使用新方法,应该设置factory_class而非provider_class配置属性。以Ehcache 2.0为例:
<property name="hibernate.cache.region.factory_class"> net.sf.ehcache.hibernate.EhCacheRegionFactory </property>
其他相关的Hibernate缓存配置都和老方法一样。
新方法也能向后兼容遗留方法。如果还是只配了CacheProvider,新方法中将使用下列自说明(self-explanatory)适配器和桥隐式地调用老的接口/类:
RegionFactoryCacheProviderBridge、EntityRegionAdapter、 CollectionRegionAdapter、QueryResultsRegionAdapter、 EntityAccessStrategyAdapter和CollectionAccessStrategyAdapter
4.8.3 查询缓存
二级缓存也能缓存查询结果。如果查询开销很大而且要重复运行,这也会很有帮助。
4.9批量处理调优
大多数Hibernate的功能都很适合那些每个事务都通常只处理少量数据的OLTP系统。但是,如果你有一个数据仓库或者事务需要处理大量数据,那么就另当别论了。
4.9.1使用有状态会话的非DML风格批处理
如果你已经在使用常规会话了,那这是最自然的方法。你需要做三件事:
- 配置下列3个属性以开启批处理特性:
hibernate.jdbc.batch_size 30 hibernate.jdbc.batch_versioned_data true hibernate.cache.use_second_level_cache false
batch_size设置为正值会开启JDBC2的批量更新,Hibernate的建议值是5到30。基于我们的测试,极低值和极高值性能都很差。只要取值在合理范围内,区别就只有几秒而已。如果网络够快,这个结果是一定的。
第二个配置设为true,这要求JDBC驱动在executeBatch()方法中返回正确的行数。对于Oracle用户而言,批量更新时不能将其设为true。请阅读Oracle的《JDBC Developer’s Guide and Reference》中的“标准批处理的Oracle实现中的更新计数 ”(Update Counts in the Oracle Implementation of Standard Batching )以获得更多详细信息。因为它对批量插入来说还是安全的,所以你可以为批量插入创建单独的专用数据源。最后一个配置项是可选的,因为你可以在会话中显式关闭二级缓存。
Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
Customer customer = new Customer(.....);
//if your hibernate.cache.use_second_level_cache is true, call the following:
session.setCacheMode(CacheMode.IGNORE);
session.save(customer);
if (i % 50 == 0) { //50, same as the JDBC batch size
//flush a batch of inserts and release memory:
session.flush();
session.clear();
}
}
tx.commit();
session.close();
批处理通常不需要数据缓存,否则你会将内存耗尽并大量增加GC开销。如果内存有限,那这种情况会很明显。
每次事务修改的对象数量越少就意味着会有更多数据库提交,正如4.5节 所述每次提交都会带来磁盘相关的开销。
另一方面,每次事务修改的对象数量越多就意味着锁定变更时间越长,同时数据库需要更大的redo log。
4.9.2使用无状态会话的非DML风格批处理
无状态会话执行起来比上一种方法更好,因为它只是JDBC的简单包装,而且可以绕开很多常规会话要求的操作。例如,它不需要会话缓存,也不和任何二级缓存或查询缓存有交互。
然而它的用法并不简单。尤其是它的操作并不会级联到所关联的实例上;你必须自己来处理它们。
4.9.3 DML风格
使用DML风格的插入、更新或删除,你直接在数据库中操作数据,这和前两种方法在Hibernate中操作数据的情况有所不同。
因为一个DML风格的更新或删除相当于前两种方法中的多个单独的更新或删除,所以如果更新或删除中的WHERE子句暗示了恰当的数据库索引,那么使用DML风格的操作能节省网络开销,执行得更好。
强烈建议结合使用DML风格操作和无状态会话。如果使用有状态会话,不要忘记在执行DML前清除缓存,否则Hibernate将会更新或清除相关缓存(见下面的范例10)。
4.9.4批量加载
如果你的HQL或Criteria会返回很多数据,那么要注意两件事:
- 用下列配置开启批量抓取特性:
hibernate.jdbc.fetch_size 10
fetch_size设置为正值将开启JDBC批量抓取特性。相对快速网络,在慢速网络中这一点更为重要。Oracle建议的经验值是10。你应该基于自己的环境进行测试。
范例10
我们有一个后台任务,分段加载大量的IsoDeal数据用于后续处理。我们还会在分段数据交给下游系统处理前将其更新为处理中状态。最大的一段有50万行数据。以下是原始代码中截取出来的一段:
Query query = session.createQuery("FROM IsoDeal d WHERE chunk-clause "); query.setLockMode("d" , LockMode.UPGRADE ); //for Inprocess status update List<IsoDeal> isoDeals = query.list(); for (IsoDeal isoDeal : isoDeals) { //update status to Inprocess isoDeal.setStatus("Inprocess" ); } return isoDeals;包含上述代码的方法加上了Spring 2.5声明式事务的注解。加载并更新50万行数据大约花了10分钟。我们识别出了以下这些问题:
- 由于会话缓存和二级缓存的原因,系统会频繁地内存溢出。
- 就算没有内存溢出,当内存消耗很高时GC的开销也会很大。
- 我们还未设置fetch_size。
- 就算我们设置了batch_size,for循环也创建了太多update SQL语句。
不幸的是Spring 2.5不支持Hibernate无状态会话,所以我们只能关闭二级缓存;设置fetch_size;用DML风格的更新来代替for循环,以此改善性能。
但是,执行时间还是要6分钟。将Hibernate的日志级别调成trace后,我们发现是更新会话缓存造成了延时。通过在DML更新前清除会话缓存,我们将时间缩短到了4分钟,全部都是将数据加载到会话缓存中花费的时间。
4.10 SQL生成调优
本节将向你展示如何减少SQL生成的数量。
4.10.1 N+1抓取问题
“select抓取”策略会导致N+1问题。如果“连接抓取”策略适合你的话,你应该始终使用该策略避免N+1问题。
但是,如果“连接抓取”策略执行效果不理想,就像4.7.2节 中那样,你可以使用“subselect抓取”、“批量抓取”或“延迟集合抓取”来减少所需的额外SQL语句数。
4.10.2 Insert+Update问题
范例11
我们的ElectricityDeal与DealCharge有单向one-to-many关联,如下列HBM文件片段所示:
<class name ="ElectricityDeal " select-before-update ="true " dynamic-update ="true " dynamic-insert ="true " > <id name ="key " column ="ID " > <generator class ="sequence " > <param name ="sequence " >SEQ_ELECTRICITY_DEALS</param > </generator> </id> … <set name ="dealCharges " cascade ="all-delete-orphan "> <key column ="DEAL_KEY " not-null ="false " update ="true " on-delete ="noaction " /> <one-to-many class ="DealCharge " /> </set> </class>
在“key”元素中,“not-null”和“update”对应的默认值是false和true,上述代码为了明确这些取值,将它们写了出来。
如果你想创建一个ElectricityDeal和十个DealCharge,会生成如下SQL语句:
- 1句ElectricityDeal的插入语句;
- 10句DealCharge的插入语句,其中不包括外键“DEAL_KEY”;
- 10句DealCharge字段“DEAL_KEY”的更新语句。
为了消除那额外的10句更新语句,可以在那10句DealCharge插入语句中包含“DEAL_KEY”,你需要将“not-null”和“update”分别修改为true和false。
另一种做法是使用双向或many-to-one关联,让DealCharge来管理关联。
4.10.3 更新前执行select
在范例11中,我们为ElectricityDeal加上了select-before-update,这会对瞬时(transient)对象或分离(detached)对象产生额外的select语句,但却能避免不必要的数据库更新。
你应该做出一些权衡,如果对象没多少属性,不需要防止不必要的数据库更新,那么就不要使用该特性,因为你那些有限的数据既没有太多网络传输开销,也不会带来太多数据库更新开销。
如果对象的属性较多,例如是一张大的遗留表,那你应该开启该特性,和“dynamic-update”结合使用以避免太多数据库更新开销。
4.10.4 级联删除
在范例11中,如果你想删除1个ElectricityDeal和它的100个DealCharge,Hibernate会对DealCharge做100次删除。
如果将“on-delete”修改为“cascade”,Hibernate不会执行DealCharge的删除动作;而是让数据库根据ON CASCADE DELETE约束自动删除那100个DealCharge。不过,需要让DBA开启ON CASCADE DELETE约束,大多数DBA不愿意这么做,因为他们想避免父对象的意外删除级联到它的依赖对象上。此外,还要注意,该特性会绕过Hibernate对 版本数据(versioned data)的常用乐观锁策略。
4.10.5 增强的序列标识符生成器
范例11中使用Oracle的序列作为标识符生成器。假设我们保存100个ElectricityDeal,Hibernate会将下面的SQL语句执行100次来获取下一个可用的标识符:
select SEQ_ELECTRICITY_DEALS.NEXTVAL from dual;
如果网络不是很快,那这无疑会降低效率。3.2.3及后续版本中增加了一个增强的生成器“SequenceStyleGenerator”,它带了两个优化器:hilo和pooled。尽管HRD的第5章“基础O/R映射” 讲到了这两个优化器,不过内容有限。两个优化器都使用了HiLo算法,该算法生成的标识符等于Hi值加上Lo值,其中Hi值代表组号,Lo值顺序且重复地从1迭代到最大组大小,组号在Lo值“转回到”1时加1。
假设组大小是5(可以用max_lo或increment_size参数来表示),下面是个例子:
- hilo优化器
- pooled优化器
组号取自数据库序列的下一个可用值,Hi值由Hibernate定义,是组号乘以increment_size参数值。
Hi值直接取自数据库序列的下一个可用值。数据库序列的增量应该设置为increment_size参数值。
直到内存组中的值耗尽后,两个优化器才会去访问数据库,上面的例子每5个标识值符访问一次数据库。使用hilo优化器时,你的序列不能再被其他应用程序使用,除非它们使用与Hibernate相同的逻辑。使用pooled优化器,在其他应用程序使用同一序列时则相当安全。
两个优化器都有一个问题,如果Hibernate崩溃,当前组内的一些标识符值就会丢失,然而大多数应用程序都不要求拥有连续的标识符值(如果你的数据库,比方说Oracle,缓存了序列值,当它崩溃时你也会丢失标识符值)。
如果在范例11中使用pooled优化器,新的id配置如下:
<id name ="key" column ="ID" > <generator class ="org.hibernate.id.enhance .SequenceStyleGenerator" > <param name ="sequence_name" > SEQ_ELECTRICITY_DEALS</param> <param name ="initial_value" > 0</param> <param name ="increment_size" > 100</param> <param name ="optimizer " > pooled</param> </generator> </id>
5 总结
本文涵盖了大多数你在Hibernate应用程序调优时会觉得很有用的调优技巧,其中的大多数时间都在讨论那些行之有效却缺乏文档的调优主题,例如继承映射、二级缓存和增强的序列标识符生成器。
它还提到了一些Hibernate调优所必需的数据库知识。一些范例中包含了你可能遇到的问题的实际解决方案。
除此之外,值得一提的是Hibernate也可以和In-Memory Data Grid(IMDG)一起使用,例如Oracle的Coherance或GigaSpaces IMDG,这能让你的应用程序达到毫秒级别。
发表评论
-
jcl与jul、log4j1、log4j2、logback的集成原理
2017-12-01 15:59 534jcl与jul、log4j1、log4j2、logbac ... -
slf4j与jul、log4j1、log4j2、logback的集成原理
2017-12-01 15:52 427收藏 jd ... -
预编译分析
2017-11-29 10:26 654一.背景: 用Mybatis+my ... -
预编译
2017-11-29 09:57 710PreparedStatement 在说PreparedS ... -
Spring Boot应用的后台运行配置
2017-11-21 14:26 540Spring Boot应用的后台运行配置 酱油一篇,整 ... -
编码
2017-11-21 14:25 523几种常见的编码格式 为什么要编码 不知道大家有没有想过一 ... -
Spring Boot应用的后台运行配置
2017-11-29 09:58 737Spring Boot应用的后台运行配置 酱油一篇, ... -
spring boot 注解
2017-11-01 10:58 347@EnableAutoConfiguration和@Spr ... -
支付话题
2015-09-09 11:45 1450本文档适用人员:交易领域的产品研发人员 提纲: 银 ... -
深入分析 Java 中的中文编码问题
2014-12-19 10:21 602在 IBM Bluemix 云平台上开发并部署您的下一个应 ... -
hashmap死循环
2014-11-24 10:45 755疫苗:Java HashMap的死循环 在淘宝内 ... -
jquery
2014-02-07 09:03 765当你准备使用jQuery,我强烈建议你遵循下面这些指南: ... -
减轻页面压力
2014-01-26 09:04 611网站快速加载,是提供 ... -
linux 命令
2014-01-23 09:20 402一.linux快捷键 Ctrl+C : 终止当前命令 C ... -
mina
2013-10-15 12:49 1362<!--StartFragment --> ... -
spring 线程池
2013-10-12 14:35 684Spring 线程池使用 Spring ... -
性能监控
2013-07-08 10:34 793spring,真是一个好东西;性能,真是个让人头疼又不 ... -
java ftp
2013-06-24 11:05 880在项目中使用到FTP功能,于是采用类似Spring的各种 ... -
json
2013-06-21 14:01 721JSON小结【json-lib】 j ... -
基于Spring打造简单高效通用的异步任务处理系统
2013-05-21 14:24 3928背景 随着应用系统功 ...
相关推荐
### Hibernate 性能调优详解 #### 一、概述 Hibernate 是一款优秀的 Java 持久层框架,它简化了数据库操作,使开发者能够更加关注业务逻辑而不是底层的数据访问细节。然而,在实际应用中,为了确保应用的高性能与...
### Hibernate性能调优知识点 #### 一、理解Hibernate与关联管理 在Hibernate中,关联管理是性能优化的关键因素之一。关联通常包括以下几种类型:单向`one-to-many`关联、双向`one-to-many`关联、`many-to-one`关联...
### Hibernate的开发注意项与性能调优 在长期的软件开发过程中,Hibernate作为一款流行的ORM(对象关系映射)框架,被广泛应用于Java项目中。然而,在实际的应用场景下,如何进行性能调优是一个非常重要的话题。...
最后,书中会探讨如何在实际项目中集成和优化Hibernate,包括事务管理、性能调优、问题排查等实战技巧。这有助于开发者在实际开发过程中更好地应用Hibernate,提升项目的稳定性和效率。 总的来说,《精通Hibernate...
《Hibernate技术手册》是针对Java开发人员的一份详尽指南,它深入剖析了Hibernate这一流行的持久化框架。Hibernate是一个对象关系映射(ORM)工具,它简化了数据库操作,允许开发者使用面向对象的方式处理数据库交互...
**hibernate持久化技术详解** Hibernate是一款强大的Java对象关系映射(ORM)框架,它为开发者提供了在Java应用中操作数据库的强大工具。通过Hibernate,开发者可以将数据库操作转化为对Java对象的操作,大大降低了...
文章通过一个使用Hibernate 3.3.1和Oracle 9i的实际项目案例,详细介绍了多个调优技术,并强调了数据库知识的重要性。 文章首先指出,调优是一个持续的过程,涵盖了从业务规则到底层系统各个层面。在使用Hibernate...
9. **Chapter 10**:最后,作者可能讨论了如何将Hibernate与其他技术(如Spring框架)集成,以及在实际项目中如何进行最佳实践和性能调优。 通过这些章节的学习,读者不仅可以理解Hibernate的工作原理,还能熟练...
总结,Hibernate的批处理是大数据场景下提高性能的关键技术之一,需要根据具体业务需求和系统资源进行细致的配置和优化。了解并掌握这些知识点,能够帮助开发者更高效地利用Hibernate处理大规模数据。
总之,《Hibernate4.0中文文档》是Java开发者的必备读物,它覆盖了Hibernate的所有核心概念和技术,帮助开发者高效地利用Hibernate进行数据库操作,从而提高开发效率并降低维护成本。通过深入学习和实践,开发者可以...
**EJB(Enterprise JavaBeans)与Hibernate的整合是Java企业级开发中的一项重要技术结合,主要目的是为了在EJB容器中充分利用Hibernate的持久化能力,提高数据管理的灵活性和效率。** EJB,全称为Enterprise ...
Struts2提供了强大的拦截器机制,可以灵活地处理请求和响应,支持多种视图技术如JSP、FreeMarker等,并且可以与各种持久层框架如Hibernate集成。 **Hibernate** 是一个对象关系映射(ORM)框架,它简化了Java应用与...
**Hibernate 框架概述** Hibernate 是一个开源的对象关系映射(ORM)框架,它允许开发者用面向对象的...通过学习这些教程和书籍,你可以更好地理解和掌握 ORM 技术,提升开发效率,减少与数据库交互时的错误和复杂性。
7. 扩展与整合:讲解了Hibernate与其他技术的集成,如Spring框架、EJB、JPA,以及如何自定义类型和事件监听器。 8. 性能调优:提供了实用的性能调优技巧,包括数据库配置、连接池选择、查询优化和实体管理策略等。 ...
【描述】:这个项目是一个基于Java技术栈的论坛系统实现,主要利用了Hibernate ORM框架与JSP(JavaServer Pages)进行开发,是适合学生作为毕业论文项目的实例。它展示了如何将数据库操作与Web界面相结合,为用户...
7. **性能调优**:提供一系列技巧和最佳实践,帮助开发者优化 Hibernate 应用程序的性能。 8. **高级主题**:介绍 Hibernate 的一些高级特性,如缓存机制、批量更新/删除等。 #### 六、目标读者群体 这本书主要...
4. 性能优化:可能包含了针对Spring和Hibernate的性能调优策略,如缓存机制、批处理操作等。 5. 安全性增强:可能集成了安全框架如Spring Security,提供用户认证和授权功能。 6. 日志和监控:可能实现了详细的日志...
在IT行业中,数据库连接池是优化数据库访问性能的重要技术之一,而Hibernate作为一款流行的Java对象关系映射(ORM)框架,提供了与各种连接池的集成,包括Proxool。本篇将详细介绍如何在Hibernate中使用Proxool作为...