所涉对象
四个持久化对象(User、ServicePrudoct、State、Order),四张表(user、service_product、state、order)。
对象间关系
前三者和Order之间均存在一对多(one-to-many)关系,每个的映射文件中均有一个set配置节;Order和前三者之间均存在多对一(many-to-one)关系,Order的映射文件中存在三个many-to-one配置节。
问题现象
在struts1.3、sprint2.5、hibernate3.2环境下,user、service_product、state表均成功生成,而order表不能生成,提示以下hql语句存在语法错误:
create table order (order_id INT NOT NULL AUTO_INCREMENT , order_date DATE NOT NULL , order_message VARCHAR( 64 ) NOT NULL , order_attachement VARCHAR( 255 ) NOT NULL , user_id INT NOT NULL , service_product_id INT NOT NULL , state_id INT NOT NULL , PRIMARY KEY ( order_id))
分析试验
因为成功生成的表格和其他表格均是独立表格,相互间没有关系,最先怀疑,是多对一或一对多配置有问题,但参考若干成功范例发现,没有什么错误,最后求助于Hibernate3的文档7章“关联关系映射”,将其“7.4.1 双向关联”提供的实例加入同一Project:
双向多对一关联 是最常见的关联关系。(这也是标准的父/子关联关系。)
<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<many-to-one name="address"
column="addressId"
not-null="true"/>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
<set name="people" inverse="true">
<key column="addressId"/>
<one-to-many class="Person"/>
</set>
</class>
没有发现问题,成功生成了表格。
没辙,查不出问题来,继续试验,想这User等三个对象均和Order对象存在关系,我何不先简单化,添加一个Article对象,让它先只和User发生关系,然后再逐个添加另外两个关系,这样试验了一下,发现居然也没有问题,能成功生成表格。此时,还是没有想到问题在哪。最后想,那就把原来的Order对象和映射文件删除,将Article对象和映射文件复制一份,修改成Order对象和映射文件,这样一改,居然又不行了。此时,发现,只改过名称,难道是名称有问题,名称和mysql的关键字冲突?在映射文件里,将Order对象的“table = "order"”改为“table = "tbl_orfer"”一试,果然如此。
总结教训
用Hibernate直接生成数据库,看起来和sql语句没关系了,可一样不能忽视和关键字冲突的问题!!!
另外:在表名前面加前缀“tbl_”是个好习惯!!!
hbm文件
User.hbm.xml
<class name="User" table="user">
<id name="id" type="java.lang.Integer" column="user_id">
<generator class="identity"/>
</id>
<property name="email" column="email" type="java.lang.String" not-null="true" length="128" unique="true"/>
<property name="password" column="password" type="java.lang.String" not-null="true" length="64"/>
<property name="firstName" column="first_name" type="java.lang.String" not-null="true" length="32"/>
<property name="lastName" column="last_name" type="java.lang.String" not-null="false" length="32"/>
<property name="phoneNumber" column="phone_number" type="java.lang.String" not-null="true" length="32"/>
<set name="orders" inverse="true">
<key column="user_id" />
<one-to-many class="Order" />
</set>
</class>
ServiceProduct.hbm.xml
<class name="ServiceProduct" table="tbl_service_product">
<id name="id" type="java.lang.Integer" column="service_product_id">
<generator class="identity"/>
</id>
<property name="serviceProductTitle" column="serviceProductTitle" type="java.lang.String" not-null="false" length="255"/>
<property name="serviceProductDescription" column="serviceProductDescription" type="java.lang.String" not-null="true" length="1024"/>
<property name="serviceProductImagePath" column="serviceProductImagePath" type="java.lang.String" not-null="false" length="255"/>
<property name="serviceProductPrice" column="serviceProductPrice" type="java.lang.Double" not-null="true" length="12"/>
<set name="orders" inverse="true">
<key column="service_product_id" />
<one-to-many class="Order" />
</set>
</class>
State.hbm.xml
<class name="State" table="tbl_state">
<id name="id" type="java.lang.Integer" column="state_id">
<generator class="identity"/>
</id>
<property name="stateName" column="state_name" type="java.lang.String" not-null="false" length="32" />
<property name="stateDescription" column="state_description" type="java.lang.String" not-null="false" length="255" />
<set name="orders" inverse="true">
<key column="state_id"/>
<one-to-many class="Order"/>
</set>
</class>
Order.hbm.xml
<class name="Order" table="tbl_order" >
<id name="id" type="java.lang.Integer" column="order_id">
<generator class="identity"/>
</id>
<property name="orderDate" column="order_date" type="java.util.Date" not-null="true" length="0"/>
<property name="orderMessage" column="order_message" type="java.lang.String" not-null="false" length="64"/>
<property name="orderAttachment" column="order_attachment" type="java.lang.String" not-null="false" length="255"/>
<many-to-one name="orderUser" column="user_id" not-null="true" lazy="false"/>
<many-to-one name="orderServiceProduct" column="service_product_id" not-null="true" lazy="false"/>
<many-to-one name="orderState" column="state_id" not-null="true" lazy="false"/>
</class>