JasperReport与JPA结合设计报表

最近思考采用JasperReport设计报表,用JPA技术填充报表后存放在服务端会话中(session),采用jasperReport XMLServlet分页返回XML给flex客户端。结合jasperReport flash viewer组件在客户端预览和打印报表。

前一博文中的案例是采用JDBC返回数据集给JasperReport,今天看到JasperReport的数据源可以是JavaBean Collection。于是想采用DAO返回数据集后给JRBeanDataSource,加上JPA的延迟加载技术就可以呈现报表。

一、JPA模型如下:

 

org.im.scm.domain.Material.java
  1. package org.im.scm.domain;  
  2.   
  3. import …  
  4.   
  5.   
  6. /** 
  7.  * Material entity. 
  8.  *  
  9.  * @author MyEclipse Persistence Tools 
  10.  */  
  11. //@Proxy(lazy = false)  
  12. @Entity  
  13. @Table(name = "Material", schema = "dbo", catalog = "imc_manager")  
  14. public class Material implements java.io.Serializable {  
  15.   
  16.     // Fields  
  17.   
  18.     private Integer autoid;  
  19.     private MaterialType materialType;  
  20.   
  21.     // Constructors  
  22.   
  23.     /** default constructor */  
  24.     public Material() {  
  25.     }  
  26.   
  27.     /** minimal constructor */  
  28.     public Material(Integer autoid) {  
  29.         this.autoid = autoid;  
  30.     }  
  31.   
  32.     /** full constructor */  
  33.     public Material(Integer autoid, MaterialType materialType) {  
  34.         this.autoid = autoid;  
  35.         this.materialType = materialType;  
  36.     }  
  37.   
  38.     // Property accessors  
  39.     @Id  
  40.     @Column(name = "autoid", unique = true, nullable = false)  
  41.     @GeneratedValue(strategy=GenerationType.IDENTITY)  
  42.     public Integer getAutoid() {  
  43.         return this.autoid;  
  44.     }  
  45.   
  46.     public void setAutoid(Integer autoid) {  
  47.         this.autoid = autoid;  
  48.     }  
  49.       
  50.     @ManyToOne(fetch=FetchType.LAZY)  
  51.     @JoinColumn(name = "materialTypeId")  
  52.     public MaterialType getMaterialType() {  
  53.         return this.materialType;  
  54.     }  
  55.   
  56.     public void setMaterialType(MaterialType materialType) {  
  57.         this.materialType = materialType;  
  58.     }  
  59.   
  60. }  

 

Java代码:org.im.scm.domain.MaterialType
  1. package org.im.scm.domain;  
  2.   
  3. import …  
  4.   
  5. /** 
  6.  * MaterialType entity. 
  7.  *  
  8.  * @author MyEclipse Persistence Tools 
  9.  */  
  10. @Entity  
  11. @Table(name = "materialType", schema = "dbo", catalog = "imc_manager")  
  12. public class MaterialType implements java.io.Serializable {  
  13.   
  14.     // Fields  
  15.   
  16.     private Integer autoId;  
  17.     private String name;  
  18.     private String type;  
  19.     private Set<Material> materials = new HashSet<Material>(0);  
  20.   
  21.     // Constructors  
  22.   
  23.     /** default constructor */  
  24.     public MaterialType() {  
  25.     }  
  26.   
  27.     /** minimal constructor */  
  28.     public MaterialType(Integer autoId, String type) {  
  29.         this.autoId = autoId;  
  30.         this.type = type;  
  31.     }  
  32.   
  33.     /** full constructor */  
  34.     public MaterialType(Integer autoId, String name, String type,  
  35.             Set<Material> materials) {  
  36.         this.autoId = autoId;  
  37.         this.name = name;  
  38.         this.type = type;  
  39.         this.materials = materials;  
  40.     }  
  41.   
  42.     // Property accessors  
  43.     @Id  
  44.     @Column(name = "autoId", unique = true, nullable = false)  
  45.     @GeneratedValue(strategy=GenerationType.IDENTITY)  
  46.     public Integer getAutoId() {  
  47.         return this.autoId;  
  48.     }  
  49.   
  50.     public void setAutoId(Integer autoId) {  
  51.         this.autoId = autoId;  
  52.     }  
  53.   
  54.     @Column(name = "name", length = 40)  
  55.     public String getName() {  
  56.         return this.name;  
  57.     }  
  58.   
  59.     public void setName(String name) {  
  60.         this.name = name;  
  61.     }  
  62.   
  63.     @Column(name = "type", nullable = false, length = 2)  
  64.     public String getType() {  
  65.         return this.type;  
  66.     }  
  67.   
  68.     public void setType(String type) {  
  69.         this.type = type;  
  70.     }  
  71.   
  72.     @OneToMany(cascade = CascadeType.ALL, mappedBy = "materialType", fetch = FetchType.LAZY)  
  73.     @OrderBy  
  74.     public Set<Material> getMaterials() {  
  75.         return this.materials;  
  76.     }  
  77.   
  78.     public void setMaterials(Set<Material> materials) {  
  79.         this.materials = materials;  
  80.     }  
  81.   
  82. }  

二、在应用服务中调用org.im.scm.domain.MaterialDAO.findAll();

 

Java代码
  1. private JRDataSource getJRDataSource(){  
  2.         JRBeanCollectionDataSource s= new JRBeanCollectionDataSource(materialDao.findAll());   
  3.         return s;  
  4.     }  

三、报表设置如下图:

建立字段autoId 类型为java.lang.Integer,字段materialType 类型为org.im.scm.domain.MaterialType;

在report属性"import"中导入"org.im.scm.domain.*",不然在服务中无法编译为Jasper文件,系统也不会提示出错,这个我也搞不明白。

四、服务器运行结果如下

 

完成Flex报表设计、生成、打印功能(二)

继上一节,讲解JRFV,打开jasperreports-flash-3.0.0-project.zip文件,在程序包中Viewer.mxml中有这么一段:

 

JavaScript代码
  1. <mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"   
  2.     paddingLeft="0" paddingTop="0" paddingBottom="0" paddingRight="0"   
  3.     verticalScrollPolicy="auto" horizontalScrollPolicy="auto"  
  4.     creationComplete="init()"  
  5.     resize="refreshPage()" horizontalAlign="center" height="100%" width="100%" verticalGap="0">  
  6.   
  7.     <mx:ControlBar id="toolbar" width="100%">  
  8. <!–  
  9. //这个是作者注销并未实现的部分  
  10.         <mx:Button width="22" toolTip="Print Report" id="btnPrintReport0" buttonMode="true"  
  11.             enabled="false">  
  12.             <mx:icon>@Embed(source=‘images/print.GIF’)</mx:icon>  
  13.         </mx:Button>  
  14.           
  15.         <mx:Button width="22" toolTip="Print Report" id="btnReload" buttonMode="true"  
  16.             enabled="true" click="btnReloadClick()">  
  17.             <mx:icon>@Embed(source=‘images/reload.GIF’)</mx:icon>  
  18.         </mx:Button>  
  19.         –>  

我取消注释后,在btnPrintReport0按钮中增加click事件的实现如下:

 

