天天看點

ofbiz entity.tags

OFBIZ ENTITY ENGINE COOKBOOK

============================

OFBIZ ENTITY ENGINE 菜單

* Keep your entity names less than 25 characters

  Oracle, for example, does not like tables with names longer than 30 characters, and OFBIZ

will add a "_" between words, so it's best to keep them short.

* 保證讓你的entity names在25個字元以内

  因為有些資料庫不允許表名超過30個字元,例如Oracle.而且ofbiz還要在單詞之間加入"_",是以盡可能的讓實體名稱短。

* How relationships work

  如何建立關系

  They are defined in entitymodel.xml files for an <entity> like this:

  關系是在entitymodel.xml檔案當中<entity>标簽定義的,例如:

      <relation type="one" fk-name="PROD_CTGRY_PARENT" title="PrimaryParent" rel-entity-name="ProductCategory">

      <key-map field-name="primaryParentCategoryId" rel-field-name="productCategoryId"/>

      </relation>

      <relation type="many" title="PrimaryChild" rel-entity-name="ProductCategory">

        <key-map field-name="productCategoryId" rel-field-name="primaryParentCategoryId"/>

      </relation>

  type= defines the type of the relationship: "one" for one-to-one or "many" for

one-to-many from this entity

  type=定義了一個關系類型,從這個實體看來"one" 是one-to-one 或者"many"是one-to-many

  fk-name= is a foreign key name.  It is usually good practice to set your own foreign key name, although OFBIZ will auto-generate if it's not there.

  fk-name是一個外鍵名稱,最佳實踐政策是自己在這裡定義外鍵名稱,雖然如果這裡不寫OFBIZ會自動生成一個

  rel-entity-name= is the name of the related entity.

  rel-entity-name是被關聯實體名稱

  title= is used to distinguish different relationships when there are many relationships between the same two entities.

  title是用來在兩個實體之間存在多種關系的時候用來區分不同關系的名稱

  <key-map> defines the fields for the relationship. field-name= is for the field of this entity to use.  If the field on the related entity

  has a different field name, then rel-field-name= defines the field name in the related entity.  You can have many fields serve as part of a key-map.

  <key-map> 為關系定義了字段

  field-name是本實體用到的字段,如果在被關聯實體當中使用不同的字段名,那麼用rel-field-name定義被關聯實體當中的字段名,一個key-map元素可以有多個字段名.

When you access a relationship, you would use .getRelated("") or .getRelatedOne("") with the title+entityName as parameter.  getRelated returns a List and is appropriate when it is a "many" relation.  .getRelatedOne returns a single GenericVaue and is appropriate for "one" relations.

當通路關系的時候可以用 .getRelated("") 或者 .getRelatedOne("") 用 title+entityName 作為參數。

當實體一個"many"關系的時候使用getRelated 傳回一個清單,當實體一個"one"關系的時候使用getRelatedOne 傳回一個GenericVaue .

* A few things about view-entities

關于view-entities的一些說明

View-entities are very powerful and allow you to create join-like queries, even when your database doesn't support joins.

view-entities是非常有用的并且允許你建立join-like查詢,甚至你的資料庫不支援joins都可以

The configuration of your database's join syntax is in entityengine.xml under the join-style attribute of <datasource ..>

在entityengine.xml中<datasource ..>元素當中的join-style屬性當中設定你的資料庫join文法

When you link two entities together using the <view-link ..> tag, remember

1.  The order of the entities you name is important.

2.  The default is an inner join (values must be present on both sides.)  To do an outer join, use rel-optional="true"

當你将兩個實體連接配接在一起的時候使用 <view-link ..>标簽,記住

1. 實體名稱的順序很重要

2. 預設情況時内連接配接(值必須在兩邊都出現)如果要作一個外連接配接用rel-optional="true"

If several entities have the same field name, such as statusId, the one from the first entity will be used and the rest tossed out.  So if you need the field from one, put its <alias-all> before the others.  Alternatively, use <alias ..> tag

to give the same field from different entities names, such as:

如果幾個實體擁有相同名稱的字段,例如statusId,那麼第一個實體的statusId被使用其它的都會抛棄掉,是以如果需要使用其它實體當中相同名字字段的時候,把它們放入<alias-all>,作為一個選擇用 <alias ..> 标簽

可以區分不同實體當中相同的名字字段,例如:

<alias entity="EntityOne" field="statusId"/>

<alias entity="EntityTwo" field="statusId"/>

