废话少说,接上回。
一) 如果在项目中考虑到适应多个数据库,比如sql server2005,oracle,那么请在sql server2005设计你的数据表时,将表名,字段名全部大写,那么在转换成oracle时会非常方便,否则在oracle中写sql语句是非常痛苦的。下面是一个user表对应的hibernate配置文件片断:
<class name="qk.domain.baseinfo.User" table="TBUSER">
<!-- optimistic-lock="version">-->
<meta attribute="sync-DAO">false</meta>
<id name="id" type="string" column="ID">
<generator class="assigned"/>
</id>
<!--version name="operDate" column="OPERDATE" type="timestamp" /-->
<property name="autoId" column="AUTOID" type="integer" not-null="true"
length="10" insert="false" update="false"/>
<property name="userName" column="USERNAME" type="string" not-null="false"
length="32"/>
<property name="userAccount" column="USERACCOUNT" type="string"
not-null="false" length="16"/>
......
<property name="operDate" column="OPERDATE" type="timestamp"
not-null="false" length="23"/>
<set name="roles" table="TBUSER_ROLE" inverse="false" lazy="true"
cascade="none">
<key column="USERID"></key>
<many-to-many class="qk.domain.baseinfo.Role"
column="ROLEID"/>
</set>
<many-to-one name="depart" class="qk.domain.baseinfo.Depart"
column="DEPARTID" cascade="none"/>
</class>
主键为ID,同样为了适应多数据库,在这里设置为手动对主键赋值即<generator class="assigned"/>。到目前位置我还没有跑通hibernate提供处理并发的方法,即增加一个日期时间字段,并将此字段声明<version name="operDate" column="OPERDATE" type="timestamp" />,可是总是没更新operDate字段且根本就处理不了并发的问题,哪位高人知道请告诉我,不胜感激!
由于人员可以对应多个角色且只属于一个部门,一个部门或角色又包含多个人员,所以在配置人员对应角色时是many-to-many,对应部门是many-to-one。如果删除人员要将对应的人员角色关系删除,请将人员设置为主控端(inverse='false'),设置角色为被控端(inverse='true');那么在删除人员时无需写删除角色对应关系的代码即可将对应的关系删除,这些事都是hibernate帮你完成,可以通过在appicationContext.xml中配置 <prop key="hibernate.show_sql">true</prop>在eclipse控制台输出后台运行的SQL语句。在删除角色时删除与人员的对应的关系数据则没那么简单,需要手动编写了,代码示例如下:
public void deleteRoleById(final String id)
{
Role role = getRoleById(id);
for (User user : role.getUsers())
{
user.getRoles().remove(role);
}
getHibernateTemplate().delete(role);
}
在删除部门时,由于在上面的配置文件中设置了部门是被控端(如果在配置文件中没有填写inverse值,则Hibernate默认为false),那么删除部门的代码应该是这样:
public void deleteDepartById(String id)
{
List list = getSubDepartsById(id);
for (int i = list.size() - 1; i >= 0; i--)
{
Depart depart = ((Depart) list.get(i));
getHibernateTemplate().deleteAll(depart.getUsers());
getHibernateTemplate().delete(depart);
}
}
二)在SQL SERVER中有自增字段,但在ORACLE里面没有,而是以序列代替。那么为了适应多数据库,代码不改动。则在上面的配置文件中的自增字段AUTOID的insert="false" update="false",表名此字段不由hibernate处理,这样在SQL SERVER中是没问题,在oracle里插入值要则用了个变通的办法--触发器。由触发器来完成此字段的插入。但是假如一个数据库有500张表,你不是要写500此啊?!呵呵,人是活的,当然可以编写一个SQL脚本来动态创建这些表对应的触发器啊。以后我会将此SQL脚本贴出~
三)在命名JAVA实体类的属性时,注意前两个字母不要大写,否则就会出错。具体为什么,只有JAVA知道。如果你知道其中的原因或解决办法,请告诉我。谢谢!
四)HIBERNATE的出现使我们在某种程度上避免了写SQL,但是有时候为了效率或者它自带的HQL无法实现我们需要的功能时,这就需要SQL了。以下是项目中用到的SQL配置片断:
<sql-query name="getSubDepartsById">
<return alias="department" class="qk.domain.baseinfo.Depart"/>
SELECT {department.*} FROM BiTbDepart department WHERE
department.departCode LIKE (SELECT MAX(departCode) || '%' FROM sysBiTbDepart
WHERE id = ?) ORDER BY department.departCode, department.departOrder
</sql-query>
DAO代码:
public List getSubDepartsById(String id)
{
return getHibernateTemplate().findByNamedQuery("getSubDepartsById", id);
}
以上返回的是Department类的List集合;如果不想返回Department整个类,而是取其中的几个属性,可以将具体的属性替换*,那么DAO返回的还是LIST集合,只不过LIST中的每个对象是Object[]。
建议:有些时候不要为了OO而OO,效率第一,编码再漂亮也是给程序员看的,不是给用户;所以当你遇到大数据量的运算时,请使用SQL,再退一步,用JDBC,再再退一步,用STORE PROCEDURE。多数据库的支持也是基于一定程度上的,不是绝对的。
待续......