当前位置: 首页 > news >正文

太原网站网络推广装修加盟

太原网站网络推广,装修加盟,中国前500强企业排名,我是做网站怎么赚钱吗hibernate批量查询如果需要从Java处理大型数据库结果集#xff0c;则可以选择JDBC#xff0c;以提供所需的低级控制。 另一方面#xff0c;如果您已在应用程序中使用ORM#xff0c;则回退到JDBC可能会带来一些额外的麻烦。 在导航域模型时#xff0c;您将失去诸如乐观锁定… hibernate批量查询 如果需要从Java处理大型数据库结果集则可以选择JDBC以提供所需的低级控制。 另一方面如果您已在应用程序中使用ORM则回退到JDBC可能会带来一些额外的麻烦。 在导航域模型时您将失去诸如乐观锁定缓存自动获取之类的功能。 幸运的是大多数ORM例如Hibernate都有一些选择来帮助您。 虽然这些技术不是新技术但有两种可能可供选择。 一个简化的例子 假设我们有一个表映射到类DemoEntity具有100.000条记录。 每个记录由一个列映射到DemoEntity中的属性“ property”组成其中包含一些大约2KB的随机字母数字数据。 JVM与-Xmx250m一起运行。 假设250MB是可以分配给系统上JVM的总最大内存。 您的工作是读取表中当前的所有记录进行一些未进一步指定的处理最后存储结果。 我们假设批量操作产生的实体没有被修改。 首先我们将首先尝试显而易见的方法即执行查询以简单地检索所有数据 new TransactionTemplate(txManager).execute(new TransactionCallbackVoid() {Overridepublic Void doInTransaction(TransactionStatus status) {Session session sessionFactory.getCurrentSession();ListDemoEntity demoEntitities (ListDemoEntity) session.createQuery(from DemoEntity).list();for(DemoEntity demoEntity : demoEntitities){//Process and write result}return null;} }); 几秒钟后 Exception in thread main java.lang.OutOfMemoryError: GC overhead limit exceeded 显然这不会削减。 为了解决这个问题我们将切换到Hibernate可滚动结果集这可能是大多数开发人员都知道的。 上面的示例指示hibernate执行查询将整个结果映射到实体并返回它们。 使用滚动结果集时记录一次转换为一个实体 new TransactionTemplate(txManager).execute(new TransactionCallbackVoid() {Overridepublic Void doInTransaction(TransactionStatus status) {Session session sessionFactory.getCurrentSession();ScrollableResults scrollableResults session.createQuery(from DemoEntity).scroll(ScrollMode.FORWARD_ONLY);int count 0;while (scrollableResults.next()) {if (count 0 count % 100 0) {System.out.println(Fetched count entities);}DemoEntity demoEntity (DemoEntity) scrollableResults.get()[0];//Process and write result}return null;} }); 运行此后我们得到 ... Fetched 49800 entities Fetched 49900 entities Fetched 50000 entities Exception in thread main java.lang.OutOfMemoryError: GC overhead limit exceeded 尽管我们使用的是可滚动的结果集但每个返回的对象都是一个附加对象并成为持久性上下文即会话的一部分。 结果实际上与我们使用“ session.createQueryfrom DemoEntity。list 的第一个示例相同。 但是采用这种方法我们无法控制。 一切都在幕后发生如果Hibernate完成了工作您将获得包含所有数据的列表。 另一方面使用可滚动的结果集使我们迷上了检索过程并允许我们在需要时释放内存。 正如我们已经看到的那样它不会自动释放内存您必须指示Hibernate实际执行此操作。 存在以下选项 处理对象后将其从持久性上下文中逐出 偶尔清除整个会话 我们将选择第一个。 在上面的示例的第13行 // Process和write result 下我们将添加 session.evict(demoEntity); 重要 如果您要对实体或与其有关联的实体进行级联逐出进行任何修改请确保在逐出或清除之前刷新会话否则由于Hibernate的回写而导致的查询将不会发送到数据库 逐出或清除不会将实体从二级缓存中删除。 如果启用了二级缓存并正在使用它并且还希望将其删除请使用所需的sessionFactory.getCache。evictXxx方法 从您退出实体的那一刻起该实体将不再附加不再与会话关联。 在该阶段对实体所做的任何修改将不再自动反映到数据库中。 如果您使用的是延迟加载则访问驱逐之前未加载的任何属性都会产生著名的org.hibernate.LazyInitializationException。 因此基本上在逐出或清除之前请确保已完成对该实体的处理或至少已对其进行初始化以进一步满足需要 再次运行该应用程序后我们看到它现在已成功执行 ... Fetched 99800 entities Fetched 99900 entities Fetched 100000 entities 顺便说一句; 您还可以将查询设置为只读以允许Hibernate执行一些其他优化 ScrollableResults scrollableResults session.createQuery(from DemoEntity).setReadOnly(true).scroll(ScrollMode.FORWARD_ONLY); 这样做只会在内存使用方面产生很小的差异在此特定的测试设置中它使我们能够在给定的内存量下额外读取约300个实体。 就我个人而言我不会仅将此功能仅用于内存优化而仅当它适合您的整体不变性策略时才使用。 使用hibernate您可以使用不同的选项将实体设置为只读在实体本身上整个会话为只读依此类推。 分别对查询设置只读为false可能是最不推荐的方法。 例如之前在会话中加载的实体将保持不受影响可能可修改。即使查询返回的根对象是只读的惰性关联也将可修改地加载。 好的我们能够处理我们的100.000条记录生活很好。 但是事实证明Hibernate对于批量操作还有另一个选择无状态会话。 您可以从无状态会话中获取可滚动结果集方法与从普通会话中获取方法相同。 无状态会话直接位于JDBC之上。 Hibernate将在几乎“所有功能禁用”模式下运行。 这意味着没有持久上下文没有第二级缓存没有脏检测没有延迟加载基本上什么也没有。 从javadoc /*** A command-oriented API for performing bulk operations against a database.* A stateless session does not implement a first-level cache nor interact with any * second-level cache, nor does it implement transactional write-behind or automatic * dirty checking, nor do operations cascade to associated instances. Collections are * ignored by a stateless session. Operations performed via a stateless session bypass * Hibernates event model and interceptors. Stateless sessions are vulnerable to data * aliasing effects, due to the lack of a first-level cache. For certain kinds of * transactions, a stateless session may perform slightly faster than a stateful session.** author Gavin King*/ 它唯一要做的就是将记录转换为对象。 这可能是一个有吸引力的选择因为它可以帮助您摆脱手动驱逐/冲洗的麻烦 new TransactionTemplate(txManager).execute(new TransactionCallbackVoid() {Overridepublic Void doInTransaction(TransactionStatus status) {sessionFactory.getCurrentSession().doWork(new Work() {Overridepublic void execute(Connection connection) throws SQLException {StatelessSession statelessSession sessionFactory.openStatelessSession(connection);try {ScrollableResults scrollableResults statelessSession.createQuery(from DemoEntity).scroll(ScrollMode.FORWARD_ONLY);int count 0;while (scrollableResults.next()) {if (count 0 count % 100 0) {System.out.println(Fetched count entities);}DemoEntity demoEntity (DemoEntity) scrollableResults.get()[0];//Process and write result }} finally {statelessSession.close();}}});return null;} }); 除了无状态会话具有最佳的内存使用情况外使用它还会带来一些副作用。 您可能已经注意到我们正在打开一个无状态会话并显式关闭它既没有sessionFactory.getCurrentStatelessSession也没有在撰写本文时任何用于管理无状态会话的Spring集成。打开无状态会话会分配一个新的Java。默认情况下sql.Connection如果使用openStatelessSession 执行其工作因此间接产生第二个事务。 您可以通过使用Hibernate工作API来减轻这些副作用如提供当前Connection并将其传递给openStatelessSessionConnection connection的示例中所示。 最后关闭会话对物理连接没有影响因为它是由Spring基础结构捕获的打开无状态会话时仅逻辑连接句柄已关闭并且创建了新的逻辑连接句柄。 还要注意您必须自己关闭无状态会话并且上面的示例仅适用于只读操作。 从您打算使用无状态会话进行修改的那一刻起还有更多警告。 如前所述Hibernate模式在“所有功能都已禁用”模式下运行因此直接导致实体以分离状态返回。 对于您修改的每个实体您都必须明确地调用 statelessSession.updateentity 。 首先我尝试使用此方法来修改实体 new TransactionTemplate(txManager).execute(new TransactionCallbackVoid() {Overridepublic Void doInTransaction(TransactionStatus status) {sessionFactory.getCurrentSession().doWork(new Work() {Overridepublic void execute(Connection connection) throws SQLException {StatelessSession statelessSession sessionFactory.openStatelessSession(connection);try {DemoEntity demoEntity (DemoEntity) statelessSession.createQuery(from DemoEntity where id 1).uniqueResult();demoEntity.setProperty(test);statelessSession.update(demoEntity);} finally {statelessSession.close();}}});return null;} }); 这个想法是我们用现有的数据库Connection打开一个无状态会话。 正如StatelessSession javadoc指示不会发生任何回写一样我确信无状态会话执行的每个语句都将直接发送到数据库。 最终当提交事务由TransactionTemplate开始时结果将在数据库中可见。 但是hibernate使用无状态会话来执行BATCH语句。 我不是100知道批处理和回写之间有什么区别但是结果是相同的因此与javadoc的字典相反因为语句在以后排队并刷新。 因此如果您不执行任何特殊操作则不会刷新批处理的语句这就是我的情况“ statelessSession.updatedemoEntity;” 被分批处理从不冲洗。 强制刷新的一种方法是使用Hibernate事务API StatelessSession statelessSession sessionFactory.openStatelessSession(); statelessSession.beginTransaction(); ... statelessSession.getTransaction().commit(); ... 在这种情况下您可能不想仅仅因为使用无状态会话就开始以编程方式控制事务。 此外由于没有传递我们的Connection因此我们再次在第二个事务场景中运行无状态会话工作因此将获得新的数据库连接。 我们无法通过外部连接的原因是如果我们提交内部事务“无状态会话事务”并且它将使用与外部事务相同的连接由TransactionTemplate开始则会破坏外部事务事务原子性因为从外部事务发送到数据库的语句将与内部事务一起提交。 因此不通过连接意味着打开一个新的连接从而创建第二笔交易。 更好的选择是触发Hibernate刷新无状态会话。 但是statelessSession没有“ flush”方法来手动触发刷新。 这里的解决方案是稍微依赖于Hibernate内部API。 该解决方案使手动事务处理和第二个事务处理变得过时所有语句成为我们唯一的外部事务的一部分 StatelessSession statelessSession sessionFactory.openStatelessSession(connection);try {DemoEntity demoEntity (DemoEntity) statelessSession.createQuery(from DemoEntity where id 1).uniqueResult();demoEntity.setProperty(test);statelessSession.update(demoEntity);((TransactionContext) statelessSession).managedFlush();} finally {statelessSession.close(); } 幸运的是最近在Spring jira上发布了一个更好的解决方案 https : //jira.springsource.org/browse/SPR-2495这还不是Spring的一部分但是工厂bean的实现非常简单 StatelessSessionFactoryBean。 java的时候使用这个你可以简单的注入StatelessSession Autowired private StatelessSession statelessSession; 它将注入一个无状态的会话代理这等效于正常的“当前”会话的工作方式稍有不同的是您注入一个SessionFactory并且每次都需要获取currentSession。 调用代理时它将查找绑定到正在运行的事务的无状态会话。 如果已经不存在它将创建一个与普通会话相同的连接就像我们在示例中所做的那样并为无状态会话注册自定义事务同步。 提交事务后由于同步将刷新无状态会话并最终将其关闭。 使用此方法您可以直接注入无状态会话并将其用作当前会话或与注入JPA PeristentContext相同的方式。 这使您不必处理无状态会话的打开和关闭而不必处理一种或多种方法以使其变得畅通无阻。 该实现是针对JPA的但是JPA部分仅限于在getPhysicalConnection中获得物理连接。 您可以轻松地省略EntityManagerFactory并直接从Hibernate会话获取物理连接。 非常谨慎的结论最好的方法显然取决于您的情况。 如果您使用普通会话则在读取或持久存储实体时必须自行解决。 如果您有一个混合事务那么除了必须手动执行操作之外还可能影响会话的进一步使用。 你们都在同一笔交易中执行“批量”和“正常”操作。 如果继续进行正常操作您将在会话中分离实体这可能会导致意外结果因为脏检测将不再起作用依此类推。 另一方面您仍将具有主要的Hibernate优势只要不驱逐该实体例如延迟加载缓存脏检测等。 在编写本文时使用无状态会话需要额外注意管理它打开关闭和刷新这也容易出错。 假设您可以继续使用建议的工厂bean那么您将拥有一个非常裸露的会话该会话与正常会话是分开的但仍参与同一事务。 有了它您就拥有了一个强大的工具来执行批量操作而无需考虑内存管理。 缺点是您没有其他可用的Hibernate功能。 参考在Koen Serneels – Technology博客博客上从我们的JCG合作伙伴 Koen Serneels 与Hibernate进行批量获取 。 翻译自: https://www.javacodegeeks.com/2013/03/bulk-fetching-with-hibernate.htmlhibernate批量查询
http://www.zqtcl.cn/news/470479/

