|
由于JBoss是遵守Sun公司J2EE规范的产品,所以JBoss支持J2EE标准中的EJB-QL查询语言。EJB-QL查询语言写在ejb-jar.xml中。除此以外,JBoss还支持JBossQL语言、DynamicQL语言和DeclaredSQL语言,这3种语言是JBoss为补充EJB-QL的功能而提供的,这些语言写在jbosscmp-jdbc.xml中。
EJB标准为了实现CMP组件中的查找方法(Finder)和选择方法(Select)而建立了EJB查询语言。最新的EJB 2.0规范以92版结构化查询语言(SQL-92)为参考,定义了EJB规范中标准的查询语言,即EJB-QL。EJB-QL统一了J2EE服务器产品的CMP方法,使不同J2EE服务器产品内的CMP组件可以统一起来,成为通用组件,从而提高了EJB组件的可移植性。
另外,EJB 2.0规范在CMP类型实体Bean组件的标准定义中新增了容器管理关系字段(Container-Managed Relationship,简称CMR),CMR用于表示实体组件所代表的数据库记录之间的对应关系。
1.EJB QL查询语言的通用语法规则
SELECT [DISTINCT] OBJECT(变量) FROM abstract-schema-name [AS] 变量
[WHERE value comparison value]
上述查询语句包括三部分子句:SELECT, FROM和WHERE。
SELECT子句定义了该EJB QL查询语句执行的操作类型,并且能够声明查询语句返回对象的数据类型;FROM子句定义了EJB QL语句的对象查询范围;WHERE子句是查询语句的可选项,用于标识查询语句返回被查询对象的条件。
2.SELECT子句
SELECT子句定义EJB-QL语句要执行的操作类型,并且通过该子句定义了返回对象的类型。例如:
<ejb-ql>select object(g) from node g where g.title =?1</ejb-ql>
注:这里的?1是指输入的第一个参数值。
在这语句中,如果在SELECT关键字后附加"DISTINCT"标识,则查询语句将返回EJB容器中具有惟一类型标识的node对象实例。
3.FROM子句
FROM子句通过XML部署描述文件中abstract-schema-name标识或ejb-name标识中的内容来定义查询语句所查询的对象范围。查询对象的范围可以用一种类型对象来确定,如前面第一个查询语句中的"node g"字符串。
4.WHERE子句
WHERE子句通常由条件表达式构成,用于确定查询语句返回对象的条件。例如上面语句中的“where g.title =?1”部分,用于判断对象的title属性值是否与查询值一致。
本书简单地介绍了EJB-QL的语法,如果你想深入了解EJB-QL,可以参看Sun的J2EE标准文档。
JBossQL是JBoss实现的一种查询语言,作为对EJB-QL的有力补充。JBossQL的语句结构如下:
JBossQL := SELECT子句 FROM子句[WHERE子句] [ORDER BY子句]
JBossQL由SELECT子句、FROM子句、可选的WHERE子句和ORDER BY子句组成。其中SELECT子句、FROM子句和WHERE子句与EJB-QL相近,ORDER BY子句为CMP增加了排序功能。
在JBossQL中,还可以使用IN, LIKE关键字,也可以套用一些内建函数,包括UCASE, LCASE, CONCAT和SUBSTRING。
JBossQL的使用示例:
<jboss-ql>SELECT OBJECT(g) FROM node g WHERE g.id > ?1 ORDER BY g.id</jboss-ql>
例如将前面NodeBean的findAll方法用JBoss-QL来完成:
<query>
<query-method>
<method-name>findAll</method-name>
<method-params/>
</query-method>
<jboss-ql><![CDATA[SELECT OBJECT(g) FROM node g]]></jboss-ql>
</query>
DeclaredSQL是JBoss支持的另外一种查询语言,这种语言的查询功能主要通过WHERE语句来实现,并且支持SELECT子句和FROM子句。
例如将前面NodeBean的findByTitle方法用DeclaredSQL来完成:
<query>
<description/>
<query-method>
<method-name>findByTitle</method-name>
<method-params>
<method-param>java.lang.String</method-param>
</method-params>
</query-method>
<declared-sql>
<where><![CDATA[ title = {0}]]></where>
</declared-sql>
</query>
DeclaredSQL保持了XML的结构,所实现的查询功能是对EJB-QL的补充。
JBoss还支持DynamicQL方式和类似于BMP的查询方式。DynamicQL需要用户自己分析输入的参数,根据情况可以动态生成查询语句,其声明方式如下:
<query>
<query-method>
<method-name>ejbSelectTitle</method-name>
<method-params>
<method-param>java.lang.String</method-param>
<method-param>java.lang.Object[]</method-param>
</method-params>
</query-method>
<dynamic-ql/>
</query>
JBoss的CMP引擎实现了EJB 2.0的CMP规范中的内容。对于BMP类型实体Bean,本章会在后面的小节中介绍。在这里使用CMP的配置文件可以借助JBoss CMP引擎来生成查询方法,但是如果在CMP的实现类中添加类似BMP那样的查询方法,也会被JBoss调用。
3.2.10 CMP在JBoss中的描述
从前面的介绍中可以看到,JBoss除了EJB标准中规定的内容外,对于CMP的实现还有一些特殊的支持,这些内容是JBoss所特有的,开发者通过在jbosscmp-jdbc.xml中添加适当的描述,就可以利用JBoss所提供的针对CMP类型实体Bean的特殊支持。
下面的内容详细介绍了在JBoss中描述CMP类型实体Bean的jbosscmp-jdbc.xml文件部分。
<jbosscmp-jdbc>作为CMP描述的起始标记</bosscmp-jdbc>
CMP描述主要包括:默认部分、值对象类声明、EJB声明、关系描述、数据类型映射、用户数据类型映射和其他部分。
<jbosscmp-jdbc>
<defaults> 默认部分
<dependent-value-classes> 值对象类声明
<enterprise-beans> EJB声明
<relationships> 关系描述
<type-mappings> 数据类型映射
<user-type-mapping> 用户数据类型映射
<reserved-words> 保留字声明
</jbosscmp-jdbc>
1.默认设置
<defaults>作为默认设置描述的起始标记</defaults >
<create-table>设置CMP在创建时如果对应的数据库表不存在,是否需要服务器创建这个数据表,可以选择true或者false</create-table>
<remove-table>设置CMP在结束时是否需要服务器删除对应的数据表,可以选择true或者false</remove-table>
<datasource>设定数据资源的JNDI名称</datasource>
<datasource-mapping>设定数据库资源的映射名称</datasource-mapping>
<entity-command name =“” class = “”>通过属性来设定实体命令</entity-command>
<fetch-size>一次性读取的实体数量</fetch-size>
<fk-constraint>外键是否被添加到关系角色中,可以选择true或者false </fk-constraint>
<list-cache-max,>设定查询缓冲的最大值</list-cache-max,>
<pk-constraint>创建数据表时是否增加主键,可以选择true或者false</pk- constraint>
<post-table-create> 数据库表创建时执行的SQL语句
<sql-statement>每个sql-statement代表一条SQL语句</sql-statement>
</post-table-create>
<preferred-relation-mapping>首选的关系映射方式,可以选择foreign-key和relation-table </preferred-relation-mapping>
<read-ahead>
<deep-read-ahead>设置将关系添加到预读的内容中</deep-read-ahead>
<eager-load-group>设置优先预读的字段组</eager-load-group>
<page-size>设置一次预读的实体数量</page-size>
<strategy>设置预读策略,可以选择none, on-load或者on-find</strategy>
</read-ahead>
<read-only>设置只读属性,可以选择true或者false </read-only>
<read-time-out>当一个只读字段被执行方法时的超时设定</read-time-out>
<row-locking>是否锁定行选择,可以选择true或者false </row-locking>
<unknown-pk>
<auto-increment>设定自动增加</auto-increment>
<column-name>设定列名</column-name>
<field-name>设定字段名</field-name>
<jdbc-type>设定JDBC类型,如VARCHAR</jdbc-type>
<key-generator-factory> </key-generator-factory>
<read-only>设置只读属性,可以选择true或者false </read-only>
<read-time-out>当一个只读字段被执行方法时的超时设定</read-time-out>
<sql-type>设定数据库的SQL类型,如VARCHAR(32) </sql-type>
<unknown-pk-class>设定主键类型,如java.lang.String </unknown-pk-class>
</unknown-pk>
2.值对象类声明
<dependent-value-classes>作为值对象类部分描述的起始标记</dependent-value- classes>
<description>关于这个值对象类的描述</description>
<class>值对象类对应的类名</class>
<property>值对象类通常包含不止一个属性
<column-name>包含对应字段的列名</column-name>
<jdbc-type>设定JDBC类型,如VARCHAR </jdbc-type>
<not-null>设定此处字段不为空</not-null>
<property-name>属性名</property-name>
<sql-type>设定数据库的SQL类型,如VARCHAR(32) </sql-type>
</property>
3.EJB声明
<enterprise-beans>作为CMP描述中EJB声明的起始标记</enterprise-beans>
EJB声明中可以包含若干个entity子元素,每个entity代表一个实体Bean
实体Bean声明中最关键的描述是:ejb-name, table-name, query和cmp-field。
<entity>作为实体Bean声明的起始标记</entity>
<ejb-name>设置EJB的名称</ejb-name>
<table-name>设置对应数据表的名称</table-name>
4.EJB查询
<query>一个query代表一个查询方法
<description>查询方法的描述</description>
<query-method>
<method-name>查询方法的名称</method-name>
<method-params>
<method-param>查询方法的参数类型全称,可以有多个</method-param>
</method-params>
</query-method>
<jboss-ql>JBoss特有的查询语句</jboss-ql>
<declared-sql>JBoss特有的查询语句,使用下面5个子元素来描述查询
<from>from子句</from>
<order> order子句</order>
<select> select子句</select>
<where> where子句</where>
<other>写在Declared-SQl中的其他语句</other>
</declared-sql>
<dynamic-ql>代表JBoss实现的另一种查询方式,在这种方式中,查询的方法参数将被传递给实现方法</dynamic-ql>
<read-ahead>
<deep-read-ahead>设置将关系添加到预读的内容中</deep-read-ahead>
<eager-load-group>设置优先预读的字段组</eager-load-group>
<page-size>设置一次预读的实体数量</page-size>
<strategy>设置预读策略,可以选择none, on-load或者on-find</strategy>
</read-ahead>
</query>
5.CMP的数据字段
<cmp-field>
<auto-increment>设定自动增加</auto-increment>
<check-dirty-after-get>字段返回后检查状态,可以选择true或者false </check-dirty- after-get>
<column-name>设定列名</column-name>
<field-name>设定字段名</field-name>
<dbindex>设置服务器为字段数据创建一个索引表</dbindex>
<jdbc-type>设定JDBC类型,如VARCHAR </jdbc-type>
<not-null>设定此处字段不为空</not-null>
<sql-type>设定数据库的SQL类型,如VARCHAR(32) </sql-type>
<property>
<column-name>包含对应字段的列名</column-name>
<jdbc-type>设定JDBC类型,如VARCHAR </jdbc-type>
<not-null>设定此处字段不为空</not-null>
<property-name>属性名</property-name>
<sql-type>设定数据库的SQL类型,如VARCHAR(32) </sql-type>
</property>
<read-only>设置只读属性,可以选择true或者false </read-only>
<read-time-out>当一个只读字段被执行方法时的超时设定</read-time-out>
<state-factory>设置状态工厂类的全称</state-factory>
</cmp-field>
<create-table>设置CMP在创建时如果对应的数据库表不存在,是否需要服务器创建这个数据表,可以选择true或者false</create-table>
<remove-table>设置CMP在结束时是否需要服务器删除对应的数据表,可以选择true或者false</remove-table>
<datasource>设定数据资源的JNDI名称</datasource>
<datasource-mapping>设定数据库资源的映射名称</datasource-mapping>
<eager-load-group>设置优先预读的字段组</eager-load-group>
<entity-command name =“” class = “”>通过属性来设定实体命令</entity-command>
<fetch-size>一次性读取的实体数量</fetch-size>
<lazy-load-groups>设置查询时不被先加载的字段组</lazy-load-groups>
<list-cache-max,>设定查询缓冲的最大值</list-cache-max,>
<load-groups>包含多个load-group
<load-group>有些字段通常会一起被读取,此时可以将它们设为一个组
<description>描述信息</description>
<field-name>这个组中的一个字段,一个组里可以有多个字段</field-name>
<load-group-name>这个组的名称</load-group-name>
</load-group>
</load-groups>
<optimistic-locking/>
<pk-constraint>创建数据表时是否增加主键,可以选择true或者false</pk- constraint>
<post-table-create>数据库表创建时执行的SQL语句
<sql-statement>每个sql-statement代表一条SQL语句</sql-statement>
</post-table-create>
<read-ahead>
<deep-read-ahead>设置将关系添加到预读的内容中</deep-read-ahead>
<eager-load-group>设置优先预读的字段组</eager-load-group>
<page-size>设置一次预读的实体数量</page-size>
<strategy>设置预读策略,可以选择none, on-load或者on-find</strategy>
</read-ahead>
<read-only>设置只读属性,可以选择true或者false </read-only>
<read-time-out>当一个只读字段被执行方法时的超时设定</read-time-out>
<row-locking>是否锁定行选择,可以选择true或者false </row-locking>
<unknown-pk>
<auto-increment>设定自动增加</auto-increment>
<column-name>设定列名</column-name>
<field-name>设定字段名</field-name>
<jdbc-type>设定JDBC类型,如VARCHAR</jdbc-type>
<key-generator-factory></key-generator-factory>
<read-only>设置只读属性,可以选择true或者false </read-only>
<read-time-out>当一个只读字段被执行方法时的超时设定</read-time-out>
<sql-type>设定数据库的SQL类型,如VARCHAR(32) </sql-type>
<unknown-pk-class>设定主键类型,如java.lang.String </unknown-pk-class>
</unknown-pk>
<audit>记录一些统计信息</audit>
6.关系描述
<relationships>作为关系描述的起始标记</relationships>
每个relationships中包含若干个关系描述ejb-relation,具体如下:
<ejb-relation>
<ejb-relation-name>关系的名称</ejb-relation-name>
<table-name>设置对应数据表的名称</table-name>
<read-only>设置只读属性,可以选择true或者false </read-only>
<read-time-out>当一个只读字段被执行方法时的超时设定</read-time-out>
<foreign-key-mapping>映射的外键</foreign-key-mapping>
<relation-table-mapping>
<create-table>设置CMP在创建时如果对应的数据库表不存在,是否需要服务器创建这个数据表,可以选择true或者false</create-table>
<remove-table>设置CMP在结束时是否需要服务器删除对应的数据表,可以选择true或者false
</remove-table>
<datasource>设定数据资源的JNDI名称</datasource>
<datasource-mapping>设定数据库资源的映射名称</datasource-mapping>
<pk-constraint>创建数据表时是否增加主键,可以选择true或者false</pk- constraint>
<post-table-create>数据库表创建时执行的SQL语句
<sql-statement>每个sql-statement代表一条SQL语句</sql-statement>
</post-table-create>
<row-locking>是否锁定行选择,可以选择true或者false </row-locking>
</relation-table-mapping>
<ejb-relationship-role>
<ejb-relationship-role-name>关系角色名称,如book-has-page</ejb-relationship- role-name>
</ejb-relationship-role>
</ejb-relation>
7.数据类型映射表
数据类型映射表的作用是建立Java数据、JDBC数据和SQL数据之间的映射关系。
<type-mappings>作为数据类型映射的起始标记</type-mappings>
一个type-mappings中包含多个type-mapping子元素,每个type-mapping代表一个映射关系。
<type-mapping>
<name>类型映射序列的名称</name>
<mapping>一个数据类型映射表中包含多个mapping
<java-type>Java数据类型,如java.lang.Byte</java-type>
<jdbc-type>设定JDBC类型,如VARCHAR </jdbc-type>
<sql-type>设定数据库的SQL类型,如VARCHAR(32) </sql-type>
</mapping>
<alias-header-prefix>别名的前缀</alias-header-prefix>
<alias-header-suffix>别名的后缀</alias-header-suffix>
<alias-max-length>别名的最大长度</alias-max-length>
<auto-increment-template>定义自动增长的模板</auto-increment-template>
<true-mapping>true值的映射值,例如1</true-mapping>
<false-mapping>false值的映射值,例如0</false-mapping>
<fk-constraint-template>创建外键的模板,例如ALTER TABLE ?1 ADDCONSTRA INT ?2 FOREIGN KEY (?3) REFERENCES ?4 (?5)
</fk-constraint-template>
<function-mapping>查询函数映射
<function-name>查询函数名称</function-name>
<function-sql>查询函数对应的SQL语句</function-sql>
</function-mapping>
<pk-constraint-template>定义创建主键的模板</pk-constraint-template>
<row-locking-template>定义行锁定的模板</row-locking-template>
<subquery-supported>设定是否支持subquery功能</subquery-supported>
</type-mapping>
8.用户数据类型映射
<user-type-mappings>作为用户数据类型映射的起始标记</user-type-mappings>
user-type-mappings可以包含若干个user-type-mapping,每个user-type-mapping代表一个用户数据类型的映射。
<user-type-mapping>
<java-type>作为数据类型的Java类,需要全名</java-type>
<mapped-type>映射的类型</mapped-type>
<mapper>对应实现的映射类</mapper>
</user-type-mapping>
9.其他内容
<reserved-words>保留字列表
<word>代表一个保留字,保留字在JBoss中不能用来描述数据表</word>
<reserved-words>
<entity-command name =“” class = “”>通过属性来设定实体命令</entity-command> |