使用標(biāo)注進(jìn)行配置
標(biāo)注現(xiàn)在已經(jīng)很流行了,許多人選擇它作為XML的替代來進(jìn)行元數(shù)據(jù)編程。標(biāo)注中不應(yīng)該包含配置信息,而iBATIS通過XML來進(jìn)行的工作也不光是配置。
那么什么是配置,什么又不是呢?目前,iBATIS的XML文件包含了三方面:
當(dāng)您把環(huán)境設(shè)置改變后,您同時也需要更改配置,例如數(shù)據(jù)庫連接配置、事務(wù)管理配置等等。當(dāng)您將應(yīng)用分發(fā)到不同的數(shù)據(jù)庫,而且也使用了一些專有的SQL語句后,配置中可能還要包含SQL方言的一些配置信息。在iBATIS 3.0中我們可以將這些信息包含進(jìn)去,因此,您需要針對多種方言進(jìn)行編碼(當(dāng)然這是手工的),為它們命名,并將它們配置到適當(dāng)?shù)奈恢谩E渲眯畔⒉粦?yīng)該被包含在Java源文件中。
元數(shù)據(jù)信息包括諸如結(jié)果映射、參數(shù)映射和緩存模型之類的信息。這些信息控制iBATIS如何映射您的數(shù)據(jù)以及這些映射的具體表現(xiàn)。
編碼包括SQL以及動態(tài)的SQL語句。
那么標(biāo)注應(yīng)該承擔(dān)什么樣的職責(zé)呢?
一般情況下,只有元數(shù)據(jù)信息比較適合使用標(biāo)注來描述。配置應(yīng)該通過屬性文件或者XML文件來實現(xiàn)。編碼也只能通過Java文件或者XML文件來實現(xiàn)。更進(jìn)一步看,標(biāo)注只能用來描述相對較簡單的元數(shù)據(jù)信息。有時,標(biāo)注(特別是在Java中)也會使事情變得更加復(fù)雜,使代碼更加晦澀難懂。
因為上面的原因,所以我推薦只將標(biāo)注作為約定配置的替代配置。這就是說,使用這種配置方式可以達(dá)到一定的效果,但是也僅僅限于此。
再一次強(qiáng)調(diào),C#的Attribute在某些方面要強(qiáng)于Java的標(biāo)注:
- 支持多行字符串,這使得內(nèi)嵌SQL編碼令人感到愉快
- 支持使用同一標(biāo)注多次,而在Java中則需要通過集合標(biāo)注來實現(xiàn)
- 支持順序和命名參數(shù),這使得代碼變得更加簡明扼要
下面這個例子展示了如何使用Java中的標(biāo)注來完成配置:
//
// Simple select, string concatenation, inline results(!) and inline parameters
//
@Select("SELECT #id(EMP_ID:NUMERIC), #firstName(FIRST_NAME:VARCHAR), #lastName(LAST_NAME:VARCHAR) " +
"FROM EMPLOYEE")
List selectAllEmployees();
//
// Alternative syntax using an array of strings instead of string concatenation...can be "smarter" than concatenation
//
@Select({"SELECT #id(EMP_ID:NUMERIC), #firstName(FIRST_NAME:VARCHAR), #lastName(LAST_NAME:VARCHAR) ",
"FROM EMPLOYEE",
"WHERE EMP_ID = @id"})
Employee selectEmployee(int id);
//
// Inserts look as you might expect. We can use getGeneratedKeys to get autogen key values, selectkey still supported
//
@Insert({"INSERT INTO EMPLOYEE (EMP_ID, FIRST_NAME, LAST_NAME)",
"VALUES (@id, @firstName, @lastName)"})
void insertEmployee(Employee emp);
//
// Nothing special about update
//
@Update({"UPDATE EMPLOYEE SET",
"EMP_ID=@id(NUMERIC:IN), FIRST_NAME=@firstName(VARCHAR:IN), LAST_NAME=@lastName(VARCHAR:IN)"})
void updateEmployee(Employee emp);
//
// Delete is obvious.
//
@Delete("DELETE EMPLOYEE WHERE EMP_ID = @id")
void deleteEmployee(int id);
下面這個例子要更加復(fù)雜一些,像這種使用了如此多的標(biāo)注的情況就應(yīng)該考慮使用XML文件來進(jìn)行配置。這種情況下,我想象標(biāo)注能夠提供一切功能,即XML中實現(xiàn)的功能通過標(biāo)注也能完成。然而,我們還是建議您在面對復(fù)雜的情況時使用XML來進(jìn)行配置。或許某些人不是特別在意使用XML配置,所以我們?yōu)樗麄兲峁┝藰?biāo)注配置方式。
//
// complex stuff
//
@ResultClass (Company.class)
@ConstructorResults({
@Result(property="id", column="C.COMP_ID"),
@Result(property="name", column="C.NAME")
})
@PropertyResults({
@Result(property="departments.id", column="D.DEPT_ID"),
@Result(property="departments.name", column="D.NAME"),
@Result(property="departments.employee.id", column="E.EMP_ID"),
@Result(property="departments.employee.firstName", column="E.FIRST_NAME"),
@Result(property="departments.employee.lastName", column="E.LAST_NAME")
})
@Collections ({
@Collection(type=Department.class, property="departments", groupBy="id"),
@Collection(type=Employee.class, property="departments.employees", groupBy="departments.id")
})
@Select("SELECT #id, #name, " +
"#departments.id, #departments.name, " +
"#departments.employees.id, #departments.employees.firstName, " +
"#departments.employees.lastName " +
"FROM COMPANY C, DEPARTMENT D, EMPLOYEE E " +
"WHERE D.DEPT_ID = E.DEPT_ID " +
"AND C.COMP_ID = D.COMP_ID")
List selectAllCompaniesWithJoin();
/*
* NESTED QUERIES
*/
@ResultClass (Company.class)
@FieldResults({
@Result(property="id", column="COMP_ID"),
@Result(property="name", column="NAME")
})
@PropertyResults({
@Result(property="departments",
nestedQuery=@QueryMethod(type=CompanyMapper.class, methodName="getDepartmentsForCompany", parameters="id"))
})
@Select("SELECT #id, #name FROM COMPANY C ")
List selectAllCompaniesWithNestedQueries();
@ResultClass (Department.class)
@PropertyResults({
@Result(property="id", column="DEPT_ID"),
@Result(property="name", column="NAME"),
@Result(property="employees",
nestedQuery=@QueryMethod(type=CompanyMapper.class, methodName="getEmployeesForDeparment", parameters="id"))
})
@Select("SELECT #id, #name FROM DEPARTMENT WHERE COMP_ID = @id ")
List getDepartmentsForCompany(int id);
@ResultClass (Employee.class)
@PropertyResults({
@Result(property="id", column="EMP_ID"),
@Result(property="firstName", column="FIRST_NAME"),
@Result(property="lastName", column="LAST_NAME")
})
@Select("SELECT #id, #firstName, #lastName FROM EMPLOYEE WHERE EMP_ID = @id ")
List getEmployeesForDepartment(int id);