JavaScript代码
  1. <mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"   
  2.     paddingLeft="0" paddingTop="0" paddingBottom="0" paddingRight="0"   
  3.     verticalScrollPolicy="auto" horizontalScrollPolicy="auto"  
  4.     creationComplete="init()"  
  5.     resize="refreshPage()" horizontalAlign="center" height="100%" width="100%" verticalGap="0">  
  6.     <mx:ControlBar id="toolbar" width="100%">  
  7.         <mx:Button width="22" toolTip="Print Report" id="btnPrintReport0" buttonMode="true"  
  8.             enabled="false" click="PrintManager.printAll(jrpxmlUrl);">  
  9.             <mx:icon>@Embed(source=‘images/print.GIF’)</mx:icon>  
  10.         </mx:Button>  
  11.         <!–  
  12.         <mx:Button width="22" toolTip="Print Report" id="btnReload" buttonMode="true"  
  13.             enabled="true" click="btnReloadClick()">  
  14.             <mx:icon>@Embed(source=‘images/reload.GIF’)</mx:icon>  
  15.         </mx:Button>  
  16.         –>  

这时还不好使用,因为enabled=false,在refreshPage()方法中增加一行:

 

JavaScript代码
  1. private function refreshPage():void   
  2.             {  
  3.                 if (pageBox)  
  4.                 {  
  5.                     switch (fitMode)  
  6.                     {  
  7.                         case FIT_ACTUAL_PAGE_SIZE:  
  8.                             zoomRatio = 1;  
  9.                             break;  
  10.                         case FIT_PAGE:  
  11.                             zoomRatio = (height - toolbar.height - mainBox.getStyle("paddingTop") - mainBox.getStyle("paddingBottom")) / _pageHeight;  
  12.                             break;  
  13.                         case FIT_WIDTH:  
  14.                             zoomRatio = (width - mainBox.getStyle("paddingLeft") - mainBox.getStyle("paddingRight")) / _pageWidth;  
  15.                             break;  
  16.                     }  
  17.       
  18.                     pageBox.width = zoomRatio * _pageWidth;  
  19.                     pageBox.height = zoomRatio * _pageHeight;  
  20.                       
  21.                     if (pageCount > 0)  
  22.                     {  
  23.                         var pageCanvas:PageCanvas = new PageCanvas(xml);  
  24.                         pageCanvas.scaleX = zoomRatio;  
  25.                         pageCanvas.scaleY = zoomRatio;  
  26.       
  27.                         pageBox.visible = false;  
  28.                         pageBox.removeAllChildren();  
  29.                         pageBox.addChild(pageCanvas);  
  30.                         pageBox.visible = true;  
  31.                     }  
  32.                       
  33.                     btnFirstPage.enabled = (pageIndex > 0);  
  34.                     btnPreviousPage.enabled = (pageIndex > 0);  
  35.                     btnNextPage.enabled = (pageIndex < pageCount - 1);  
  36.                     btnLastPage.enabled = (pageIndex < pageCount - 1);  
  37.                       
  38.                     btnZoomIn.enabled = (zoomRatio <= 8);  
  39.                     btnZoomOut.enabled = (zoomRatio >= 0.25);  
  40.                       
  41.      //当加载的页面中返回的服务器中报表产生的总页数大于0时可用                  
  42.                     btnPrintReport0.enabled = pageCount>0;  
  43.                 }  
  44.             }  

这样就完成了jasperReport-flash viewer插件的批量打印功能。

下面图是测试结果。

有些遗憾的是当报表中含有图片时,预览中没有问题,但是打印时图片不显示。

下载SWC点击下载此文件

完成Flex报表设计、生成、打印功能(一)

flex开发的WEB应用无法生成、预览报表将成为历史,前几天在网上找到jasperReport 3.0 falsh Viewer,下载demo中包括源代码,便将jasperReport flash viewer做成了插件。

但是jasperReport flash viewer(简称:JRFV)并没有带打印功能,于是今天增加了该项功能,支持当前页打印和全部打印。

因为JRFV是通过Flash脚本按照服务器生成的XML在本地重绘,加载时只是一页一页的加载。

下面是主要的加载代码:

 

JavaScript代码
  1. private function loadPage():void  
  2.             {  
  3.                 urlLoader=new URLLoader();  
  4.                 urlLoader.addEventListener(Event.COMPLETE, completeHandler);  
  5.                 urlLoader.addEventListener(Event.OPEN, openHandler);  
  6.                 urlLoader.addEventListener(ProgressEvent.PROGRESS, progressHandler);  
  7.                 urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);  
  8.                 urlLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);  
  9.                 urlLoader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);  
  10.                 //此处只加载一页
  11.                 urlLoader.load(new URLRequest(jrpxmlUrl + "&page=" + _pageIndex));  
  12.             }  
  13.   
  14.             private function completeHandler(event:Event):void  
  15.             {  
  16.                 xml=XML(urlLoader.data);  
  17.   
  18.                 _pageWidth=int(xml.@pageWidth);  
  19.                 _pageHeight=int(xml.@pageHeight);  
  20.   
  21.                 _pageCount=0;  
  22.                 var props:XMLList=xml.property;  
  23.                 for each (var prop:XML in props)  
  24.                 {  
  25.                     if (prop.@name == "net.sf.jasperreports.export.xml.page.count")  
  26.                     {  
  27.                         _pageCount=int(prop.@value);  
  28.                     }  
  29.                 }  
  30.   
  31.                 refreshPage();  
  32.             }  
  33. private function refreshPage():void  
  34.             {  
  35.                 if (pageBox)  
  36.                 {  
  37.                     switch (fitMode)  
  38.                     {  
  39.                         case FIT_ACTUAL_PAGE_SIZE:  
  40.                             zoomRatio=1;  
  41.                             break;  
  42.                         case FIT_PAGE:  
  43.                             zoomRatio=(height - toolbar.height - mainBox.getStyle("paddingTop") - mainBox.getStyle("paddingBottom")) / _pageHeight;  
  44.                             break;  
  45.                         case FIT_WIDTH:  
  46.                             zoomRatio=(width - mainBox.getStyle("paddingLeft") - mainBox.getStyle("paddingRight")) / _pageWidth;  
  47.                             break;  
  48.                     }  
  49.   
  50.                     pageBox.width=zoomRatio * _pageWidth;  
  51.                     pageBox.height=zoomRatio * _pageHeight;  
  52.   
  53.                     if (_pageCount > 0)  
  54.                     {  
  55.                         var pageCanvas:PageCanvas=new PageCanvas(xml);  
  56.                         pageCanvas.scaleX=zoomRatio;  
  57.                         pageCanvas.scaleY=zoomRatio;  
  58.   
  59.                         pageBox.visible=false;  
  60.                         pageBox.removeAllChildren();  
  61.                         pageBox.addChild(pageCanvas);  
  62.                         pageBox.visible=true;  
  63.                         currentPage=pageCanvas;  
  64.                     }  
  65.                     else  
  66.                     {  
  67.                         currentPage=null;  
  68.                     }  
  69.   
  70.                     btnFirstPage.enabled=(_pageIndex > 0);  
  71.                     btnPreviousPage.enabled=(_pageIndex > 0);  
  72.                     btnNextPage.enabled=(_pageIndex < _pageCount - 1);  
  73.                     btnLastPage.enabled=(_pageIndex < _pageCount - 1);  
  74.   
  75.                     btnZoomIn.enabled=(zoomRatio <= 8);  
  76.                     btnZoomOut.enabled=(zoomRatio >= 0.25);  
  77.   
  78.                     btnPrintReport0.enabled=currentPage != null;  
  79.                 }  
  80.             }  

创建新的类(PrintManager.as)如下:

 

