ofbiz之entity实体写法

  1. 实体定义文件 
    实体定义文件一般存放位置是在对应模块的entity文件夹下面,以party为例,party的实体定义文件路径为
    %ofbiz-home%\applications\party\entitydef\entitymodel.xml。 
    通过对应模块的ofbiz-component.xml进行加载。 
    <entity-resource type="model" reader-name="main" loader="main" location="entitydef/entitymodel.xml"/> 
    <entity-resource type="model" reader-name="main" loader="main" location="entitydef/entitymodel_old.xml"/> 
  2. 实体类型
    • 普通实体 
      <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 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>

      <view-entity entity-name="FaultTransSumView" package-name="com.sunyard.cpsp.fault">
          	<description>业务差错统计视图</description>
          	<member-entity entity-alias="FT" entity-name="FaultTrans"></member-entity>
          	<alias entity-alias="FT" name="faultTypeId"  group-by="true"></alias>
          	<alias entity-alias="FT" name="createdDate"  group-by="true"></alias>
          	<alias entity-alias="FT" name="cpspMsgId" col-alias="count" function="count"></alias>
      </view-entity>

      <datasource name="localmysql"
                  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" //如果使用上面的复合函数类型(红色背景标记)  此处需要改为alias-view-columns="true"  切记!
                  drop-fk-use-foreign-key-keyword="true"
                  table-type="InnoDB"
                  character-set="utf8"
                  collate="utf8_general_ci">
              <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://localhost/app_center?autoReconnect=true&characterEncoding=UTF-8"
                      jdbc-username="root"
                      jdbc-password="root"
                      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>
      view entity 一般用做多表连接复杂查询,view entity 不会在数据库中反映出来。

    • 扩展实体
      <extend-entity entity-name="UserLogin"> 
              <field name="partyId" type="id"></field> 
              <relation type="one" fk-name="USER_PARTY" rel-entity-name="Party"> 
                  <key-map field-name="partyId"/> 
              </relation> 
              <relation type="one-nofk" rel-entity-name="Person"> 
                  <key-map field-name="partyId"/> 
              </relation> 
              <relation type="one-nofk" rel-entity-name="PartyGroup"> 
                  <key-map field-name="partyId"/> 
              </relation> 
      </extend-entity> 
      继承已存在的实体并对其进行扩展。

    • 动态实体 
      DynamicViewEntity salesUsageViewEntity = new DynamicViewEntity(); 
      salesUsageViewEntity.addMemberEntity("OI", "OrderItem"); 
      salesUsageViewEntity.addMemberEntity("OH", "OrderHeader"); 
      salesUsageViewEntity.addMemberEntity("ItIss", "ItemIssuance"); 
      salesUsageViewEntity.addMemberEntity("InvIt", "InventoryItem"); 
      salesUsageViewEntity.addViewLink("OI", "OH", Boolean.valueOf(false), ModelKeyMap.makeKeyMapList("orderId")); 
      salesUsageViewEntity.addViewLink("OI", "ItIss", Boolean.valueOf(false), ModelKeyMap.makeKeyMapList("orderId", "orderId", "orderItemSeqId", "orderItemSeqId")); 
      salesUsageViewEntity.addViewLink("ItIss", "InvIt", Boolean.valueOf(false), ModelKeyMap.makeKeyMapList("inventoryItemId")); 
      
      salesUsageViewEntity.addAlias("OI", "productId"); 
      salesUsageViewEntity.addAlias("OH", "statusId"); 
      salesUsageViewEntity.addAlias("OH", "orderTypeId"); 
      salesUsageViewEntity.addAlias("OH", "orderDate"); 
      salesUsageViewEntity.addAlias("ItIss", "inventoryItemId"); 
      salesUsageViewEntity.addAlias("ItIss", "quantity"); 
      salesUsageViewEntity.addAlias("InvIt", "facilityId"); 
      
      EntityListIterator salesUsageIt = delegator.findListIteratorByCondition(
      	salesUsageViewEntity, 
      	EntityCondition.makeCondition( 
      		UtilMisc.toList( 
               		EntityCondition.makeCondition("facilityId", EntityOperator.EQUALS, facilityId), 
                		EntityCondition.makeCondition("productId", EntityOperator.EQUALS, productId), 
                  		EntityCondition.makeCondition("statusId", EntityOperator.IN, 
      				UtilMisc.toList("ORDER_COMPLETED", "ORDER_APPROVED", "ORDER_HELD")), 
              		EntityCondition.makeCondition("orderTypeId", EntityOperator.EQUALS, "SALES_ORDER"), 
                 		EntityCondition.makeCondition("orderDate", EntityOperator.GREATER_THAN_EQUAL_TO, checkTime) 
      		), 
      		EntityOperator.AND),
      	null, 
      	null, 
      	null, 
      	null 
      ); 
      在程序中手动创建实体,对其进行查询。

  3. 实体定义 
    • 命名规则 
      实体名称(entity-name)首字母大写,如果实体名称由多个关键字组成,那么关键字首字母大写,例如entity-name="TenantDataSource",ofbiz 会在创建数据库表的时候根据entity-name 实体名称除首字母之外的大写字母前加“_”,所以entity-name="TenantDataSource"生成的数据库表名为 “Tenant_Data_Source”. 
      所以要控制entity-name 实体名称不要超过25个字母。 
      Field 表字段,命名规则与实体名称差不多,唯一不同的是首字母小写。 

    • 实体与数据库的关联 
      <entity-group group="org.ofbiz.olap" entity="SalesInvoiceItemFact"/> 
      <entity-group group="org.ofbiz.olap" entity="SalesInvoiceItemStarSchema"/> 
      Entity-group(一般定义在各个模块的\entitydef\entitygroupXXX.xml中) 对实体进行分组,使不同的实体分属不同的entity-group。 
      也许你会发现并不是每个entity都进行了entity-group 分组。事实上如果你没有对实体进行分组归类的话,系统启动的时候他会将实体默认归类到"org.ofbiz"中。 
      查看数据库定义文件%ofbiz_home%/framework/entity/config/entityengine.xml 
      可以发现: 
      <delegator name="default" 
                 entity-model-reader="main" 
                 entity-group-reader="main" 
                 entity-eca-reader="main" >
                 distributed-cache-clear-enabled="false"> 
              <group-map group-name="org.ofbiz" datasource-name="localderby"/> 
              <group-map group-name="org.ofbiz.olap" datasource-name="localderbyolap"/> 
              <group-map group-name="org.ofbiz.tenant" datasource-name="localderbytenant"/> 
      </delegator> 
      可以发现delegator 将多个group-name组织到一起并将group-name与datasource-name对应起来,datasource-name又是什么?通过查看 entityengine.xml 我们可以发现: 
      <datasource name="localderby" 
                  helper-class="org.ofbiz.entity.datasource.GenericHelperDAO" 
                  schema-name="OFBIZ" 
                  field-type-name="derby" 
                  check-on-start="true" 
                  add-missing-on-start="true" 
                  use-pk-constraint-names="false" 
                  use-indices-unique="false" 
                  alias-view-columns="false" 
                  use-order-by-nulls="true"> 
              <read-data reader-name="seed"/> 
              <read-data reader-name="seed-initial"/> 
              <read-data reader-name="demo"/> 
              <read-data reader-name="ext"/> 
              <inline-jdbc 
                      jdbc-driver="org.apache.derby.jdbc.EmbeddedDriver" 
                      jdbc-uri="jdbc:derby:ofbiz;create=true" 
                      jdbc-username="ofbiz" 
                      jdbc-password="ofbiz" 
                      isolation-level="ReadCommitted" 
                      pool-minsize="2" 
                      pool-maxsize="250" 
                      time-between-eviction-runs-millis="600000"/> 
      </datasource> 
      datasource定义了数据库驱动,数据库用户名、密码等,所以datasource就是我们说的数据库。 
      总结一下:我们通过entity-group将各个实体和数据库之间关联起来,然后再将一个或多个数据库归属到一个delegator 中,那我们又是怎么使用数据库进行数据库操作的呢??查看每个模块应用底下的web.xml 我们可以发现:
      <context-param> 
              <param-name>entityDelegatorName</param-name> 
              <param-value>default</param-value> 
              <description>The Name of the Entity Delegator to use, defined in entityengine.xml</description> 
      </context-param> 
      针对不同的应用,我们可以使用不同的delegator .如果不定义则使用default. 
      在启动各个应用模块的时候,系统会根据web.xml 中的 entityDelegatorName 生成delegator 对象,然后将delegator 对象存放到servletContext 中备用。 
      我们就是使用这个delegator对象执行数据库操作,以后会介绍如何使用。 
      delegator = DelegatorFactory.getDelegator(delegatorName); 
      servletContext.setAttribute("delegator", delegator); 

    • no-auto-stamp 
      no-auto-stamp="false" 
      entity 属性之一: 将此值设置为true , 则创建数据库表时将来不创建lastUpdatedStamp、lastUpdatedTxStamp、createdStamp、createdTxStamp 这四个字段。 

    • Field.type 
      <field name="tenantId" type="id-ne"/> 
      Type , 将数据字段类型 与 java 类型关联起来的设置。 定义文件路径为: 
      %ofbiz_home%\framework\entity\fieldtype\fieldtypeXXX.xml 其中XXX为你使用的数据库名称。 
      <field-type-def type="email" sql-type="VARCHAR(255)" java-type="String"/> 

    • prim-key 
      <prim-key field="agreementId"/> 
      定义主键,其中field 需要是已经被定义过的字段,即field 定义过。 
      实体支持组合主键,即一个实体定义中可以有多个prim-key节点。 
      如果不定义主键的话,数据库是不会创建表的。 

    • relation
      relation 定义当前实体和其他实体之间的关系,一般用做创建外键和根据关系查询使用。 
      :rel-entity-name:被关联实体名称。 
      :fk-name:如果创建外键,那么定义外键的名称。 
      :title:给当前关系起个别名。 
       : field-name:当前实体的字段,指明当前实体的哪个字段与被关系实体有关系。 
      :rel-entity-name:被关系实体名称 
      :rel-field-name:被关系的实体的字段名称。指明field-name和被关系实体的哪个字段有关系。如果rel-field-name与field-name相同,那么rel-field-name可以不定义。 
      :type="one-nofk":关联类型,主要有三类 “one”、”one-nofk”、”many” 
      很多资料上将one 解释为 one-to-one ,将 many 解释为 one-to-many . 
      个人感觉不是很好理解,如果从数据库方面去理解的话,one、one-nofk  的使用条件是被关系实体的rel-field-name为主键,而many 的使用条件是被关系实体的rel-field-name为非主键。而one 与 one-nofk 的区别在于one会在数据库表结构中创建外键约束,而one-nofk 则不会。 
      relation 除了用来创建外键约束之外还被用来做关系查询。 
      当访问关系的时候可以用 .getRelated("") 或者 .getRelatedOne("") 。用 title+entityName 作为参数。 
      当实体一个"many"关系的时候使用getRelated 返回一个列表,当实体一个"one"关系的时候使用getRelatedOne 返回一个实体对象。 
       
    • index
      <index name="WEFF_KWD_KWD" unique="false"> 
      	<index-field name="keyword" function="lower"/> 
      </index> 
      创建索引。
      : name 给索引起个别名。
      : unique 是否唯一索引。
      : index-field
      : name 对实体哪个字段创建索引
      : function 待确定。 

  4. 定义视图实体 
    • member-entity 
      <member-entity entity-alias="EMPPOS" entity-name="EmplPosition"/> 
      <member-entity entity-alias="EMPPOSFUL" entity-name="EmplPositionFulfillment"/> 
      member-entity首先定义当前视图实体可能会用到的实体。
      entity-name实体名称 
      entity-alias实体别名。
      实体定义顺序很重要,除了第一个实体之外其他都是被关联实体。 

    • alias
      <alias entity-alias="EMPPOSFUL" name="partyId" field="partyId"/> 
      	<alias entity-alias="EMPPOSFUL" name="emplPositionId" function="count"/> 
      	<alias entity-alias="EMPPOSREPST" name="emplPositionIdReportingTo" group-by="true"/> 
      alias 定义当前视图实体中会用到的字段。
      entity-alias为实体别名,指当前字段是哪个实体的,
      field实体字段名称,name字段别名。
      group-by依据当前字段进行group-by 分组查询
      function对当前字段执行function 函数处理 。 
       
    • alias-all 
      <alias-all entity-alias="ODD" prefix="orderDate" group-by="true"> 
      <exclude field="dimensionId"/> 
      </alias-all> 
      alias-all 将某个实体的全部字段定义进来。Prefix定义以规定字段字符开头的字段。 
      exclude 将实体中某些字段剔除出去。 

    • view-link 
      <view-link entity-alias="SOIF" rel-entity-alias="ODD" rel-optional="false"> 
      <key-map field-name="orderDateDimId" rel-field-name="dimensionId"/> 
      </view-link>
      视图实体中relation 只能用来做关系查询。 
      而view-link 用来做 join 关联查询
      在entityengine.xml中<datasource ..>元素当中的join-style属性当中设置你的数据库join语法。 
      : rel-optional:关联类型,默认是内连接,如果将此属性值设为true ,则为外连接 

    • entity-condition 
      <entity-condition> 
           <order-by field-name="sequenceId"/> 
      </entity-condition> 
      待定

    • 复杂字段 
      <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> 
      结果为
      SELECT (SUM(COALESCE(OI.QUANTITY,'0')) - SUM(COALESCE(OI.CANCEL_QUANTITY,'0')))


  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值