Another alternative is to use <exclude field=""> inside an <alias-all> as follows:

另一個選擇就是在 <alias-all>内使用<exclude field="">例如

<alias-all entity-alias="EN">

  <exclude field="fieldNameToExclude1"/>

  <exclude field="fieldNameToExclude2"/>

</alias-all>

This top-down approach is more compact, which comes in handy for large tables.

這種嚴密的寫法更加緊湊,對于字段多的大表用的上。

Alternatively, you can specify one or more <exclude field="fieldName"> inside an  <alias-all>.

更加簡潔的一種寫法是在<alias-all>當中使用<exclude field="fieldName">

 This top-down approach is more compact than specifying the alias for every field in a big

table.

 這樣比一個一個的指定字段的别名方法更加緊湊簡潔。

If you need to do a query like this

如果你需要做一個如下查詢

SELECT count(visitId) FROM ... GROUP BY trackingCodeId WHERE fromDate > ' 2005-01-01'

include field visitId with function="count", trackingCodeId with group-by="true", and

fromDate with group-by="false"

用function="count"包含字段visitId

,用group-by="true"給trackingCodeId,用fromDate給group-by="false"

Then **VERY IMPORTANT** when you do your query, such as delegator.findByCondition, you must specify the fields to select,and you must not specify the field fromDate, or you will get an error.  This is why these view-entities can't be viewed from webtools.

非常非常重要的是當你查詢的時候,例如使用delegator.findByCondition,你必須指定選擇的字段,在上例中

不指定fromDate,你會得到一個錯誤,這也是為什麼view-entities為什麼不能在webtools裡面被看到的一個原因。

For an example, look at the view entities at the bottom of

更多的例子可以參考以下實體

applications/marketing/entitydef/entitymodel.xml and

the BSH scripts in applications/marketing/webapp/marketing/WEB-INF/actions/reports.

* How to build conditions for expiration dates

怎樣建立一個根據有效日期的查詢條件

There is a series of very helpful methods called EntityUtil.getFilterByDateExpr which return an EntityConditionList to filter out search results by date.

有一系列非常有用的方法叫 EntityUtil.getFilterByDateExpr 能夠傳回EntityConditionList用于通過日期實體條件。

* How to work with large sets of data

怎樣使用大量的資料

If you need to select large sets of data, you should use the EntityListIterator instead of the List.  For example, if you did

如果你需要選擇大量的資料集合,你可以用EntityListIterator替代List.例如如果你做了

List products = delegator.findAll("Product");

You may get yourself a "java.lang.OutOfMemoryError".  This is because findAll, findByAnd, findByCondition will try to retrieve all the records into memory as a List.  In that case, re-write your query to do return an EntityListIterator  then loop through it.  For example, this query can

be re-written as:

你可能得到一個"java.lang.OutOfMemoryError"異常。這是因為findAll, findByAnd, findByCondition嘗試把所有的符合标準的紀錄加載到記憶體當中,一個解決方案是重新寫你的查詢作為一個EntityListIterator并且周遊它,例如上面的查詢可以寫為

productsELI = delegator.findListIteratorByCondition("Product", new EntityExpr("productId",

EntityOperator.NOT_EQUAL, null), UtilMisc.toList("productId"), null);

