`
brandNewUser
  • 浏览: 446995 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

ApacheOFBiz的相关介绍以及使用总结(二)

阅读更多

 

 

OFBiz的实体配置

 
实体定义文件一般存放位置是在对应模块的entity文件夹下面,在该模块对应的ofbiz-component.xml配置文件中加入一行,用来声明实体定义文件路径:
 
<entity-resource type="model" reader-name="main" loader="main" location="entitydef/entitymodel.xml"/> 
 
我们这里先建立一个普通实体,声明数据库中该表中的所有字段信息。
 

实体定义的命名规则 

 
实体名称(entity-name)首字母大写,如果实体名称由多个关键字组成,那么关键字首字母大写,例如entity-name="TenantDataSource",ofbiz 会在创建数据库表的时候根据entity-name 实体名称除首字母之外的大写字母前加“_”,所以entity-name="TenantDataSource"生成的数据库表名为 “Tenant_Data_Source”,所以要控制entity-name 实体名称不要超过25个字母。 
 
Field 表字段,命名规则与实体名称差不多,唯一不同的是首字母小写。 
 
其中的fieldtype,可以通过文件:
 
%ofbiz_home%\framework\entity\fieldtype\fieldtypeXXX.xml 其中XXX为你使用的数据库名称
 
进行查找,就可以找到field同具体type之间的对应关系。
 
定义第一个实体:
 
<entity entity-name="DsConsultant" package-name="com.xxx.crm.drivingschool">
        <field name="consultantId" type="id-ne"/>
        <field name="consultantName" type="name"/>
        <field name="consultantCode" type="name"/>
        <field name="gender" type="indicator"/>
        <field name="city" type="name"/>
        <field name="email" type="name"/>

        <prim-key field="consultantId"/>
    </entity>
 
实体中定义了属性,注意这些属性中field name会通过Java以及SQL的命名规范进行映射,例如声明的consultantId使用了Java Camel风格命名方式,但映射到数据库中字段为:consultant_id。
在OFBiz中的实体分为多种类型,我们这里介绍本人使用最多的两种类型:
 
<!--?xml version="1.0" encoding="UTF-8" standalone="no"?-->

普通实体 

 
普通实体和数据库中的表是一一对应的。程序会根据实体定义在数据库中创建表,索引,外键约束等。 
 
 
<entity entity-name="TenantDataSource" package-name="org.ofbiz.entity.tenant"> 
        <description> 
            There should be one record for each tenant and each group-map for the active delegator. 
            The jdbc fields will override the datasource -> inline-jdbc values for the per-tenant delegator. 
        </description> 
        <field name="tenantId" type="id-ne"/> 
        <field name="entityGroupName" type="name"/> 
        <field name="jdbcUri" type="long-varchar"/> 
        <field name="jdbcUsername" type="long-varchar"/> 
        <field name="jdbcPassword" type="long-varchar"></field> 
        <prim-key field="tenantId"/> 
        <prim-key field="entityGroupName"/> 
        <relation type="one" fk-name="TNTDTSRC_TNT" rel-entity-name="Tenant"> 
        <key-map field-name="tenantId"/> 
        </relation> 
</entity> 
 
 

视图实体 

 
View entity 一般用做多表连接复杂查询,view entity 不会在数据库中反映出来。 
 
<view-entity entity-name="WorkEffortAssocView" 
            package-name="org.ofbiz.workeffort.workeffort" 
            title="Work Effort Association Entity with Name"> 
      <member-entity entity-alias="WA" entity-name="WorkEffortAssoc"/> 
      <member-entity entity-alias="WETO" entity-name="WorkEffort"/> 
      <alias-all entity-alias="WA"/> 
      <alias entity-alias="WETO" name="workEffortToName" field="workEffortName"/> 
      <alias entity-alias="WETO" name="workEffortToSetup" field="estimatedSetupMillis"/> 
      <alias entity-alias="WETO" name="workEffortToRun" field="estimatedMilliSeconds"/> 
      <alias entity-alias="WETO" name="workEffortToParentId" field="workEffortParentId"/> 
      <alias entity-alias="WETO" name="workEffortToCurrentStatusId" field="currentStatusId"/> 
      <alias entity-alias="WETO" name="workEffortToWorkEffortPurposeTypeId" field="workEffortPurposeTypeId"/> 
      <alias entity-alias="WETO" name="workEffortToEstimatedStartDate" field="estimatedStartDate"/> 
      <alias entity-alias="WETO" name="workEffortToEstimatedCompletionDate" field="estimatedCompletionDate"/> 
      <alias entity-alias="WETO" name="workEffortToActualStartDate" field="actualStartDate"/> 
      <alias entity-alias="WETO" name="workEffortToActualCompletionDate" field="actualCompletionDate"/> 
      <view-link entity-alias="WA" rel-entity-alias="WETO"> 
        <key-map field-name="workEffortIdTo" rel-field-name="workEffortId"/> 
      </view-link> 
      <relation type="one-nofk" fk-name="WK_EFFRTASSV_FWE" title="From" rel-entity-name="WorkEffort"> 
        <key-map field-name="workEffortIdFrom" rel-field-name="workEffortId"/> 
      </relation> 
</view-entity>
 
 
视图实体用于做多表连接的复杂查询,并不会在数据库端被反映出来,在更新的情况下也会有一定的困难。
 
<!--?xml version="1.0" encoding="UTF-8" standalone="no"?-->
 
首先,视图实体中的所有关联的数据表都需要在ofbiz的管理范围内:
 
<member-entity entity-alias="SR" entity-name="DsStudentReservation"/>
 
用来指定关联的实体及其别名,
 
<alias name="id" entity-alias="SR" field="id"/>
 
用来引用关联实体中的属性,属性可以重新命名(如果实体中属性冲突或更改显示名称时使用)。
 
<view-link entity-alias="SR" rel-entity-alias="SS">
            <key-map field-name="studentId" rel-field-name="id"/>
        </view-link>
 
使用关联的方式将其属性关联在一起。
 
如果optional=“false”, 将进行强制内关联。
 
在用groovy查询及在Forms.xml中使用时,与其它方式是相同的。
 
<alias-all entity-alias="ODD" prefix="orderDate" group-by="true">   
<exclude field="dimensionId"/>   
</alias-all>   
 
alias-all 将某个实体的全部字段定义进来。Prefix定义以规定字段字符开头的字段。 
exclude 将实体中某些字段剔除出去。
 
视图实体中relation 只能用来做关系查询, 而view-link 用来做 join 关联查询。
在entityengine.xml中<datasource ..>元素当中的join-style属性当中设置你的数据库join语法;rel-optional:关联类型,默认是内连接,如果将此属性值设为true ,则为外连接。
 
假如需要做一些比较复杂的关联查询,使用下面的方式:
 
<alias entity-alias="OI" name="quantityOrdered" function="sum">   
    <complex-alias operator="-">   
        <complex-alias-field entity-alias="OI"   
            field="quantity"   
            default-value="0"/>   
        <complex-alias-field entity-alias="OI"   
            field="cancelQuantity"   
            default-value="0"/>   
    </complex-alias>   
</alias>   
 
 
结果为: 
 
Select  SUM((COALESCE(OI.QUANTITY, 0) - COALESCE(OI.CANCEL_QUANTITY, 0)))  
 
一个缺省值是一个良好的习惯,否则当他们之中有一个为空就会导致结果为空 
这个操作可以支持你使用数据库的所有函数例如  +, -, * 和 /,字符串连接符||。 
 
还可以添加一个 function="" 实现min, max, sum, avg, count, count-distinct, upper 和 lower 在 complex-alias-field中,例如:
 
<alias entity-alias="OI" >   
    <complex-alias operator="-">   
        <complex-alias-field entity-alias="OI"   
                               field="quantity"   
                               default-value="0"   
                               function="sum"/>   
        <complex-alias-field entity-alias="OI"   
                               field="cancelQuantity"   
                               default-value="0"   
                   function="sum"/>   
    </complex-alias>   
</alias>   
 
 
翻译成SQL为:
 
SELECT (SUM(COALESCE(OI.QUANTITY,'0')) - SUM(COALESCE(OI.CANCEL_QUANTITY,'0')))  
 

 Delegator

 
Delegator是OFBiz中根据定义的实体模型来查询数据库的主要方式,可以在服务中通过dispatchContext.getDelegator()获取,也可以在groovy文件中直接使用。
使用Delegator的create方法来创建单个实体:
 
Delegator delegator = ctx.getDelegator();
            String id = delegator.getNextSeqId("ServiceCar");
            GenericValue dsServiceCar = delegator.makeValue("ServiceCar", UtilMisc.toMap(
                    "id", id,
                    "carType", context.get("carType")
                    "carNumber", context.get("carNumber"),
                    "coachId", context.get("coachId"),
                   "phone", context.get("phone")
            ));
            delegator.create(dsServiceCar);
 
需要创建GenericValue,可以通过可变参数的方式来将该实体创建出来。值得注意的是,实体中的主键需要通过getNextSeqId来拿到,在获取下一个sequenceId的过程中,可能出现错误:
 
<!--?xml version="1.0" encoding="UTF-8" standalone="no"?-->
delegator.getNextSeqId(“数据表”), 但是居然出现了下面的问题:
 
java.lang.Exception: Failure in create operation for entity [DsSignupStudent]: org.ofbiz.entity.GenericEntityException:
 Error while inserting: [GenericEntity:DsSignupStudent][carType,DRIVING_TYPE_C1(java.lang.String)][comment,null()][commissionFee,0(java.lang.Long)][consultantId,10020(java.lang.String)][course1Time,0(java.lang.Long)][course2Time,0(java.lang.Long)][course3Time,0(java.lang.Long)][createdStamp,2015-10-10 09:44:05.147(java.sql.Timestamp)][createdTxStamp,2015-10-10 09:44:05.146(java.sql.Timestamp)][drivingSchoolId,2(java.lang.String)][handleBy,null()][id,10122(java.lang.String)][idCard,2123123(java.lang.String)][infoChannel,INFO_CHANNEL_NET(java.lang.String)][isBodyCheckTable,null()][isCommissionPayed,null()][isContractTable,null()][isFinger,null()][isGivenMaterial,null()][isIdCardTable,null()][isPersonalPhoto,null()][isReceipt,null()][isSignupTable,null()][isUrgent,null()][lastUpdatedStamp,2015-10-10 09:44:05.147(java.sql.Timestamp)][lastUpdatedTxStamp,2015-10-10 09:44:05.146(java.sql.Timestamp)][localTrain,LOCAL_TRAIN_BD(java.lang.String)][name,a1(java.lang.String)][nextVisitDate,2015-10-11(java.sql.Date)][payForm,PAY_FORM_CARD(java.lang.String)][payMethod,PAY_METHOD_ALL(java.lang.String)][payedFee,111(java.lang.Long)][phone,122(java.lang.String)][referrerId,null()][serviceCityId,2(java.lang.String)][signupDate,2015-10-10(java.sql.Date)][signupFee,111(java.lang.Long)][signupStore,SIGNUP_STORE_FHD(java.lang.String)][studentStatus,STUDENT_STATUS_Y(java.lang.String)][studyProgress,STUDY_PROGRESS_LR(java.lang.String)][trainType,TRAIN_TYPE_ZX(java.lang.String)][trainingSiteId,10000(java.lang.String)] (SQL Exception while executing the following:INSERT INTO DS_SIGNUP_STUDENT (ID, SERVICE_CITY_ID, SIGNUP_STORE, NAME, ID_CARD, PHONE, CAR_TYPE, SIGNUP_FEE, PAY_METHOD, PAY_FORM, PAYED_FEE, SIGNUP_DATE, STUDY_PROGRESS, DRIVING_SCHOOL_ID, LOCAL_TRAIN, TRAIN_TYPE, INFO_CHANNEL, TRAINING_SITE_ID, CONSULTANT_ID, REFERRER_ID, NEXT_VISIT_DATE, STUDENT_STATUS, COMMENT, COURSE1_TIME, COURSE2_TIME, COURSE3_TIME, IS_ID_CARD_TABLE, IS_BODY_CHECK_TABLE, IS_SIGNUP_TABLE, IS_PERSONAL_PHOTO, IS_CONTRACT_TABLE, IS_RECEIPT, IS_FINGER, IS_GIVEN_MATERIAL, IS_URGENT, HANDLE_BY, COMMISSION_FEE, IS_COMMISSION_PAYED, IS_EXAM_FEE_PAYED, LAST_UPDATED_STAMP, LAST_UPDATED_TX_STAMP, CREATED_STAMP, CREATED_TX_STAMP) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) (Duplicate entry '10122' for key 'PRIMARY')). 
Rolling back transaction.
        at 
org.ofbiz.entity.transaction.TransactionUtil.setRollbackOnly(TransactionUtil.java:378) [ofbiz-entity-test.jar:?]
 
 
为什么系统会自动填充10122这个主键?我们发现OFBiz中存在一张表:
 
select * from sequence_value_item;
 
 
用于记录每个实体的下一个生成主键,如果这个主键已经被使用了,就会发生上面的错误:


 
在delegator中使用各种find方法来进行查找,最主要的查询方法是findList:
 
condition = EntityCondition.makeCondition(EntityJoinOperator.AND,EntityCondition.makeCondition("isConfirmed", EntityOperator.EQUALS, 'Y'),cityCondition,deleteCondition);
context.allRecords = delegator.findList("DsStudentPayRecordView", condition, null, ["-recordDate"], null, false);
 
可以根据需要选择的实体,选择的条件,选出的字段(如果为null则选择所有的字段),排序方式(在groovy中通过减号-来进行倒序),是否缓存(cache)来进行全面的查询。
此外,OFBiz中是可以跳过内置的实体模型,来直接查询数据库的。

 

在配置文件entityengine.xml中,需要使用GenericHelperDAO:

 

<datasource name="localmysqlolap"
            helper-class="org.ofbiz.entity.datasource.GenericHelperDAO"
            field-type-name="mysql"
            check-on-start="true"
            add-missing-on-start="true"
            check-pks-on-start="false"
            use-foreign-keys="true"
            join-style="ansi-no-parenthesis"
            alias-view-columns="false"
            drop-fk-use-foreign-key-keyword="true"
            table-type="InnoDB"
            character-set="utf8"
            collate="utf8_general_ci">
    <read-data reader-name="tenant"/>
    <read-data reader-name="seed"/>
    <read-data reader-name="seed-initial"/>
    <read-data reader-name="demo"/>
    <read-data reader-name="ext"/>
    <read-data reader-name="ext-test"/>
    <read-data reader-name="ext-demo"/>
    <inline-jdbc
            jdbc-driver="com.mysql.jdbc.Driver"
            jdbc-uri="jdbc:mysql://xxx.com:3306/xxx?useUnicode=true&amp;characterEncoding=utf8&amp;autoReconnect=true&amp;failOverReadOnly=false"
            jdbc-username="xxx"
            jdbc-password="xxxx"
            isolation-level="ReadCommitted"
            pool-minsize="2"
            pool-maxsize="250"
            time-between-eviction-runs-millis="600000"/><!-- Please note that at least one person has experienced a problem with this value with MySQL
            and had to set it to -1 in order to avoid this issue.
            For more look at http://markmail.org/thread/5sivpykv7xkl66px and http://commons.apache.org/dbcp/configuration.html-->
    <!-- <jndi-jdbc jndi-server-name="localjndi" jndi-name="java:/MySqlDataSource" isolation-level="Serializable"/> -->
</datasource>

 

找到其中的group-name,在本文件声明中的group-name为:

 

<delegator name="test" entity-model-reader="main" entity-group-reader="main" entity-eca-reader="main">
    <group-map group-name="org.ofbiz" datasource-name="localmysql"/>
    <group-map group-name="org.ofbiz.olap" datasource-name="localmysqlolap"/>
    <group-map group-name="org.ofbiz.tenant" datasource-name="localmysqltenant"/>

</delegator>

 

 

可以看出,对应的group-name为org.ofbiz.tenant,使用这个group-name来构建SQLProcessor,就可以进行数据库SQL查询。

在Groovy中的写法为:

 

sqlProcessor = new SQLProcessor(delegator.getGroupHelperInfo("org.ofbiz.tenant"));
result = sqlProcessor.executeQuery("select * from xxx")
while (result.next()){
    println result.getString("id")
}

 

可以通过调用ResultSet的方式进行数据库的查询操作,此时SQL就需要为可以在数据库中直接查询的SQL了。

 
总之,OFBiz中的实体模型还是比较强大的而且易于扩展,虽然相比Hibernate肯定有所不足,但足以应付其中的所有应用场景,以一种非常快捷易用的方式来进行业务场景逻辑的组合工作。
 
  • 大小: 67.1 KB
分享到:
评论

相关推荐

    六首页数字藏品NFT交易网React NextJS网站模板 六首页数字藏品nft交易网反应NextJS网站模板

    六首页数字藏品NFT交易网React NextJS网站模板 六首页数字藏品nft交易网反应NextJS网站模板

    wireshark安装教程入门

    wireshark安装教程入门

    基于C++负数据库的隐私保护在线医疗诊断系统

    【作品名称】:基于C++负数据库的隐私保护在线医疗诊断系统 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【项目介绍】: 基于负数据库的隐私保护在线医疗诊断系统 NDBMedicalSystem 客户端及服务器端 本项目是在保护用户隐私的前提下,完成了对新冠肺炎、乳腺癌、眼疾等多种疾病的智能诊断。

    基本的嵌入式操作系统给

    任务管理

    3-10.py

    3-10

    Python3+MATLAB无线传感器网络相关仿真 基于RSSI测距的多边定位法仿真 生成五种网络拓扑结构源码.zip

    Python3+MATLAB无线传感器网络相关仿真 基于RSSI测距的多边定位法仿真 生成五种网络拓扑结构源码.zip

    matlab交互式课件模块,介绍了典型的工作流程,设置,以及涉及到用机器学习解决回归问题的考虑.zip

    matlab交互式课件模块,介绍了典型的工作流程,设置,以及涉及到用机器学习解决回归问题的考虑.zip

    563563565+3859

    5635356

    基于Matlab的模糊控制PID仿真以及相应的论文验证参数源码+文档+各种资料.zip

    基于Matlab的模糊控制PID仿真以及相应的论文验证参数源码+文档+各种资料.zip

    麦肯锡-年月xx集团战略设计和首次上市咨询报告.ppt

    麦肯锡-年月xx集团战略设计和首次上市咨询报告.ppt

    麦肯锡 把握中国资本市场的机遇.ppt

    麦肯锡 把握中国资本市场的机遇.ppt

    基于python深度学习实现多种农产品价格预测源码+项目说明.zip

    基于python深度学习实现多种农产品价格预测源码+项目说明.zip个人经导师指导并认可通过的98分大作业设计项目,适用人群:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业或毕业设计,作为“参考资料”使用。 基于python深度学习实现多种农产品价格预测源码+项目说明.zip个人经导师指导并认可通过的98分大作业设计项目,适用人群:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业或毕业设计,作为“参考资料”使用。 基于python深度学习实现多种农产品价格预测源码+项目说明.zip个人经导师指导并认可通过的98分大作业设计项目,适用人群:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业或毕业设计,作为“参考资料”使用。 基于python深度学习实现多种农产品价格预测源码+项目说明.zip个人经导师指导并认可通过的98分大作业设计项目,适用人群:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业或毕业设计,作为“参考资料”使用。 基于python深度学习实现多种农产品价格预测源码+项目说明.zip个人经导师指导并认可通过的98分大作

    matlab华松敏编写的教科书《机器人理论与技术基础》的源代码.zip

    matlab华松敏编写的教科书《机器人理论与技术基础》的源代码.zip

    setuptools-23.0.0-py2.py3-none-any.whl

    文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

    ChatGPT 中文调教指南.zip

    ChatGPT是由OpenAI训练的一款大型语言模型,能够和你进行任何领域的对话。 国内中文版 它能够生成类似于人类写作的文本。您只需要给出提示或提出问题,它就可以生成你想要的东西。 充当 Linux 终端 我想让你充当 Linux 终端。我将输入命令,您将回复终端应显示的内容。我希望您只在一个唯一的代码块内回复终端输出,而不是其他任何内容。不要写解释。除非我指示您这样做,否则不要键入命令。当我需要用英语告诉你一些事情时,我会把文字放在中括号内[就像这样]。我的第一个命令是 pwd 充当英语翻译和改进者 我希望你能担任英语翻译、拼写校对和修辞改进的角色。我会用任何语言和你交流,你会识别语言,将其翻译并用更为优美和精炼的英语回答我。请将我简单的词汇和句子替换成更为优美和高雅的表达方式,确保意思不变,但使其更具文学性。请仅回答更正和改进的部分,不要写解释。我的第一句话是“how are you ?”,请翻译它。 充当论文润色者(拿摘要部分举例) 请你充当一名论文编辑专家,在论文评审的角度去修改论文摘要部分,使其更加流畅,优美。下面是具体要求: 能让读者快速获得文章的要点或精髓,

    matlab机器人课程和书籍中的问题.zip

    matlab机器人课程和书籍中的问题.zip

    麦肯锡_-_解决_问题_的_基本_方法_-_七步成诗.ppt

    麦肯锡_-_解决_问题_的_基本_方法_-_七步成诗.ppt

    麦肯锡培训手册——好的开始是成功的一半()如何进行团队及团队与客户之间的交流.ppt

    麦肯锡培训手册——好的开始是成功的一半()如何进行团队及团队与客户之间的交流.ppt

    Scrapy-1.2.0-py2.py3-none-any.whl

    文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

    stm32f103c8t6 写一个串口DMA程序

    stm32f103c8t6在STM32F103C8T6上编写一个使用DMA(Direct Memory Access)的串口(USART)程序,通常涉及以下几个步骤: 初始化串口(USART):设置波特率、数据位、停止位和校验位。 初始化DMA:配置DMA通道、传输方向、源地址和目标地址等。 配置NVIC(Nested Vectored Interrupt Controller):如果需要中断来处理DMA传输完成事件。 主程序循环:发送或接收数据,并处理相关事件。

Global site tag (gtag.js) - Google Analytics