精华内容
下载资源
问答
  • 点击上方“小哈学Java”,选择“星标”回复“666”,领取100G独家整理的学习资料哟~来源:http://t.cn/AiCTERJzJava 应用性能优化是一个老生常谈的话题,典型的性能问题如页面响应慢、接口超时,...Java 应用性...

    点击上方“小哈学Java”,选择星标

    回复“666”,领取100G独家整理的学习资料哟~

    31772ff9f9a59647f5f51559e880c776.png

    来源:http://t.cn/AiCTERJz

    Java 应用性能优化是一个老生常谈的话题,典型的性能问题如页面响应慢、接口超时,服务器负载高、并发数低,数据库频繁死锁等。尤其是在“糙快猛”的互联网开发模式大行其道的今天,随着系统访问量的日益增加和代码的臃肿,各种性能问题开始纷至沓来。

    Java 应用性能的瓶颈点非常多,比如磁盘、内存、网络 I/O 等系统因素,Java 应用代码,JVM GC,数据库,缓存等。笔者根据个人经验,将 Java 性能优化分为 4 个层级:应用层、数据库层、框架层、JVM 层,如图 1 所示。

    图 1.Java 性能优化分层模型
    8965a4a962a8cc552707e90d88e05145.png

    每层优化难度逐级增加,涉及的知识和解决的问题也会不同。比如应用层需要理解代码逻辑,通过 Java 线程栈定位有问题代码行等;数据库层面需要分析 SQL、定位死锁等;框架层需要懂源代码理解框架机制;JVM 层需要对 GC 的类型和工作机制有深入了解,对各种 JVM 参数作用了然于胸。

    围绕 Java 性能优化,有两种最基本的分析方法:现场分析法和事后分析法。

    现场分析法通过保留现场,再采用诊断工具分析定位。现场分析对线上影响较大,部分场景(特别是涉及到用户关键的在线业务时)不太合适。

    事后分析法需要尽可能多收集现场数据,然后立即恢复服务,同时针对收集的现场数据进行事后分析和复现。下面我们从性能诊断工具出发,分享一些案例与实践。

    1、性能诊断工具

    性能诊断一种是针对已经确定有性能问题的系统和代码进行诊断,还有一种是对预上线系统提前性能测试,确定性能是否符合上线要求。

    本文主要针对前者,后者可以用各种性能压测工具(例如 JMeter)进行测试,不在本文讨论范围内。

    针对 Java 应用,性能诊断工具主要分为两层:OS 层面和 Java 应用层面(包括应用代码诊断和 GC 诊断)。

    OS 诊断

    OS 的诊断主要关注的是 CPU、Memory、I/O 三个方面。

    2、CPU 诊断

    对于 CPU 主要关注平均负载(Load Average),CPU 使用率,上下文切换次数(Context Switch)。

    通过 top 命令可以查看系统平均负载和 CPU 使用率,图 2 为通过 top 命令查看某系统的状态。

    图 2.top 命令示例

    812bbf01bbb832f55643bbc9314edb9e.png

    平均负载有三个数字:63.66,58.39,57.18,分别表示过去 1 分钟、5 分钟、15 分钟机器的负载。按照经验,若数值小于 0.7*CPU 个数,则系统工作正常;若超过这个值,甚至达到 CPU 核数的四五倍,则系统的负载就明显偏高。

    图 2 中 15 分钟负载已经高达 57.18,1 分钟负载是 63.66(系统为 16 核),说明系统出现负载问题,且存在进一步升高趋势,需要定位具体原因了。

    通过 vmstat 命令可以查看 CPU 的上下文切换次数,如图 3 所示:

    图 3.vmstat 命令示例f142a67a6493a78eba421ece83666b04.png

    上下文切换次数发生的场景主要有如下几种:

    • 1)时间片用完,CPU 正常调度下一个任务;

    • 2)被其它优先级更高的任务抢占;

    • 3)执行任务碰到 I/O 阻塞,挂起当前任务,切换到下一个任务;

    • 4)用户代码主动挂起当前任务让出 CPU;

    • 5)多任务抢占资源,由于没有抢到被挂起;

    • 6)硬件中断。

    Java 线程上下文切换主要来自共享资源的竞争。一般单个对象加锁很少成为系统瓶颈,除非锁粒度过大。但在一个访问频度高,对多个对象连续加锁的代码块中就可能出现大量上下文切换,成为系统瓶颈。

    比如在我们系统中就曾出现 log4j 1.x 在较大并发下大量打印日志,出现频繁上下文切换,大量线程阻塞,导致系统吞吐量大降的情况,其相关代码如清单 1 所示,升级到 log4j 2.x 才解决这个问题。

    for(Category c = 

    3、Memory

    从操作系统角度,内存关注应用进程是否足够,可以使用 free –m 命令查看内存的使用情况。

    通过 top 命令可以查看进程使用的虚拟内存 VIRT 和物理内存 RES,根据公式 VIRT = SWAP + RES 可以推算出具体应用使用的交换分区(Swap)情况,使用交换分区过大会影响 Java 应用性能,可以将 swappiness 值调到尽可能小。

    因为对于 Java 应用来说,占用太多交换分区可能会影响性能,毕竟磁盘性能比内存慢太多。

    4、I/O

    I/O 包括磁盘 I/O 和网络 I/O,一般情况下磁盘更容易出现 I/O 瓶颈。通过 iostat 可以查看磁盘的读写情况,通过 CPU 的 I/O wait 可以看出磁盘 I/O 是否正常。

    如果磁盘 I/O 一直处于很高的状态,说明磁盘太慢或故障,成为了性能瓶颈,需要进行应用优化或者磁盘更换。

    除了常用的 top、 ps、vmstat、iostat 等命令,还有其他 Linux 工具可以诊断系统问题,如 mpstat、tcpdump、netstat、pidstat、sar 等。Brendan 总结列出了 Linux 不同设备类型的性能诊断工具,如图 4 所示,可供参考。

    图 4.Linux 性能观测工具

    e6afb47d21a2d96b3f9871678a90fd32.png

    5、Java 应用诊断及工具

    应用代码性能问题是相对好解决的一类性能问题。通过一些应用层面监控报警,如果确定有问题的功能和代码,直接通过代码就可以定位;或者通过 top+jstack,找出有问题的线程栈,定位到问题线程的代码上,也可以发现问题。对于更复杂,逻辑更多的代码段,通过 Stopwatch 打印性能日志往往也可以定位大多数应用代码性能问题。

    常用的 Java 应用诊断包括线程、堆栈、GC 等方面的诊断。

    jstack

    jstack 命令通常配合 top 使用,通过 top -H -p pid 定位 Java 进程和线程,再利用 jstack -l pid 导出线程栈。由于线程栈是瞬态的,因此需要多次 dump,一般 3 次 dump,一般每次隔 5s 就行。将 top 定位的 Java 线程 pid 转成 16 进制,得到 Java 线程栈中的 nid,可以找到对应的问题线程栈。

    图 5. 通过 top –H -p 查看运行时间较长 Java 线程

    738518df6e2ccf363e5f14bd6db01202.png

    如图 5 所示,其中的线程 24985 运行时间较长,可能存在问题,转成 16 进制后,通过 Java 线程栈找到对应线程 0x6199 的栈如下,从而定位问题点,如图 6 所示。

    图 6.jstack 查看线程堆栈

    e638c07adc351f5b0742a17ef817b62a.png

    JProfiler

    JProfiler 可对 CPU、堆、内存进行分析,功能强大,如图 7 所示。同时结合压测工具,可以对代码耗时采样统计。

    图 7. 通过 JProfiler 进行内存分析b8701008fdf7b898452d49d83c659134.png

    6、GC 诊断

    Java GC 解决了程序员管理内存的风险,但 GC 引起的应用暂停成了另一个需要解决的问题。JDK 提供了一系列工具来定位 GC 问题,比较常用的有 jstat、jmap,还有第三方工具 MAT 等。

    jstat

    jstat 命令可打印 GC 详细信息,Young GC 和 Full GC 次数,堆信息等。其命令格式为

    jstat –gcxxx -t pid ,如图 8 所示。

    图 8.jstat 命令示例

    5e9b92f87222e89c71286fa3eb66165f.png

    jmap

    jmap 打印 Java 进程堆信息 jmap –heap pid。通过 jmap –dump:file=xxx pid 可 dump 堆到文件,然后通过其它工具进一步分析其堆使用情况

    MAT

    MAT 是 Java 堆的分析利器,提供了直观的诊断报告,内置的 OQL 允许对堆进行类 SQL 查询,功能强大,outgoing reference 和 incoming reference 可以对对象引用追根溯源。

    图 9.MAT 示例

    0809e486858330e509df8cfec96d3555.png

    图 9 是 MAT 使用示例,MAT 有两列显示对象大小,分别是 Shallow size 和 Retained size,前者表示对象本身占用内存的大小,不包含其引用的对象,后者是对象自己及其直接或间接引用的对象的 Shallow size 之和,即该对象被回收后 GC 释放的内存大小,一般说来关注后者大小即可。

    对于有些大堆 (几十 G) 的 Java 应用,需要较大内存才能打开 MAT。

    通常本地开发机内存过小,是无法打开的,建议在线下服务器端安装图形环境和 MAT,远程打开查看。或者执行 mat 命令生成堆索引,拷贝索引到本地,不过这种方式看到的堆信息有限。

    为了诊断 GC 问题,建议在 JVM 参数中加上-XX:+PrintGCDateStamps。常用的 GC 参数如图 10 所示。

    图 10. 常用 GC 参数

    787b8e9ea6709ea7caaaa27a4c8b20a4.png

    对于 Java 应用,通过 top+jstack+jmap+MAT 可以定位大多数应用和内存问题,可谓必备工具。有些时候,Java 应用诊断需要参考 OS 相关信息,可使用一些更全面的诊断工具,比如 Zabbix(整合了 OS 和 JVM 监控)等。在分布式环境中,分布式跟踪系统等基础设施也对应用性能诊断提供了有力支持。

    7、性能优化实践

    在介绍了一些常用的性能诊断工具后,下面将结合我们在 Java 应用调优中的一些实践,从 JVM 层、应用代码层以及数据库层进行案例分享。

    JVM 调优:GC 之痛

    XX商业平台某系统重构时选择 RMI 作为内部远程调用协议,系统上线后开始出现周期性的服务停止响应,暂停时间由数秒到数十秒不等。通过观察 GC 日志,发现服务自启动后每小时会出现一次 Full GC。由于系统堆设置较大,Full GC 一次暂停应用时间会较长,这对线上实时服务影响较大。

    经过分析,在重构前系统没有出现定期 Full GC 的情况,因此怀疑是 RMI 框架层面的问题。通过公开资料,发现 RMI 的 GDC(Distributed Garbage Collection,分布式垃圾收集)会启动守护线程定期执行 Full GC 来回收远程对象,清单 2 中展示了其守护线程代码。

    清单 2.DGC 守护线程源代码
    private 
    位问题后解决起来就比较容易了。一种是通过增加-XX:+DisableExplicitGC 参数,直接禁用系统 GC 的显示调用,但对使用 NIO 的系统,会有堆外内存溢出的风险。
    另一种方式是通过调大 -Dsun.rmi.dgc.server.gcInterval 和-Dsun.rmi.dgc.client.gcInterval 参数,增加 Full GC 间隔,同时增加参数-XX:+ExplicitGCInvokesConcurrent,将一次完全 Stop-The-World 的 Full GC 调整为一次并发 GC 周期,减少应用暂停时间,同时对 NIO 应用也不会造成影响。
    从图 11 可知,调整之后的 Full GC 次数 在 3 月之后明显减少。
    图 11.Full GC 监控统计

    4e04b27ac3c9e28ab7f1b9739ee34b91.png

    GC 调优对高并发大数据量交互的应用还是很有必要的,尤其是默认 JVM 参数通常不满足业务需求,需要进行专门调优。GC 日志的解读有很多公开的资料,本文不再赘述。

    GC 调优目标基本有三个思路:降低 GC 频率,可以通过增大堆空间,减少不必要对象生成;降低 GC 暂停时间,可以通过减少堆空间,使用 CMS GC 算法实现;避免 Full GC,调整 CMS 触发比例,避免 Promotion Failure 和 Concurrent mode failure(老年代分配更多空间,增加 GC 线程数加快回收速度),减少大对象生成等。

    应用层调优:嗅到代码的坏味道

    从应用层代码调优入手,剖析代码效率下降的根源,无疑是提高 Java 应用性能的很好的手段之一。

    某商业广告系统(采用 Nginx 进行负载均衡)某次日常上线后,其中有几台机器负载急剧升高,CPU 使用率迅速打满。我们对线上进行了紧急回滚,并通过 jmap 和 jstack 对其中某台服务器的现场进行保存。

    图 12. 通过 MAT 分析堆栈现场

    84f0ac9ee50c1561a8e7de973d88aae8.png

    堆栈现场如图 12 所示,根据 MAT 对 dump 数据的分析,发现最多的内存对象为 byte[] 和 java.util.HashMap $Entry,且 java.util.HashMap $Entry 对象存在循环引用。初步定位在该 HashMap 的 put 过程中有可能出现了死循环问题(图中 java.util.HashMap $Entry 0x2add6d992cb8 和 0x2add6d992ce8 的 next 引用形成循环)。

    查阅相关文档定位这属于典型的并发使用的场景错误 (http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6423457) ,简要的说就是 HashMap 本身并不具备多线程并发的特性,在多个线程同时 put 操作的情况下,内部数组进行扩容时会导致 HashMap 的内部链表形成环形结构,从而出现死循环。

    针对此次上线,最大的改动在于通过内存缓存网站数据来提升系统性能,同时使用了懒加载机制,如清单 3 所示。

    清单 3. 网站数据懒加载代码
    private 

    可以看到此处的 domainMap 为静态共享资源,它是 HashMap 类型,在多线程情况下会导致其内部链表形成环形结构,出现死循环。

    通过对前端 Nginx 的连接和访问日志可以看到,由于在系统重启后 Nginx 积攒了大量的用户请求,在 Resin 容器启动,大量用户请求涌入应用系统,多个用户同时进行网站数据的请求和初始化工作,导致 HashMap 出现并发问题。在定位故障原因后解决方法则比较简单,主要的解决方法有:

    • (1)采用 ConcurrentHashMap 或者同步块的方式解决上述并发问题;

    • (2)在系统启动前完成网站缓存加载,去除懒加载等;

    • (3)采用分布式缓存替换本地缓存等。

    对于坏代码的定位,除了常规意义上的代码审查外,借助诸如 MAT 之类的工具也可以在一定程度对系统性能瓶颈点进行快速定位。但是一些与特定场景绑定或者业务数据绑定的情况,却需要辅助代码走查、性能检测工具、数据模拟甚至线上引流等方式才能最终确认性能问题的出处。以下是我们总结的一些坏代码可能的一些特征,供大家参考:

    • (1)代码可读性差,无基本编程规范;

    • (2)对象生成过多或生成大对象,内存泄露等;

    • (3)IO 流操作过多,或者忘记关闭;

    • (4)数据库操作过多,事务过长;

    • (5)同步使用的场景错误;

    • (6)循环迭代耗时操作等。

    数据库层调优:死锁噩梦

    对于大部分 Java 应用来说,与数据库进行交互的场景非常普遍,尤其是 OLTP 这种对于数据一致性要求较高的应用,数据库的性能会直接影响到整个应用的性能。搜狗商业平台系统作为广告主的广告发布和投放平台,对其物料的实时性和一致性都有极高的要求,我们在关系型数据库优化方面也积累了一定的经验。

    对于广告物料库来说,较高的操作频繁度(特别是通过批量物料工具操作)很极易造成数据库的死锁情况发生,其中一个比较典型的场景是广告物料调价。客户往往会频繁的对物料的出价进行调整,从而间接给数据库系统造成较大的负载压力,也加剧了死锁发生的可能性。下面以搜狗商业平台某广告系统广告物料调价的案例进行说明。

    某商业广告系统某天访问量突增,造成系统负载升高以及数据库频繁死锁,死锁语句如图 13 所示。

    图 13. 死锁语句

    053c4411a5b150f4fbded27f5960186b.png

    其中,groupdomain 表上索引为 idx_groupdomain_accountid (accountid),idx_groupdomain_groupid(groupid),primary(groupdomainid) 三个单索引结构,采用 Mysql innodb 引擎。

    此场景发生在更新组出价时,场景中存在着组、组行业(groupindus 表)和组网站(groupdomain 表)。

    当更新组出价时,若组行业出价使用组出价(通过 isusegroupprice 标示,若为 1 则使用组出价)。同时若组网站出价使用组行业出价(通过 isuseindusprice 标示,若为 1 则使用组行业出价)时,也需要同时更新其组网站出价。由于每个组下面最大可以有 3000 个网站,因此在更新组出价时会长时间的对相关记录进行锁定。

    从上面发生死锁的问题可以看到,事务 1 和事务 2 均选择了 idx_groupdomain_accountid 的单列索引。根据 Mysql innodb 引擎加锁的特点,在一次事务中只会选择一个索引使用,而且如果一旦使用二级索引进行加锁后,会尝试将主键索引进行加锁。进一步分析可知事务 1 在请求事务 2 持有的`idx_groupdomain_accountid`二级索引加锁(加锁范围“space id 5726 page no 8658 n bits 824 index”),但是事务 2 已获得该二级索引 (“space id 5726 page no 8658 n bits 824 index”) 上所加的锁,在等待请求锁定主键索引 PRIMARY 索引上的锁。由于事务 2 等待执行时间过长或长时间不释放锁,导致事务 1 最终发生回滚。

    通过对当天访问日志跟踪可以看到,当天有客户通过脚本方式发起大量的修改推广组出价的操作,导致有大量事务在循环等待前一个事务释放锁定的主键 PRIMARY 索引。该问题的根源实际上在于 Mysql innodb 引擎对于索引利用有限,在 Oracle 数据库中此问题并不突出。

    解决的方式自然是希望单个事务锁定的记录数越少越好,这样产生死锁的概率也会大大降低。最终使用了(accountid, groupid)的复合索引,缩小了单个事务锁定的记录条数,也实现了不同计划下的推广组数据记录的隔离,从而减少该类死锁的发生几率。

    通常来说,对于数据库层的调优我们基本上会从以下几个方面出发:

    (1)在 SQL 语句层面进行优化:慢 SQL 分析、索引分析和调优、事务拆分等;

    (2)在数据库配置层面进行优化:比如字段设计、调整缓存大小、磁盘 I/O 等数据库参数优化、数据碎片整理等;

    (3)从数据库结构层面进行优化:考虑数据库的垂直拆分和水平拆分等;

    (4)选择合适的数据库引擎或者类型适应不同场景,比如考虑引入 NoSQL 等。

    8、总结与建议

    性能调优同样遵循 2-8 原则,80%的性能问题是由 20%的代码产生的,因此优化关键代码事半功倍。同时,对性能的优化要做到按需优化,过度优化可能引入更多问题。对于 Java 性能优化,不仅要理解系统架构、应用代码,同样需要关注 JVM 层甚至操作系统底层。总结起来主要可以从以下几点进行考虑:

    1)基础性能的调优

    这里的基础性能指的是硬件层级或者操作系统层级的升级优化,比如网络调优,操作系统版本升级,硬件设备优化等。比如 F5 的使用和 SDD 硬盘的引入,包括新版本 Linux 在 NIO 方面的升级,都可以极大的促进应用的性能提升;

    2)数据库性能优化

    包括常见的事务拆分,索引调优,SQL 优化,NoSQL 引入等,比如在事务拆分时引入异步化处理,最终达到一致性等做法的引入,包括在针对具体场景引入的各类 NoSQL 数据库,都可以大大缓解传统数据库在高并发下的不足;

    3)应用架构优化

    引入一些新的计算或者存储框架,利用新特性解决原有集群计算性能瓶颈等;或者引入分布式策略,在计算和存储进行水平化,包括提前计算预处理等,利用典型的空间换时间的做法等;都可以在一定程度上降低系统负载;

    4)业务层面的优化

    技术并不是提升系统性能的唯一手段,在很多出现性能问题的场景中,其实可以看到很大一部分都是因为特殊的业务场景引起的,如果能在业务上进行规避或者调整,其实往往是最有效的。

    欢迎大家添加个人微信号  jiangbingdreamer,加入群聊,一起深入交流~

    免费无套路分享 | 面试&学习福利资源

    最近在网上发现一个不错的 PDF 资源《Java 核心知识&面试.pdf》内容覆盖很广,Java 核心基础、Java 多线程、高并发、Spring、微服务、Netty 与 RPC、Zookeeper、Kafka、RabbitMQ、Habase、设计模式、负载均衡、分布式缓存、Hadoop、Spark、Storm、云计算等

    获取方式: 关注本公众号: 小哈学Java, 后台回复资源,既可免费无套路获取资源链接

    ee815d5ad8a4d056f93391227cda4800.gif

    更多推荐内容

    ↓↓↓

    原创 | Spring Boot 2.x 快速整合消息中间件 Kafka

    Linux 最常用命令:简单易学,但能解决 95% 以上的问题

    给你一份Spring Boot核心知识清单 | 建议收藏

    32个 IDEA 推荐配置,团队开发必备!

    收到面试通知后,如何准备可以大大提升面试成功率?

    如果你喜欢本文

    请长按二维码,关注小哈学Java

    73466b66ff665464a7a79be4a7502027.png

    转发朋友圈,是对我最大的支持哟

    文章有帮助的话,在看,转发吧。

    谢谢支持哟 (*^__^*) 

    展开全文
  • private String[][] HOMEPAGE_MAINMENU = { { "创业指导", "0" ... { "信息服务", "2" }, { "管理咨询", "3" }, { "法律维权", "4" }, { "市场开拓", "5" }, { "融资担保", "6" }, { "技术创新", "7" } }; ...
            private String[][] HOMEPAGE_MAINMENU = { { "创业指导", "0" }, { "人才培养", "1" },
    			{ "信息服务", "2" }, { "管理咨询", "3" }, { "法律维权", "4" }, { "市场开拓", "5" },
    			{ "融资担保", "6" }, { "技术创新", "7" } };
    
            /**
    	 * 加载数据
    	 */
    	private void loadData() {
    		mAdapter = new MainGridViewAdapter(this);
    		List<MainCatalogEntity> dataList = new ArrayList<MainCatalogEntity>();
    		int length = HOMEPAGE_MAINMENU.length;
    		for (int i = 0; i < length; i++) {
    			MainCatalogEntity entity = new MainCatalogEntity();
    			entity.setMenuName(HOMEPAGE_MAINMENU[i][0]);
    			entity.setPicPath(HOMEPAGE_MAINMENU[i][1]);
    			dataList.add(entity);
    		}
    		mAdapter.setData(dataList);
    		maingridview.setAdapter(mAdapter);
    	}
    

      

    转载于:https://www.cnblogs.com/xiaoyao095/p/4432271.html

    展开全文
  • 外包服务Java

    2014-08-05 13:10:53
    外包服务JavaJava被广泛地用于Web开发的应用程序。它提供了有效的可移植性和可扩展性,以满足使用Internet人们日益增长的需求。仅举少数人能玩网络游戏,闲聊与他们的朋友,同事或生意伙伴,计算按揭利息,或看...
    外包服务的Java   的Java被广泛地用于Web开发的应用程序。它提供了有效的可移植性和可扩展性,以满足使用Internet人们日益增长的需求。仅举少数人能玩网络游戏,闲聊与他们的朋友,同事或生意伙伴,计算按揭利息,或看看3维图像。 Java技术已经能够提供:   *多功能*高效*安全和网络*平台的可移植性在发达国家专业费用使得Java应用软件的高额费用。但在发展中国家,如印度的Java服务,供应商可以收费相当少而不包括有关质量。部分原因要提前和外包的java服务厂商合作,包括:   *经济的解决方案?有许多公司用Java开发服务,有竞争力的成本提供。因此,您可以选择适合您的需求以及之一。
       *懂行的人才?知识就是力量。同样的事情也适用于Java开发人员。他们是专家,了解工作的质量和时效性的重要性。因此,你可以完全依赖它们来获得高质量的输出。他们构建,管理和促进客户的业务,让他们可以牟取高额利润。   *战略方针:谁是处理你的工作外包战略,公司致力于降低客户成本,适度的风险,并建议必要的解决方案。   *完整的测试和风险分析:在最终产品和服务的交付,他们完全在功能,性能和完整性进行评估。   为了更多地了解公司提供外包java的服务,请访问:应用开发使用Java java开发印度
    
    展开全文
  • 由于二数组的接收网上资料很少,通过自己的研究发现二数组可以先转换成一数组,然后每个元素再逆向转换成Oracle.ARRAY,再然后按照一数组如法炮制。 --建立一数组 --PS也请使用NVARCHAR2 CREATE OR REPLACE...

    --建立oracle对象

    CREATE OR REPLACE TYPE PERSON AS OBJECT (

    --如果你执意使用VARCHAR2有一定几率出现乱码和ASCII码(貌似和驱动有关)

    --为了避免平台,服务器中间件,驱动等等因素而造成的

    --可能出现乱码(无法识别)和以0X开头的16进制ASCII等情况请使用NVARCHAR2

    P_ID NVARCHAR2(32),

    P_NAME NVARCHAR2(16),

    P_AGE NVARCHAR2(24),

    P_PROJECT NVARCHAR2(32) )

    --建立对象数组

    CREATE OR REPLACE TYPE PERSON_TABLE_TYPE IS TABLE OF PERSON

    --建立测试用存储过程

    --PS:这个过程是在我的一个包(TEST.DEMO)里面的,如果单独写成过程请create or replace

    PROCEDURE GETBEAN_OBJTABLE(V_TABLE OUT PERSON_TABLE_TYPE)

    AS

    BEGIN V_TABLE := PERSON_TABLE_TYPE();

    FOR I IN 1 .. 5 LOOP

    V_TABLE.EXTEND; V_TABLE(I) := PERSON('23231123232'||I,

    '第'||I||'代',

    '20'||I,

    '2010-1-1'||I);

    END LOOP;

    END;

    JAVA端

    //如果你使用JDBC,

    //你可以强转conn为oracleConnection也可以像我一样强转CallableStatement为OracleCallableStatement。

    //但如果你使用诸如tomcat的DBCP等连接池请首先转换为native连接,然后转换为oracle连接,直接强转是无效的!

    //(最后释放关闭的连接是连接池的连接而不是oracle的连接)

    conn = DbHelperImpJdbc.getInstance().getConn();

    cs = (OracleCallableStatement) conn.prepareCall("{call PKG_DEMO.GETBEAN_OBJTABLE(?)}");

    cs.registerOutParameter(1, OracleTypes.ARRAY, "PERSON_TABLE_TYPE".toUpperCase());

    ARRAY obj = (ARRAY) cs.getArray(1);

    Datum[] datas = obj.getOracleArray();//获取对象

    //遍历对象数组

    for(int i=0;i

    System.out.println("对象"+i);

    //获取属性

    Object[] beanAttributes = ((STRUCT) datas[i]).getOracleAttributes();

    //遍历属性

    for(int m=0;m

    System.out.println(" "+beanAttributes[m]);

    }

    }

    打印结果:

    对象0

    232311232321

    第1代

    201

    2010-1-11

    对象1

    232311232322

    第2代

    202

    2010-1-12

    对象2

    232311232323

    第3代

    203

    2010-1-13

    对象3

    232311232324

    第4代

    204

    2010-1-14

    对象4

    232311232325

    第5代

    205

    2010-1-15

    接下来我们来看看怎么从过程中接收二维数组,由于二维数组的接收网上资料很少,通过自己的研究发现二维数组可以先转换成一维数组,然后每个元素再逆向转换成Oracle.ARRAY,再然后按照一维数组如法炮制。

    --建立一维数组

    --PS也请使用NVARCHAR2

    CREATE OR REPLACE TYPE TYPE_VARCHAR IS TABLE OF NVARCHAR2(2000)

    --建立二维数组

    CREATE OR REPLACE TYPE TYPE_VARCHAR_TABLE IS TABLE OF TYPE_VARCHAR

    --建立测试用过程

    PROCEDURE GETBEAN_ARRAYTABLE(V_TABLE OUT TYPE_VARCHAR_TABLE)

    AS

    BEGIN

    V_TABLE:=TYPE_VARCHAR_TABLE();

    FOR I IN 1 .. 5 LOOP

    V_TABLE.EXTEND;

    V_TABLE(I):=NEW TYPE_VARCHAR('23231123232'||I,

    ' 第'||I||'代',

    '20'||I,

    '2010-1-1'||I);

    END LOOP;

    END;

    JAVA端

    conn = DbHelperImpJdbc.getInstance().getConn();

    cs = (OracleCallableStatement) conn.prepareCall("{call PKG_DEMO.GETBEAN_ARRAYTABLE(?)}");

    cs.registerOutParameter(1, OracleTypes.ARRAY, "TYPE_VARCHAR_TABLE".toUpperCase());

    cs.execute();

    ARRAY obj = (ARRAY) cs.getArray(1);

    //获取第一维度

    Object[] firstDimension=(Object[]) obj.getArray();

    for(int i=0;i

    System.out.println("对象"+i);

    //将第一维度元素转成ARRAY之后获取数组再将该数组元素转换成数组,

    //这便是第二维度数组

    Object[] secondDimension=(Object[]) ((ARRAY)firstDimension[i]).getArray();

    for(int m=0;m

    System.out.println(" "+secondDimension[m]);

    }

    }

    打印结果同上。

    总结:使用二维数组比对象数组灵活的多,如果我们要为返回结果集中删减字段,就必须要先去更改oracle的对象,这样很不灵活。而二维数组的可伸缩性就非常好了。

    分享到:

    18e900b8666ce6f233d25ec02f95ee59.png

    72dd548719f0ace4d5f9bca64e1d7715.png

    2012-07-06 11:29

    浏览 4035

    评论

    1 楼

    usherzhao

    2012-07-19

    我先来顶了。以后也许用的到

    展开全文
  • 2.5又称假三,是一种将三模型固定角度后输出的图像...在三技术飞速发展的今天,各种精细的三地图服务纷纷上线,但商业的在线地图还只是提供了主要建筑物的三地图,还远未实现全覆盖,因其数据门槛相对较...
  • JAVA_API1.6文档(中文)

    万次下载 热门讨论 2010-04-12 13:31:34
    java.awt.geom 提供用于在与二几何形状相关的对象上定义和执行操作的 Java 2D 类。 java.awt.im 提供输入方法框架所需的类和接口。 java.awt.im.spi 提供启用可以与 Java 运行时环境一起使用的输入方法开发的...
  • 存储过程越来越多的应用到项目当中了,不罗嗦了先来看看JAVA怎么从oracle接收对象数组。 [code="sql"] --建立oracle对象 CREATE OR REPLACE TYPE PERSON AS OBJECT ( --如果你执意使用VARCHAR2有...
  • java

    2017-12-01 08:25:03
    主要功能模块: ...取数配置模块:宽表分类配置、宽表配置、表分类配置、表配置、固定取数配置   文件管理模块:文件上传管理、文件下载管理、文件导出管理、文件下发管理、网络文件管理
  • 由于我最开始学习的Java,做过电子商务的开发,所以对以Java为语言写服务器代码相对来说更容易一些。但是我最想做的是游戏科普的方向,但又不想放弃之前的学习,我学习了JNI,Android NDK的使用,但是所有的button等...
  • java Graphics2D绘制文字并居中并解决服务器乱码问题

    万次阅读 多人点赞 2017-06-08 10:04:41
    它是用于在 Java(tm) 平台上呈现二形状、文本和图像的基础类。一、在图片上绘制文字实例代码:package com.test.testImage;import java.awt.Color; import java.awt.Font; import java.awt.Font
  •        在SuperMap iServer产品中封装了大部分的GIS功能,比如基本的地图功能、二三...本文将重点介绍使用iserver REST API和SuperMap iObjects for Java(以下简称Java组件)来...
  • 通过Java客户端访问Web时,session信息的保存问题。通过浏览器访问Web,浏览器自动管理Http连接的的session信息,如果通过Java连接,比如HttpURLConnection,就需要...我们希望java客户端能像浏览器一样,每次请求都
  • Java数据库

    2019-10-22 19:32:43
    Java数据库 数据库 的概念 存储数据的仓库,你一台电脑装有数据库软件,你可以对外提供数据的增删改查服务,你这台电脑,就是一台,数据库服务器 常见数据库: SQLServer 微软的 中小型关系型数据库 MySQL 中小型...
  • BeginnersBook Java 示例

    2019-10-12 20:53:46
    来源:ApacheCN BeginnersBook 翻译项目 译者:飞龙 协议:CC BY-NC-SA 4.0 贡献指南 本项目需要校对,欢迎大家提交 Pull Request。 请您勇敢地去翻译和改进翻译。虽然我们追求卓越,但我们并不要求...(改编自...
  • 精通Java JDK

    热门讨论 2009-06-27 20:03:50
    DoubleArray.java数组的使用 ArrayListDemo.java ArrayList的使用 LinkedListDemo.java LinkedList的使用 VectorDemo.java Vector数组的使用 MapDemo.java Map的使用 HashtableDemo.java Hashtable的...
  • ...   ...import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.Pri...
  • Oracle EBS JSP实现QRCode二条码

    千次阅读 2018-06-09 13:24:05
    另外,自己架建Tomcat Web服务是PC机,通过JSP也是可以实现打印二条码,由于PC机不稳定,每隔一段时间PC机会宕机,给我们带比较大的困扰。业务需求为了解XML报表或者Oracle Report Builder打印批量打印二条码,...
  • java api最新7.0

    千次下载 热门讨论 2013-10-26 17:34:06
    java.awt.geom 提供用于在与二几何形状相关的对象上定义和执行操作的 Java 2D 类。 java.awt.im 提供输入方法框架所需的类和接口。 java.awt.im.spi 提供启用可以与 Java 运行时环境一起使用的输入方法开发的接口...
  • java开源包1

    千次下载 热门讨论 2013-06-28 09:14:34
    PortGroper 是一款java写的开源拒绝服务测试工具,它不是僵尸网络类的ddos,而是使用大量的代理作为bots发起DDOS。Port Groper可以与用测试防火墙,干扰web 统计脚本的跟踪,为网站增加流量..往好了用什么都能干,就是...
  • java开源包12

    热门讨论 2013-06-28 10:14:45
    PortGroper 是一款java写的开源拒绝服务测试工具,它不是僵尸网络类的ddos,而是使用大量的代理作为bots发起DDOS。Port Groper可以与用测试防火墙,干扰web 统计脚本的跟踪,为网站增加流量..往好了用什么都能干,就是...
  • java微服务

    2020-06-19 08:28:07
    微服务是强调小型短暂组件的SOA。 整体性架构的局限性: ...扩展式一的。而微服务只对需要扩展的服务进行扩展,允许对资源的最优利用。 微服务开发使用REST式的WEB服务开发。服务器端无状态、水平扩展。
  • Java资源包01

    2016-08-31 09:16:25
    PortGroper 是一款java写的开源拒绝服务测试工具,它不是僵尸网络类的ddos,而是使用大量的代理作为bots发起DDOS。Port Groper可以与用测试防火墙,干扰web 统计脚本的跟踪,为网站增加流量..往好了用什么都能干,就是...
  • 存档日期:2019年5月13日 | 首次发布:2010年4月20日 ... 在本文中,IBM Java技术中心Java服务策略的架构师Chris Bailey从Oracle规范和IBM提供的增值两方面介绍了商店中的一些更改。 此内容不再被更新或...
  • java开源包101

    2016-07-13 10:11:08
    PortGroper 是一款java写的开源拒绝服务测试工具,它不是僵尸网络类的ddos,而是使用大量的代理作为bots发起DDOS。Port Groper可以与用测试防火墙,干扰web 统计脚本的跟踪,为网站增加流量..往好了用什么都能干,就是...
  • java开源包11

    热门讨论 2013-06-28 10:10:38
    PortGroper 是一款java写的开源拒绝服务测试工具,它不是僵尸网络类的ddos,而是使用大量的代理作为bots发起DDOS。Port Groper可以与用测试防火墙,干扰web 统计脚本的跟踪,为网站增加流量..往好了用什么都能干,就是...
  • java开源包6

    热门讨论 2013-06-28 09:48:32
    PortGroper 是一款java写的开源拒绝服务测试工具,它不是僵尸网络类的ddos,而是使用大量的代理作为bots发起DDOS。Port Groper可以与用测试防火墙,干扰web 统计脚本的跟踪,为网站增加流量..往好了用什么都能干,就是...
  • java开源包10

    热门讨论 2013-06-28 10:06:40
    PortGroper 是一款java写的开源拒绝服务测试工具,它不是僵尸网络类的ddos,而是使用大量的代理作为bots发起DDOS。Port Groper可以与用测试防火墙,干扰web 统计脚本的跟踪,为网站增加流量..往好了用什么都能干,就是...
  • java开源包8

    热门讨论 2013-06-28 09:55:26
    PortGroper 是一款java写的开源拒绝服务测试工具,它不是僵尸网络类的ddos,而是使用大量的代理作为bots发起DDOS。Port Groper可以与用测试防火墙,干扰web 统计脚本的跟踪,为网站增加流量..往好了用什么都能干,就是...
  • BeginnersBook Java 集合教程

    千次阅读 2019-10-10 20:07:48
    来源:ApacheCN BeginnersBook 翻译项目 译者:飞龙 协议:CC BY-NC-SA 4.0 贡献指南 本项目需要校对,欢迎大家提交 Pull Request。 请您勇敢地去翻译和改进翻译。虽然我们追求卓越,但我们并不要求...(改编自...

空空如也

空空如也

1 2 3 4 5 ... 10
收藏数 183
精华内容 73
关键字:

java维服务

java 订阅