级联删除
相信学过数据库基础的童鞋们都知道,当有两个表A和B,表A的外键正是表B的主键时,我们会发现,当我们用数据库语言对B表数据进行删除操作的时候,我们会发现根本就删除不了,所以呢,在实际代码中,想要通过点击删除就可以删除?那么就需要对其进行相关操作了,具体的呢,咱就一步一步来,我所写的是通过spring3+hibernate4+struts2+maven写的代码,里面有两个表department 和user,其department的主键did在user中作为外键,这时候就必然会在department.hbm.xml中配置多对多的关系,如下代码:
<hibernate-mapping package="com.cct.entity"> <class name="Department" table="department"> <id name="did" type="java.lang.Integer"> <generator class="increment"/> </id> <property name="dname" type="java.lang.String"/> <property name="description" type="java.lang.String"/> <!--用户和部门之间的关系 --> <set name="users" inverse="true" cascade="all">//cascade参数不要掉 <key> <column name="did"></column> </key> <many-to-many class="com.cct.entity.User"></many-to-many> </set> </class> </hibernate-mapping>
因为是通过spring的管理,所以在spring.xml中sessionfactory和transactionmanage的配置都要记得,具体代码如下:
<!-- session工厂 --> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="hibernateProperties"> <props> <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.show_sql">${hibernate.show_sql}</prop> <prop key="hibernate.format_sql">${hibernate.format_sql}</prop> </props> </property> <property name="mappingResources"> <list> <value>com/cct/entity/Department.hbm.xml</value> <value>com/cct/entity/User.hbm.xml</value> <value>com/cct/entity/Post.hbm.xml</value> </list> </property> </bean> <bean name="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory"> <ref local="sessionFactory"/></property> </bean>
<tx:advice id="advice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="save*" propagation="REQUIRED" isolation="DEFAULT" read-only="false"/> <tx:method name="delete*" propagation="REQUIRED" isolation="DEFAULT" read-only="false"/> <tx:method name="update*" propagation="REQUIRED" isolation="DEFAULT" read-only="false"/> <tx:method name="*" read-only="true"/> </tx:attributes> </tx:advice> <!-- 5配置切入点 --> <aop:config> <!-- 配置切入点 ,这里的切入点应用的类级别 --> <aop:pointcut id="perform" expression="execution( * com.cct.service..*.*(..))"/> <!-- 建立通知和切入点的结合 --> <aop:advisor advice-ref="advice" pointcut-ref="perform"/> </aop:config>
以上代码中,记得后面的对于transactionManager的处理(tx:开头的和aop:开头)一定不能掉了,在这部分进行了开启事务管理,如果掉了的话就会报错:No Session found for current thread,当然,除此之外,在写Dao层的时候,也需要注意的是,如果用的是hibernate3,则可以通过继承HibernateDaoSupport来通过hibernatetemplate来进行增删改查操作,当然也是不需要写transaction的开启和提交类似的语句的,如果是hibernate4的话,就需要在Dao中写下下面代码:
@Resource private SessionFactory sessionFactory ;
通过spring注解特性,用@Resource对sessionfactory进行注入,这样的话在dao层的每个方法中通过sessionfactory.getCurrentSession.*()就可以直接进行增删改查操作,接下来关键的时候到了,那就是在删除操作中,需要进行判断,通过判断departmentservice传过来的参数DeleMode(这个是提前在单独类中定义一些静态变量)来做删除前的解除关系操作,解除关系之后就可以正常删除:
public void deleteDepartmentByID(Serializable id,String deletemode) { Department departement=this.getDepartmentbyId(id); if("del".equals(deletemode)) { sessionFactory.getCurrentSession().delete(departement); } else if("del_pre_release".equals(deletemode))//删除之前先解除关系 { Set<User> departments=departement.getUsers(); for(User user:departments) { user.setDepartment(null); } } else{//级联删除 } sessionFactory.getCurrentSession().delete(departement); }
这样的操作应该是比较常见的,所以有些问题需要注意一下。