JavaScript代码
  1. package net.sf.jasperreports.flex.view  
  2. {  
  3.     import flash.events.Event;  
  4.     import flash.events.EventDispatcher;  
  5.     import flash.events.HTTPStatusEvent;  
  6.     import flash.events.IOErrorEvent;  
  7.     import flash.events.ProgressEvent;  
  8.     import flash.events.SecurityErrorEvent;  
  9.     import flash.net.URLLoader;  
  10.     import flash.net.URLRequest;  
  11.       
  12.     import mx.containers.VBox;  
  13.     import mx.core.Application;  
  14.     import mx.core.UIComponent;  
  15.     import mx.printing.flexPrintJob;  
  16.   
  17.     [Event(name="loadPage",type="flash.events.Event")]  
  18.     [Event(name="allPageLoader",type="flash.events.Event")]  
  19.       
  20.     public class PrintManager extends EventDispatcher  
  21.     {  
  22.         private var _url:String;  
  23.         private var urlLoader:URLLoader;  
  24.         private var xml:XML;  
  25.         private var _pageIndex:int=0;  
  26.         private var _pageWidth:int;  
  27.         private var _pageHeight:int;  
  28.         private var _pageCount:int;  
  29.         private var _pages:Array=new Array();  
  30.   
  31.   
  32.         public const LOAD_PAGE:String="loadPage";  
  33.         public const ALL_PAGE:String="allPageLoader";  
  34.   
  35.         public function get url():String  
  36.         {  
  37.             return _url;  
  38.         }  
  39.   
  40.         public function set url(value:String):void  
  41.         {  
  42.             _url=value;  
  43.         }  
  44.           
  45.         public static function printAll(url:String):void  
  46.         {  
  47.             var pm:PrintManager = new PrintManager();  
  48.             pm.url = url;  
  49.             pm.loadAll();  
  50.         }  
  51.   
  52.         private function onLoadPage(e:Event):void  
  53.         {  
  54.             _pageIndex++;  
  55.             if (_pageIndex < _pageCount)  
  56.                 loadPage()  
  57.             else{  
  58.                 removeEventListener(LOAD_PAGE, onLoadPage);  
  59.                 dispatchEvent(new Event(ALL_PAGE));  
  60.             }  
  61.         }  
  62.           
  63.         private function processPage(page:PageCanvas):UIComponent  
  64.         {  
  65.                 var source:VBox=new VBox();  
  66.                 source.horizontalScrollPolicy="off";  
  67.                 source.verticalScrollPolicy="off";  
  68.                 source.width=_pageWidth;  
  69.                 source.height=_pageHeight;  
  70.                 source.setStyle("backgroundColor""#FFFFFF");  
  71.                 source.addChild(page);  
  72.                     //printJob.addObject(source, FlexPrintJobScaleType.NONE);  
  73.                 return source;  
  74.         }  
  75.           
  76.         private function onAllPageLoaded(event:Event):void  
  77.         {  
  78.             var job:FlexPrintJob = new FlexPrintJob();  
  79.             job.printAsBitmap = false;  
  80.             if(job.start()){  
  81.                 for(var i:int=0;i< _pages.length;i++){  
  82.                     var p1:UIComponent = processPage(PageCanvas(_pages[i]));  
  83.                     Application.application.addChild(p1);  
  84.                     job.addObject(p1);  
  85.                     Application.application.removeChild(p1);  
  86.                 }  
  87.                 job.send();  
  88.             }  
  89.             removeEventListener(ALL_PAGE,onAllPageLoaded);  
  90.         }  
  91.   
  92.         private function loadAll():void  
  93.         {  
  94.             _pageIndex=0;  
  95.             _pages=new Array();  
  96.             this.addEventListener(LOAD_PAGE, onLoadPage);  
  97.             this.addEventListener(ALL_PAGE,onAllPageLoaded);  
  98.             loadPage();  
  99.         }  
  100.   
  101.         private function loadPage():void  
  102.         {  
  103.             urlLoader=new URLLoader();  
  104.             urlLoader.addEventListener(Event.COMPLETE, completeHandler);  
  105.             urlLoader.addEventListener(Event.OPEN, openHandler);  
  106.             urlLoader.addEventListener(ProgressEvent.PROGRESS, progressHandler);  
  107.             urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);  
  108.             urlLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);  
  109.             urlLoader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);  
  110.             urlLoader.load(new URLRequest(_url + "&page=" + _pageIndex));  
  111.         }  
  112.   
  113.         private function completeHandler(event:Event):void  
  114.         {  
  115.             xml=XML(urlLoader.data);  
  116.   
  117.             _pageWidth=int(xml.@pageWidth);  
  118.             _pageHeight=int(xml.@pageHeight);  
  119.   
  120.             _pageCount=0;  
  121.             var props:XMLList=xml.property;  
  122.             for each (var prop:XML in props)  
  123.             {  
  124.                 if (prop.@name == "net.sf.jasperreports.export.xml.page.count")  
  125.                 {  
  126.                     _pageCount=int(prop.@value);  
  127.                 }  
  128.             }  
  129.   
  130.             refreshPage();  
  131.         }  
  132.   
  133.         private function refreshPage():void  
  134.         {  
  135.   
  136.             if (_pageCount > 0)  
  137.             {  
  138.                 //var pageCanvas:PageCanvas=new PageCanvas(xml);  
  139.                 _pages.push(new PageCanvas(new XML(xml)));  
  140.                 this.dispatchEvent(new Event(this.LOAD_PAGE));  
  141.                     //pageBox.addChild(pageCanvas);  
  142.             }  
  143.         }  
  144.   
  145.         private function openHandler(event:Event):void  
  146.         {  
  147.             trace("openHandler: " + event);  
  148.         }  
  149.   
  150.         private function progressHandler(event:ProgressEvent):void  
  151.         {  
  152.             trace("progressHandler loaded:" + event.bytesLoaded + " total: " + event.bytesTotal);  
  153.         }  
  154.   
  155.         private function securityErrorHandler(event:SecurityErrorEvent):void  
  156.         {  
  157.             trace("securityErrorHandler: " + event);  
  158.         }  
  159.   
  160.         private function httpStatusHandler(event:HTTPStatusEvent):void  
  161.         {  
  162.             trace("httpStatusHandler: " + event);  
  163.         }  
  164.   
  165.         private function ioErrorHandler(event:IOErrorEvent):void  
  166.         {  
  167.             trace("ioErrorHandler: " + event);  
  168.         }  
  169.     }  
  170. }  

详解待继

Granite Data Service 延时加载的问题

在创建大的工程项目时,从granite builder产生很多domain的as类,如果有些类在单个XMLApplication 项目中没有明确引用,会产生如下问题

ArgumentError: Error #2173: 无法读取流中的对象。类 org.granite.messaging.persistence.ExternalizablePersistentSet 虽未实现 flash.utils.IExternalizable,但由其别名可得知它为 externalizable 类。
    at ObjectInput/readObject()
    at org.im.scm.domain::MaterialCatalogBase/readExternal()[E:\workspace\scmSystem\as3\org\im\scm\domain\MaterialCatalogBase.as:154]
    at ObjectInput/readObject()
    at mx.collections::ArrayList/readExternal()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\collections\ArrayList.as:443]
    at mx.collections::ArrayCollection/readExternal()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\collections\ArrayCollection.as:132]
 

 

[RPC Fault faultString="Didn't receive an acknowledge message" faultCode="Server.Acknowledge.Failed" faultDetail="Was expecting mx.messaging.messages.AcknowledgeMessage, but received null"]