Note that the only method for finding an EntityListIterator is a by condition, so you would have to re-write your conditions as EntityExpr (in this case, a dummy one which just says that productId is not null, which should apply to all Product entities,

since productId is a not-null primary key field) or EntityConditionList. This method also asks you to fill in the fields to select (in this case just productId) and order by (which I didn't specify with the last null.)

注意這是唯一的一個通過條件得到一個EntityListIterator的方法,你必須用EntityExpr(這個例子當中表示為productId 不能為 null,其實是一句廢話,就是說明所有紀錄)或EntityConditionList者重寫你的條件 。這個方法也要求指定所有要選擇的字段(這個例子裡面隻有productId) 并且order by(在給出的例子當中沒有指定,位置位于最有一個null參數)

You can pass a null EntityCondition to grab all records.  However, this does not work across all databases!  Beware the use of avanced functionality such as the EntityListIterator with maxdb and other odd databases.

你可以通過一個空的EntityCondition 抓取所有紀錄,然而這種做法并不支援所有的資料庫,對于大型資料庫或者奇怪的資料庫,謹慎的使用進階的函數例如EntityListIterator當中的函數。

* How to use an EntityListIterator

如何使用一個EntityListIterator

When iterating through the EntityListIterator, this is the preferred form:

當周遊EntityListIterator的時候如下的做法是首選的

while ((nextProduct = productsELI.next()) != null) {

....

    // operations on nextProduct

}

Using the .hasNext() method on EntityListIterator is considered wasteful.

在EntityListIterator 當中使用.hasNext()被認為是浪費資源的

When you are done, don't forget to close it:

當你使用EntityListIterator ,不要忘記關閉它

productsELI.close();

* How to do a select distinct

如何得到不重複的紀錄

The only way we know of to do it with the entity engine is to find a list iterator and use

EntityFindOptions to specify it, like this:

據我們所知在 entity engine隻能通過指定EntityFindOptions 得到一個list iterator例如:

    listIt = delegator.findListIteratorByCondition(entityName, findConditions,

            null, // havingEntityConditions

            fieldsToSelectList,

            fieldsToOrderByList, 

            // This is the key part.  The first true here is for "specifyTypeAndConcur"

            // the second true is for a distinct select.  Apparently this is the only way

the entity engine can do a distinct query

            new EntityFindOptions(true, EntityFindOptions.TYPE_SCROLL_INSENSITIVE,

EntityFindOptions.CONCUR_READ_ONLY, true));

In minilang, curiously, it is much easier:

奇怪的是在minilang他非常簡單。

  <entity-condition entity-name="${entityName}" list-name="${resultList}" distinct="true">

     <select field="${fieldName}"/>

     ....

* How to go from EntityListIterator to just List

怎樣從EntityListIterator變為一個純粹的List

  Use the EntityListIterator.getCompleteList() and getPartialList methods

使用EntityListIterator.getCompleteList()和getPartialList方法

* How to get the next ID value automatically

怎樣通過自動增長得到下一個ID

  Use either <sequence-id-to-env ...> in minilang or delegator.getNextSeqId(...) in Java.  The id sequence numbers are stored in an entity SequenceValueItem.

使用在minilang中的<sequence-id-to-env ...> 或者 Java 中的delegator.getNextSeqId(...)這個id序列的數字被存儲在一個SequenceValueItem當中。

* A word of warning about ID values

關于ID值被警告的說明

  DO NOT CREATE SEED OR DEMO DATA WITH ID 10000!  When the system tries to create more values automatically, it will also try to use 10000,

  resulting in a key clash.

  不要用ID 10000建立種子或者例子資料!當系統嘗試穿件自動增長的值時候他會嘗試10000

* How to set up an alias that does the equivalent of SELECT SUM(QUANTITY - CANCEL_QUANTITY) AS QUANTITY

  怎樣設定一個别名類似于SELECT SUM(QUANTITY - CANCEL_QUANTITY) AS QUANTITY這用SQL語句

  <alias entity-alias="OI" 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>

  This results in SELECT SUM(COALESCE(OI.QUANTITY,'0') - COALESCE(0I.CANCEL_QUANTITY)) AS QUANTITY  Including a default-value is a good habit, otherwise the result of the subtraction will be null if any of its fields are null.

  The operator can be any of the supported SQL operations of your database, such as

arithmetic with  +, -, * and / or concatenation of strings with ||.

給這個SELECT SUM(COALESCE(OI.QUANTITY,'0') - COALESCE(0I.CANCEL_QUANTITY)) AS QUANTITY的結果一個預設值是一個良好的習慣,否則當他們之中有一個為空就會導緻結果為空

  這個操作可以支援你使用資料庫的所有函數例如  +, -, * 和 /,字元串連接配接符||。

  You can add a function="" to perform min, max, sum, avg, count, count-distinct, upper and lower

你也可以添加一個 function="" 實作min, max, sum, avg, count, count-distinct, upper 和 lower on the complex-alias-field.  For example, an alternative way to express the query above

is to do:

  對于複雜的别名字段,例如在查詢中的二選一的表達式采用如下做法

  <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>

  Which results in SELECT (SUM(COALESCE(OI.QUANTITY,'0')) - SUM(COALESCE(OI.CANCEL_QUANTITY,'0'))) AS QUANTITY

結果是類似 SELECT (SUM(COALESCE(OI.QUANTITY,'0')) - SUM(COALESCE(OI.CANCEL_QUANTITY,'0'))) AS QUANTITY的查詢結果

原文位址: http://blog.sina.com.cn/s/blog_6a61574d0100nkqe.html