相关文章:

  • 网站建设科技国外网站入口
  • 怎样用网站做淘宝推广免费的项目管理软件
  • 共青城网站建设微网站开发报价
  • 网站建设选超速云建站网站建设公司比较
  • 芜湖网络科技有限公司沈阳网站推广优化公司哪家好
  • 自己制作图片文字图片网站建设和优化内容最重要性
  • 邢台做网站优化建筑行业新闻资讯
  • 站长统计app最新版本2023网站标题是关键词吗
  • 中山精品网站建设市场wordpress登陆phpadmin
  • 泸县手机网站建设佛山城市建设工程有限公司
  • 长沙网站推广排名优化wordpress主题字体更改
  • 深圳网站建设软件定制公司房地产开发公司注册资金要求
  • 个人如何在企业网站做实名认证房地产平面设计主要做什么
  • 网站做字工具WordPress搜索功能增强
  • 慢慢来做网站多少钱wordpress优化搜索引擎
  • 网页 网站 区别现在装宽带要多少钱
  • 黄金网站下载免费建设个人网站需要什么条件
  • 网站开发人员岗位职责网站维护报价单
  • 免费正能量不良网站推荐自建网站视频教程
  • 厦门物流网站建设南京宜电的网站谁做的
  • vps 网站备案手机界面设计素材
  • seo排名影响因素主要有灯塔seo
  • 济南哪家做网站小勇cms网站管理系统
  • sns社交网站注册做网站 提交源码 论坛
  • wordpress网站编辑semir是什么牌子
  • 做区块链的网站教育培训机构平台
  • 系统网站怎么做的seo竞争对手分析
  • 菏泽网站建设菏泽众皓网页开发工资
  • 网站建设需求分析酒类群晖wordpress 映射
  • 呼和浩特网站建设宣传wordpress淘宝客插件开发