经过测试有两种办法解决:

1、将所有的granite builder产生的as代码包含在一个SWC中,xmlApplication项目中明确包含编译产生的SWC文件的所有类,会产生编译后SWF变大

2、在编译命令中加入如下参数:

 -include-libraries  "E:/applications/flex Framworks/libs/graniteds2.0GA/granite-essentials.swc"

也可以解决如上问题。

 

同时要注意WEB-INF/web.xml的配置:

 

XML/HTML代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">  
  5.     <description>  
  6.         my first Granite Data Service and Spring framework  
  7.     </description>  
  8.     <display-name>GraniteDS Spring</display-name>  
  9.     <context-param>  
  10.         <description>Path to spring config</description>  
  11.         <param-name>contextConfigLocation</param-name>  
  12.         <param-value>  
  13.             /WEB-INF/classes/applicationContext.xml  
  14.         </param-value>  
  15.     </context-param>  
  16.     <!– uncomment this block –>  
  17.     <context-param>  
  18.         <param-name>servicesConfigPath</param-name>  
  19.         <param-value>/WEB-INF/flex/services-config.xml</param-value>  
  20.     </context-param>  
  21.     <context-param>  
  22.         <param-name>graniteConfigPath</param-name>  
  23.         <param-value>/WEB-INF/granite/granite-config.xml</param-value>  
  24.     </context-param>  
  25.   
  26.     <!– JPA hibernate session filter 这个地方是解决服务端的延时加载报错–>  
  27.     <filter>  
  28.         <filter-name>SpringOpenEntityManagerInViewFilter</filter-name>  
  29.         <filter-class>  
  30.             org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter  
  31.         </filter-class>  
  32.     </filter>  
  33.       
  34.     <filter-mapping>  
  35.         <filter-name>SpringOpenEntityManagerInViewFilter</filter-name>  
  36.         <url-pattern>/*</url-pattern>  
  37.     </filter-mapping>  
  38.   
  39.     <!– Granite Data Service AMF Message Filter –>  
  40.     <filter>  
  41.         <filter-name>AMFMessageFilter</filter-name>  
  42.         <filter-class>  
  43.             org.granite.messaging.webapp.AMFMessageFilter  
  44.         </filter-class>  
  45.     </filter>  
  46.     <filter-mapping>  
  47.         <filter-name>AMFMessageFilter</filter-name>  
  48.         <url-pattern>/graniteamf/*</url-pattern>  
  49.     </filter-mapping>  
  50.     <listener>  
  51.         <listener-class>  
  52.             org.springframework.web.context.ContextLoaderListener  
  53.         </listener-class>  
  54.     </listener>  
  55.     <listener>  
  56.         <listener-class>  
  57.             org.springframework.web.context.request.RequestContextListener  
  58.         </listener-class>  
  59.     </listener>  
  60.     <listener>  
  61.         <listener-class>  
  62.             org.granite.config.GraniteConfigListener  
  63.         </listener-class>  
  64.     </listener>  
  65.     <servlet>  
  66.         <servlet-name>AMFMessageServlet</servlet-name>  
  67.         <servlet-class>  
  68.             org.granite.messaging.webapp.AMFMessageServlet  
  69.         </servlet-class>  
  70.         <load-on-startup>1</load-on-startup>  
  71.     </servlet>  
  72.     <servlet-mapping>  
  73.         <servlet-name>AMFMessageServlet</servlet-name>  
  74.         <url-pattern>/graniteamf/*</url-pattern>  
  75.     </servlet-mapping>  
  76.     <welcome-file-list>  
  77.         <welcome-file>index.jsp</welcome-file>  
  78.     </welcome-file-list>  
  79.     <login-config>  
  80.         <auth-method>BASIC</auth-method>  
  81.     </login-config>  
  82. </web-app>  

 特别要注意这一段代码:

 

web.xml配置片段
  1. <!– JPA hibernate session filter –>  
  2. <filter>  
  3.     <filter-name>SpringOpenEntityManagerInViewFilter</filter-name>  
  4.     <filter-class>  
  5.         org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter  
  6.     </filter-class>  
  7. </filter>  
  8.   
  9. <filter-mapping>  
  10.     <filter-name>SpringOpenEntityManagerInViewFilter</filter-name>  
  11.     <url-pattern>/*</url-pattern>  
  12. </filter-mapping>  

 

外高桥的CIMS项目实施

           在“总体规划、分步实施、效益驱动、稳妥推进”的实施原则下,上海外高桥造船有限公司一方面建立完善系统实施环境和基础数据,解决共享数据库和软件接口关 键技术,另一方面联合国内管理专家、造船专家,走引进和自主开发相结合的道路,努力使信息化投入迅速发挥最大效能。我们主要做法有:
建立有效的项目管理体系
为 了更好地指导开展实施工作,公司成立了由分管领导、专家和项目经理组成的推进组,由部门实施领导、项目骨干和专家组成的专业项目组。创造条件,使核心业务 人员及早进入角色,在CIMS工程中起主导作用。积极组织开展对外合作工作,每周召开协调会,及时解决过程中的存在问题。

坚持以产品为对象推进信息化
通过载体船H1021船实际试用,以达到“打通流程,校正数据,检验系统,掌握方法”目的。
打通业务流程:系统能否按照设计、生产、物资一体化原则运行。
掌握规则方法:按系统要求准备所需编码标准、设计规则、运行规则
校正数据标准:及时消除软件、数据或标准方面可能存在的问题。
验证系统性能:验证集成性、适用性、可靠性、操作性。
通过试点积累实施经验
按照H1021生产顺序,重点在制造部推行班组固化、H1021实施工作,以便为全面推行CIMS应用总结经验。目前,随着H1021生产进行,涂装、模块、搭载、总装等培训和实施工作也在陆续展开。
针 对系统运行基础条件要求高,设计、任务包不全,难以通过系统反馈工时的情况,我们自行开发了工时统计反馈软件,已经在制造部投入使用。由于具备了考勤、焊 材消耗对照功能,在OA网上直接可以进行组合查询,弥补了派工单的缺陷,为班组固化和工时实绩反馈创造了条件,受到了车间的欢迎。
因地制宜,开展物资模块实施工作
完成了管附件范围确定、编码完善、输入系统等工作,并总结出了具体操作办法和规程,正在向其他种类物资推广。
CIMS要求按托盘清单组织采购,并且按照班组申请,实行托盘配送。这需要集配场地、专用托盘架和设施。通过3个多月的调查,目前已形成了场地、设备和费用方案,为下阶段实行托盘管理创造条件。
基础数据标准由编码建立,开始转向完善提高
因 为初始积累少、关键数据不完整等原因,实施CIMS前期的数据准备难度大,审核校验也比较困难。我们专门成立了攻关小组,通过近8个月努力,已完成的基础 数据有:基础数据200余类,其中基础标准110类,设计、物资、生产、品质等方面编码约70类。已经完成标准物资编码13719项,非标准物资编码 1735种。
已完成H1021工程数据项目:设计建模——CAD部件库6千余条,船体图约2000份,舾装图约1000份;物资编码7910项, 托盘PML数量数据776项;累计发布托盘采购指令设计POR399个,非托盘采购指令POR 259个;已完成任务包WP2077个,派工单WO 5400个。
优化业务流程,促进管理规范化
目前,公司一级主要的目标业务流程已明确,并确定了组织结构调整目标。我们现在正在组织各专业部门领导和骨干克服缺乏系统资料与具体咨询指导的困难,以我为主,自行修改完善部门和室的二级、三级业务流程、岗位职责和作业标准等资料,逐步实现“岗位明确、描述细化”的目标。
十几项与CIMS相关的业务管理规定正在修改会审,试点编制的作业标准初稿正在修改会审,其中制造部门作业标准已经修改到第五稿,准备组织试行。
CIMS项目实施已有十个月,外高桥造船公司克服了基础差、资料数据和配套业务模式不全等困难,以我为主,做了许多艰苦细致的实施工作,建立了相关基础数据标准,初步形成了CIMS运行的环境。目前,部分模块已开始投入试运行。
我 们十分清楚地认识到,实施CIMS是一个长期艰苦的过程。要在造船业务上全面应用CIMS,使实际业务模式和管理方式真正在系统上进行,从而将现行造船模 式转换至现代造船模式,还需要做更加艰苦扎实的工作。面对目前实际环境和条件,我们必须树立“立足自我”的思想,以CIMS实施为契机,加快转变管理机制 和业务模式,努力建立务实配套的企业文化,加快整合资源,提升人员素质,切实提高设计水平和业务水平,持续完善数据资料,优化完善软件系统。尽快实现“精 益生产、精细管理”的目标,从而使公司综合竞争能力再上一个台阶。

中国海运江苏基地新造船舶命名下水

9月20日,中国海运在江都举办江苏造船基地新造船舶命名下水仪式,新建成的2号船坞、900吨龙门吊也同时投产。副省长史和平出席仪式并讲话,与中海集团总裁李绍德、宝钢集团董事长徐乐江等共同开启按钮启动船坞大门。

   中国海运是我省的重要战略合作伙伴。中国海运江苏造船基地于2007年4月28日开工奠基。9月20日下水的3条新造船舶都是57300吨的散货船,被 分别命名为“安强山”轮、“银致”轮和“新世纪128”轮。预计到2011年,中国海运江苏造船基地将全面建成达产,形成年造船400万载重吨、年销售 200亿元的规模,成为国内最大的单体造船基地。

  史和平在讲话中说,当前,江苏正处在新一轮加快发展的关键时期,特别是江苏沿海开发上升为国家战略,为江苏经济发展和船舶工业升级带来了千载难逢的历史机遇。希望中国海运江苏造船基地加快发展步伐,不断提升在全国造船业中的地位,为江苏船舶工业发展作出更大贡献。

 

收藏-EJB3.0 JPQL一般语法

JPQL就是一种查询语言,具有与SQL 相类似的特征,JPQL是完全面向对象的,具备继承、多态和关联等特性,和hibernate HQL很相似。
 
查询语句的参数
JPQL语句支持两种方式的参数定义方式: 命名参数和位置参数。在同一个查询语句中只允许使用一种参数定义方式。
 
命令参数的格式为:“: +参数名”
例:

 

Java代码
  1. Query query = em.createQuery("select p from Person p where p.personid=:Id");  
  2. query.setParameter("Id",new Integer(1));  
 
位置参数的格式为“?+位置编号”
例:

 

Java代码
  1. Query query = em.createQuery("select p from Person p where p.personid=?1");  
  2. query.setParameter(1,new Integer(1));  
  3.    
 
如果你需要传递java.util.Datejava.util.Calendar参数进一个参数查询你需要使用一个特殊的setParameter()方法,相关的setParameter方法定义如下:
 

 

Java代码
  1. public interface Query  
  2. {  
  3. //命名参数查询时使用,参数类型为java.util.Date  
  4. Query setParameter(String name, java.util.Date value, TemporalType temporalType);  
  5. //命名参数查询时使用,参数类型为java.util.Calendar  
  6. Query setParameter(String name, Calendar value, TemporalType temporalType);  
  7. //位置参数查询时使用,参数类型为java.util.Date  
  8. Query setParameter(int position, Date value, TemporalType temporalType);  
  9. //位置参数查询时使用,参数类型为java.util.Calendar  
  10. Query setParameter(int position, Calendar value, TemporalType temporalType);  
  11. }  
  12.    
因为一个DateCalendar对象能够描述一个真实的日期、时间或时间戳.所以我们需要告诉Query对象怎么使用这些参数,我们javax.persistence.TemporalType作为参数传递进setParameter方法,告诉查询接口在转换java.util.Datejava.util.Calendar参数到本地SQL时使用什么数据库类型
 
下面通过实例来学习JPQL语句,例子的entity BeanPerson, order, orderItem他们之间的关系是:一个Person有多个Order,一个Order有多个OrderItem
 
JPQL语句的大小写敏感性:除了Java 类和属性名称外,查询都是大小写不敏感的。所以,Selectselect以及Select相同的,但是com.foshanshop.ejb3.bean.Personcom.foshanshop.ejb3.bean.PERSon是不同的,person.nameperson.NAME也是不同的。
 
 
命名查询
可以在实体bean通过@NamedQuery or @NamedQueries预先定义一个或多个查询语句,减少每次因书写错误而引起的BUG。通常把经常使用的查询语句定义成命名查询
 
定义单个命名查询:

 

Java代码
  1. @NamedQuery(name="getPerson", query= "FROM Person Where personid=?1")  
  2. @Entity  
  3. public class Person implements Serializable{  
  4.    
  5. 如果要定义多个命名查询,应在@javax.persistence.NamedQueries里定义@NamedQuery:  
  6. @NamedQueries({  
  7. @NamedQuery(name="getPerson", query= "FROM Person Where personid=?1"),  
  8. @NamedQuery(name="getPersonList", query= "FROM Person Where age>?1")  
  9. })  
  10. @Entity  
  11. public class Person implements Serializable{  
 
当命名查询定义好了之后,我们就可以通过名称执行其查询。代码如下:

 

Java代码
  1. Query query = em.createNamedQuery("getPerson");  
  2. query.setParameter(11);  
  3.    
 
排序(order by)
"ASC""DESC"分别为升序和降序,JPQL中默认为asc升序
例:

 

Java代码
  1. //先按年龄降序排序,然后按出生日期升序排序  
  2. Query query = em.createQuery("select p from Person p order by p.age desc, p.birthday asc");  
  3.    
查询部分属性
通常来说,都是针对Entity类的查询,返回的也是被查询的Entity类的实体。JPQL也允许我们直接查询返回我们需要的属性,而不是返回整个Entity在一些Entity中属性特别多的情况,这样的查询可以提高性能
例:

 

Java代码
  1. //只查询我们感兴趣的属性(列)  
  2. Query query=em.createQuery("select p.personid, p.name from Person p order by p.personid desc ");  
  3. //集合中的元素不再是Person,而是一个Object[]对象数组  
  4. List result = query.getResultList();  
  5. if (result!=null){  
  6. Iterator iterator = result.iterator();  
  7. while( iterator.hasNext() ){  
  8. Object[] row = ( Object[]) iterator.next();  
  9. int personid = Integer.parseInt(row[0].toString());  
  10. String PersonName = row[1].toString();  
  11. 。。。。  
  12. }  
  13. }  
 
查询中使用构造器(Constructor)
JPQL支持将查询的属性结果直接作为一个java class的构造器参数,并产生实体作为结果返回例如上面的例子只获取person entity bean的name and personid属性,我们不希望返回的集合的元素是object[],而希望用一个类来包装它。就要用到使用构造器
例:

 

Java代码
  1. public class SimplePerson {  
  2.  private Integer personid;  
  3. private String name;  
  4.    。。。。  
  5. public SimplePerson() {  
  6. }  
  7. public SimplePerson(Integer personid, String name) {  
  8. this.name = name;  
  9. this. personid = personid;  
  10. }  
  11. }  
 
查询代码为:

 

Java代码
  1. //我们把需要的两个属性作为SimplePerson的构造器参数,并使用new 函数。  
  2. Query query = em.createQuery("select new com.foshanshop.ejb3.bean.SimplePerson(p. personid, p.name) from Person p order by p.personid desc");  
  3. //集合中的元素是SimplePerson 对象  
  4. List result = query.getResultList();  
  5. if (result!=null){  
  6. Iterator iterator = result.iterator();  
  7. while( iterator.hasNext() ){  
  8. SimplePerson simpleperson = (SimplePerson) iterator.next();  
  9. 。。。。  
  10. }  
  11. }  
 
聚合查询(Aggregation)
JPQL支持的聚合函数包括:
1. AVG()
2. SUM()
3. COUNT()返回类型为Long,注意count(*)语法在hibernate中可用,但在toplink 其它产品中并不可用
4. MAX()
5. MIN()
 
例:

 

Java代码
  1. //获取最大年龄  
  2. Query query = em.createQuery("select max(p.age) from Person p");  
  3. Object result = query.getSingleResult();  
  4. String maxAge = result.toString();  
  5. //获取平均年龄  
  6. query = em.createQuery("select avg(p.age) from Person p");  
  7. //获取最小年龄  
  8. query = em.createQuery("select min(p.age) from Person p");  
  9. //获取总人数  
  10. query = em.createQuery("select count(p) from Person p");  
  11. //获取年龄总和  
  12. query = em.createQuery("select sum(p.age) from Person p");  
  13.    
  14. 如果聚合函数不是select…from的唯一一个返回列,需要使用"GROUP BY"语句。"GROUP BY"应该包含select 语句中除了聚合函数外的所有属性。  
  15. 例:  
  16. //返回男女生各自的总人数  
  17. Query query = em.createQuery("select p.sex, count(p) from Person p group by p.sex");  
  18. //集合中的元素不再是Person,而是一个Object[]对象数组  
  19. List result = query.getResultList();  
 
如果还需要加上查询条件,需要使用"HAVING"条件语句而不是"Where"语句
例:

 

SQL代码
  1. //返回人数超过1人的性别  
  2. Query query = em.createQuery("select p.sex, count(p) from Person p group by p.sex having count(*)>?1");  
  3. //设置查询中的参数  
  4. query.setParameter(1, new Long(1));  
  5. //集合中的元素不再是Person,而是一个Object[]对象数组  
  6. List result = query.getResultList();  
  7.    
 
关联(join)
JPQL仍然支持和SQL中类似的关联语法:
left out join/left join
inner join
left join fetch/inner join fetch
 
 
left out join/left join等,都是允许符合条件的右边表达式中的Entiies 为空(需要显式使用left join/left outer join 的情况会比较少。
例:

 

SQL代码
  1. //获取26岁人的订单,不管Order中是否有OrderItem  
  2. select o from Order o left join o.orderItems where o.ower.age=26 order by o.orderid  
  
inner join 要求右边的表达式必须返回Entities
例:

 

SQL代码
  1. //获取26 岁人的订单,Order 中必须要有OrderItem  
  2. select o from Order o inner join o.orderItems where o.ower.age=26 order by o.orderid  
 
 
!!重要知识点在默认的查询中,Entity中的集合属性默认不会被关联,集合属性默认是延迟加载( lazy-load )。那么,left fetch/left out fetch/inner join fetch提供了一种灵活的查询加载方式来提高查询的性能。
例:

 

Java代码
  1. private String QueryInnerJoinLazyLoad(){  
  2. // 默认不关联集合属性变量(orderItems)对应的表  
  3. Query query = em.createQuery("select o from Order o inner join o.orderItems where o.ower.age=26 order by o.orderid");  
  4. List result = query.getResultList();  
  5. if (result!=null && result.size()>0){  
  6. //这时获得Order 实体中orderItems( 集合属性变量)为空  
  7. Order order = (Order) result.get(0);  
  8. //当需要时,EJB3 Runtime才会执行一条SQL语句来加载属于当前Order的  
  9. //OrderItems  
  10. Set<OrderItem> list = order.getOrderItems();  
  11. Iterator<OrderItem> iterator = list.iterator();  
  12. if (iterator.hasNext()){  
  13. OrderItem orderItem =iterator.next();  
  14. System.out.println ("订购产品名:"+ orderItem.getProductname());  
  15. }  
  16. }  
 
上面代码在执行"select o from order o inner join o.orderItems where o.ower.age=26 order by o.orderid"时编译成的SQL如下(他不包含集合属性变量(orderItems)对应表的字段

 

SQL代码
  1. select order0_.orderid as orderid6_, order0_.amount as amount6_, order0_.person_id as  
  2. person4_6_, order0_.createdate as createdate6_ from Orders order0_ inner join OrderItems  
  3. orderitems1_ on order0_.orderid=orderitems1_.order_id, Person person2_ where  
  4. order0_.person_id=person2_.personid and person2_.age=26 order by order0_.orderid  
 
 
上面代码当执行到Set<OrderItem> list = order.getOrderItems();才会执行一条SQL语句来加载属于当前OrderOrderItems,编译成的SQL 如下

 

SQL代码
  1. select orderitems0_.order_id as order4_1_, orderitems0_.id as id1_, orderitems0_.id as id7_0_,  
  2. orderitems0_.order_id as order4_7_0_, orderitems0_.productname as productn2_7_0_,  
  3. orderitems0_.price as price7_0_ from OrderItems orderitems0_ where orderitems0_.order_id=?  
  4. order by orderitems0_.id ASC  
 
这样的查询性能上有不足的地方。为了查询NOrder,我们需要一条SQL语句获得所有的Order的原始对象属性,但需要另外N 条语句获得每个OrderorderItems集合属性。为了避免N+1的性能问题,我们可以利用join fetch一次过用一条SQL语句把Order的所有信息查询出来
 
例子

 

SQL代码
  1. //获取26 岁人的订单,Order 中必须要有OrderItem  
  2. Query query = em.createQuery("select o from Order o inner join fetch o.orderItems where 
  3. o.ower.age=26 order by o.orderid");  
 
上面这句HPQL编译成以下的SQL

 

SQL代码
  1. select order0_.orderid as orderid18_0_, orderitems1_.id as id19_1_, order0_.amount as  
  2. amount18_0_,order0_.person_id as person4_18_0_, order0_.createdate as createdate18_0_,  
  3. orderitems1_.order_id as order4_19_1_, orderitems1_.productname as productn2_19_1_,  
  4. orderitems1_.price as price19_1_, orderitems1_.order_id as order4_0__, orderitems1_.id as id0__  
  5. from Orders order0_ inner join OrderItems orderitems1_ on  
  6. order0_.orderid=orderitems1_.order_id, Person person2_ where  
  7. order0_.person_id=person2_.personid and person2_.age=26 order by order0_.orderid,  
  8. orderitems1_.id ASC  
 
上面由于使用了fetch,这个查询只会产生一条SQL语句,比原来需要N+1 SQL语句在性能上有了极大的提升
 
 
排除相同的记录DISTINCT
使用关联查询,我们很经常得到重复的对象,如下面语句:
"select o from order o inner join fetch o.orderItems order by o.orderid "
当有N orderItem 时就会产生NOrder,而有些Order对象往往是相同的,这时我们需要使用DISTINCT关键字来排除掉相同的对象
例:
SQL代码
  1. select DISTINCT o from Order o inner join fetch o.orderItems order by o.orderid  

 比较Entity

在查询中使用参数查询时,参数类型除了String, 原始数据类型( int, double)和它们的对象类型( Integer, Double),可以是Entity的实例
例:

 

SQL代码
  1. //查询某人的所有订单  
  2. Query query = em.createQuery("select o from Order o where o.ower =?1 order by o.orderid");  
  3. Person person = new Person();  
  4. person.setPersonid(new Integer(1));  
  5. //设置查询中的参数  
  6. query.setParameter(1,person);  
 
 
批量更新(Batch Update)
HPQL支持批量更新
例:

 

SQL代码
  1. //把所有订单的金额加10  
  2. Query query = em.createQuery("update Order as o set o.amount=o.amount+10");  
  3. //update 的记录数  
  4. int result = query.executeUpdate();  
  5.    
 
批量删除(Batch Remove)
例:

 

SQL代码
  1. //把金额小于100的订单删除,先删除订单子项,再删除订单  
  2. Query query = em.createQuery("delete from OrderItem item where item.order in(from Order as o where o.amount<100)");  
  3. query.executeUpdate();  
  4. query = em.createQuery("delete from Order as o where o.amount<100");  
  5. query.executeUpdate();//delete的记录数  
 
 
使用操作符NOT

 

SQL代码
  1. //查询除了指定人之外的所有订单  
  2. Query query = em.createQuery("select o from Order o where not(o.ower =?1) order by o.orderid");  
  3. Person person = new Person();  
  4. person.setPersonid(new Integer(2));  
  5. //设置查询中的参数  
  6. query.setParameter(1,person);  
 
 
使用操作符BETWEEN
SQL代码
  1. select o from Order as o where o.amount between 300 and 1000  

 

使用操作符IN

 

SQL代码
  1. //查找年龄为26,21 的Person  
  2. select p from Person as p where p.age in(26,21)  
  3.    
使用操作符LIKE

 

SQL代码
  1. //查找以字符串"li"开头的Person  
  2. select p from Person as p where p.name like ‘li%’  
  3.    
使用操作符IS NULL

 

SQL代码
  1. //查询含有购买者的所有Order  
  2. select o from Order as o where o.ower is [notnull  
  3.    
使用操作符IS EMPTY
IS EMPTY是针对集合属性(Collection)的操作符。可以和NOT 一起使用注:低版权的Mysql 不支持IS EMPTY

 

SQL代码
  1. //查询含有订单项的所有Order  
  2. select o from Order as o where o.orderItems is [not] empty  
 
使用操作符EXISTS
[NOT]EXISTS 需要和子查询配合使用。注:低版权的Mysql 不支持EXISTS

 

SQL代码
  1. //如果存在订单号为1 的订单,就获取所有OrderItem  
  2. select oi from OrderItem as oi where exists (select o from Order o where o.orderid=1)  
  3. //如果不存在订单号为10 的订单,就获取id 为1 的OrderItem  
  4. select oi from OrderItem as oi where oi.id=1 and not exists (select o from Order o where o.orderid=10)  
 
 
字符串函数
JPQL定义了内置函数方便使用。这些函数的使用方法和SQL中相应的函数方法类似。包括:
1. CONCAT 字符串拼接
2. SUBSTRING 字符串截取
3. TRIM 去掉空格
4. LOWER 转换成小写
5. UPPER 装换成大写
6. LENGTH 字符串长度
7. LOCATE 字符串定位
 
例:

 

SQL代码
  1. //查询所有人员,并在姓名后面加上字符串"_foshan"  
  2. select p.personid, concat(p.name‘_foshan’from Person as p  
  3. //查询所有人员,只取姓名的前三个字符  
  4. select p.personid, substring(p.name,1,3) from Person as p  
  5.    
计算函数
HPQL定义的计算函数包括:
ABS 绝对值
SQRT 平方根
MOD 取余数
SIZE 取集合的数量
 
例:

 

SQL代码
  1. //查询所有Order 的订单号及其订单项的数量  
  2. select o.orderid, size(o.orderItems) from Order as o group by o.orderid  
  3. //查询所有Order 的订单号及其总金额/10 的余数  
  4. select o.orderid, mod(o.amount, 10) from Order as o  
  5.    
 
子查询
子查询可以用于Where HAVING 条件语句中
例:
//查询年龄为26 岁的购买者的所有Order

SQL代码
  1. select o from Order as o where o.ower in(select p from Person as p where p.age =26)  
 
 
结果集分页
有些时候当执行一个查询会返回成千上万条记录,事实上我们只需要显示一部分数据。这时我们需要对结果集进行分页QueryAPI有两个接口方法可以解决这个问题:setMaxResults( ) setFirstResult( )
 
setMaxResults方法设置获取多少条记录
setFirstResult方法设置从结果集中的那个索引开始获取(假如返回的记录有3条,容器会自动为记录编上索引,索引从0开始,依次为012
 
例:

 

Java代码
  1. public List getPersonList(int max,int whichpage) {  
  2. try {  
  3. int index = (whichpage-1) * max;  
  4. Query query = em.createQuery("from Person p order by personid asc");  
  5. List list = query.setMaxResults(max).  
  6. setFirstResult(index).  
  7. getResultList();  
  8. em.clear();//分离内存中受EntityManager管理的实体bean,让VM进行垃圾回收  
  9. return list;  
  10. catch (Exception e) {  
  11. e.printStackTrace();  
  12. return null;  
  13. }  
  14. }  

 

用Python调用中控SDK存取考勤机数据库

开发环境:myeclipse 6.5,pyDev,Python 2.6,Python ex for windows,pymssql,中控SDK

主代码
  1. # -*- coding: utf-8 -*-  
  2.   
  3. ”’ 
  4. Created on Sep 17, 2009 
  5.  
  6. @author: sy 
  7. ”’  
  8. from win32com.client import Dispatch  
  9. from zk.demo.IC_db import IC_DB  
  10. import sys  
  11. from datetime import datetime  
  12.   
  13.   
  14.        
  15. devid = 1  
  16. usersInfo=[  
  17.            ['204113386','a1',3],  
  18.            ['-491435564','a2',4],  
  19.            ['1550229372','a3',5]  
  20.            ]  
  21. statusNames =(  
  22.               ‘Tatal adminstrator’,  
  23.               ‘Total users’,  
  24.               ‘Total FP’,  
  25.               ‘Total Password’,  
  26.               ‘Total manage record’,  
  27.               ‘Total In and out record’,  
  28.               ‘Nominal FP number’,  
  29.               ‘Nominal user number’,  
  30.               ‘Nominal In and out record number’,  
  31.               ‘Remain FP number’,  
  32.               ‘Remain user number’,  
  33.               ‘Remain In and out record number’)  
  34.   
  35. def syncDateTime(zk):  
  36.     print ‘Set Termail Datetime by PC…’  
  37.     if zk.SetDeviceTime(devid):  
  38.         print ‘Set Termail Datetime ok’  
  39.   
  40.       
  41.       
  42.         
  43. def SendUserInfo(zk):  
  44.     cardNo = ’0522766478′  
  45.     zk.SetStrCardNumber(cardNo)  
  46.       
  47.     zk.SetUserInfo(devid,2,‘沈阳’,None,True)  
  48.       
  49.     for user in usersInfo:  
  50.         print user  
  51.         zk.SetStrCardNumber(user[0])  
  52.         s = zk.SetUserInfo(devid,user[2],user[1],None,0,True)  
  53.         if s:  
  54.             print ‘send user %s info to device,Card No:%s ’ %(user[1],user[0])  
  55.     db = IC_DB()  
  56.     users = db.getUserInfo()  
  57.     usersCount = len(users)  
  58.       
  59.     if usersCount>0:  
  60.         print ‘Sending some user info to device…’, datetime.now()  
  61.         #zk.BeginBatchUpdate(devid,1)  
  62.         for user in users:  
  63.             zk.SetStrCardNumber(user[1])  
  64.             s = zk.SetUserInfo(devid,user[0],user[2],None,0,True)  
  65.             if s and usersCount<10:  
  66.                 print ‘send user %s info to device,Card No:%s ’ %(user[2],user[0])  
  67.         #if len(users)>0:  
  68.         #if zk.BatchUpdate(devid):  
  69.         print ‘Send %d user info to device.’ %(len(users)),datetime.now()  
  70. def downloadLog(zk):  
  71.     if zk.ReadAllGLogData(devid):  
  72.         print ‘User log list:’  
  73.         while True:  
  74.             s= zk.GetGeneralLogDataStr(devid,None,None,None,None)  
  75.             if s[0]:  
  76.                 print ‘Reg No:%d  VerifyMode:%d InOutMode:%d DateTime:%s’ %(s[1],s[2],s[3],s[4])  
  77.             else:  
  78.                 break  
  79.         print ‘User log list end.’  
  80.       
  81. def readDeviceStatus(zk):  
  82.     s = zk.GetFirmwareVersion(devid,None)  
  83.     if s[0]:  
  84.         print ‘firmware Version:’,s[1]  
  85.     s = zk.GetSerialNumber(devid,None)  
  86.     if s[0]:  
  87.         print ‘Serial Number:%s’ %(s[1])  
  88.     s = zk.GetProductCode(devid,None)  
  89.     if s[0]:  
  90.         print ‘Product Code:%s’ %(s[1])  
  91.     s= zk.GetDeviceTime(devid,None,None,None,None,None,None)  
  92.     if s[0]:  
  93.         print ‘Device Time:’ ,(s[1:8])  
  94.     for i in range(1,12):  
  95.         s= zk.GetDeviceStatus(devid,i,None)  
  96.         if s[0]:  
  97.             print ‘%s:%s’ %(statusNames[i-1],s[1])  
  98.       
  99.   
  100. def connectToZK(zk):  
  101.     devPort = 4370  
  102.     devIPAddr = ’192.168.30.198′  
  103.       
  104.     flag = zk.Connect_Net(devIPAddr,devPort)  
  105.     print ‘Connect flag:%d’ %flag  
  106.     if flag:  
  107.         print ‘Device Connected.’  
  108.     return flag  
  109.       
  110. def clearAllData(zk):  
  111.     print ‘Clear device all log..’  
  112.     if zk.ClearKeeperData(devid):  
  113.         print ‘Clear device all log finished.’  
  114.   
  115. def main():  
  116.       
  117.     zk = Dispatch(‘zkemkeeper.ZKEM’)  
  118.       
  119.     #sdkVersion = create_string_buffer(”,256)  
  120.     sdkVersion = zk.GetSDKVersion(None)  
  121.     if sdkVersion[0]:  
  122.         print ‘sdkVersion:’ , sdkVersion[1]  
  123.         if connectToZK(zk):  
  124.             readDeviceStatus(zk)  
  125.             syncDateTime(zk)  
  126.             if len(sys.argv)>1:  
  127.                 if sys.argv[1] ==‘send’:  
  128.                     clearAllData(zk)  
  129.                     SendUserInfo(zk)  
  130.             else:  
  131.                 downloadLog(zk)  
  132.             pass  
  133.             zk.Disconnect()  
  134.             print ‘Disconnect…’  
  135.     print ‘Done’  
  136.       
  137.       
  138.   
  139.    
  140. if __name__ == ‘__main__’:  
  141.     main()  

 

zk.demo.IC_db代码
  1. # -*- coding: utf-8 -*-  
  2. ”’ 
  3. Created on Sep 18, 2009 
  4.  
  5. @author: sy 
  6. ”’  
  7. import pymssql  
  8.   
  9. class IC_DB:  
  10.     ”’ 
  11.     classdocs 
  12.     ”’  
  13.     
  14.   
  15.     def __init__(self):  
  16.         ”’ 
  17.         Constructor 
  18.         ”’  
  19.            
  20.     def getUserInfo(self):  
  21.         con = pymssql.connect(host=‘localhost,1433′, user=‘sa’, password=,database =‘IC_DB’)  
  22.         cur = con.cursor()  
  23.         cur.execute(operation=’Select top 5 a.card_id,a.snr,b.user_name ,b.user_code FROM ztx_card_init a ,pub_user b,pub_card c\  
  24.                 Where a.card_id = c.Card_id1 AND c.User_uid = b.user_uid’)  
  25.         return cur.fetchall()  
  26.           
  27.           

 

STX Shipbuilding造船厂采用达索PLM

中国北京,2009 年 2月 4 日- 日前,产品全生命周期管理 (PLM) 解决方案及 3D 技术的领导者,达索系统公司(Dassault Systèmes;DS)(巴黎欧洲证券:#13065,DSY.PA)宣布,世界领先的造船公司之一 STX Shipbuilding 已采用达索ENOVIA 解决方案作为企业内部署PLM的支持骨干

为巩固STX Shipbuilding作为世界一流造船厂的优势,该公司计划在其三大生产基地部署达索ENOVIA PLM解决方案的流程创新(Process Innovation;PI)项目,其中包括:韩国镇海 (Jinhae) 造船厂、中国大连造船厂及STX近期收购的顶级游轮制造商——挪威 Aker Yards造船厂。这次大规模的部署在造船行业当属首次。由于每艘船舶的建造一般需要使用超过 12 万个不同种类的数据文件,STX 的 PI 流程着重于推进内部关键职能部门(如存货、生产、质量控制以及会计等)与外部供应商之间更深入的协作,并推广最佳实践。此方法确保任何变更需求均可被轻松 地整合到最终数据中,从而减少出错的几率,最终将项目完成时间平均缩短 15%。

STX Shipbuilding 的高级副总裁 Hyo-Gwan Leem 指出:“通过部署 达索ENOVIA PLM 解决方案,我们可将关键业务流程标准化,实现更加密切地协作并创造推动创新的反馈机制,从而大幅提高运营绩效。通过此次PI 项目的部署,我们预计今后五年可将成本降低1,000亿韩元以上,具体实现公司价值的增长。”

通过部署包括 Product Central、Program Central 及 Engineering Central 在内的 ENOVIA 解决方案骨干,STX Shipbuilding 已经将工程工作量减少 50%,生产工作量减少 30%。此外,凭借ENOVIA解决方案,该公司得以向客户提供广泛的船舶建模信息、确保计划制定更加精确、并防止任务延滞,大幅缩短研发周期。

达索系统公司ENOVIA 亚洲区副总裁兼总经理 Andy Kalambi 表示:“与STX的成功合作代表ENOVIA 产品进军全球船舶制造行业的首战告捷。这也彰显了客户