【7.5.0】基于主键的单向多对多的关联映射
1.角色Role 和功能 Function
2.类Role 和Function类
public class Role { private int id; private String name; private Set<Function> functions = new HashSet<Function>(0); //get…set } public class Function { private int id; private String name; private String code; private String url; public Function() { // TODO Auto-generated constructor stub } public Function(String name, String code, String url) { super(); this.name = name; this.code = code; this.url = url; } //get…set }
3. 映射文件
Role.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.siggy.pojo"> <class name="Function"> <id name="id"> <!-- foreign表示引用外键 --> <generator class="native"/> </id> <property name="name"/> <property name="code"/> <property name="url"/> </class> </hibernate-mapping>
function.hbm.xml【因为casecade=all,即所有操作都级联】
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.siggy.pojo"> <class name="Role"> <id name="id"> <generator class="native"></generator> </id> <property name="name"/> <!-- 多对多 --> <set name="functions" table="role_func" cascade="all"> <!-- 表示当前类 映射到关系表中的列--> <key column="rid"/> <!-- 所对应的另一方在关系表中的列 --> <many-to-many column="fid" class="Function"/> </set> </class> </hibernate-mapping>
4.测试代码
package cn.siggy.test; import java.sql.SQLException; import java.util.Iterator; import javax.sql.rowset.serial.SerialException; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.tool.hbm2ddl.SchemaExport; import org.junit.Test; import cn.siggy.pojo.Function; import cn.siggy.pojo.Role; import cn.siggy.util.HibernateUtil; public class HibernateTest { @Test public void testCreateDB(){ Configuration cfg = new Configuration().configure(); SchemaExport se = new SchemaExport(cfg); //第一个参数 是否生成ddl脚本 第二个参数 是否执行到数据库中 se.create(true, true); } @Test public void testSave() throws HibernateException, SerialException, SQLException{ Session session = null; Transaction tx = null; try{ session = HibernateUtil.getSession(); tx = session.beginTransaction(); Function f1 = new Function("用户管理","user_mag","userAction"); Function f2 = new Function("角色管理","role_mag","roleAction"); Function f3 = new Function("系统管理","sys_mag","sysAction"); Function f4 = new Function("权限管理","prev_mag","prevAction"); Role r1 = new Role(); r1.setName("admin"); r1.getFunctions().add(f1); r1.getFunctions().add(f2); r1.getFunctions().add(f3); r1.getFunctions().add(f4); Role r2 = new Role(); r2.setName("vip"); r2.getFunctions().add(f1); r2.getFunctions().add(f2); session.save(r1); session.save(r2); tx.commit(); }catch (HibernateException e) { if(tx!=null) tx.rollback(); e.printStackTrace(); throw e; }finally{ HibernateUtil.closeSession(); } } @Test public void testGet(){ Session session = null; Transaction tx = null; try{ session = HibernateUtil.getSession(); tx = session.beginTransaction(); Role role = (Role)session.get(Role.class, 1); System.out.println("角色名:"+role.getName()); System.out.println("该角色所对应的权限:"); for(Iterator<Function> iter = role.getFunctions().iterator(); iter.hasNext();){ Function func = iter.next(); System.out.println(func.getName()+"---"+func.getCode()); } //取数据 tx.commit(); }catch (HibernateException e) { if(tx!=null) tx.rollback(); e.printStackTrace(); throw e; }finally{ HibernateUtil.closeSession(); } } @Test public void testDelete(){ Session session = null; Transaction tx = null; try{ session = HibernateUtil.getSession(); tx = session.beginTransaction(); Role role = (Role)session.get(Role.class, 2); session.delete(role); tx.commit(); }catch (HibernateException e) { if(tx!=null) tx.rollback(); e.printStackTrace(); throw e; }finally{ HibernateUtil.closeSession(); } } }
5.测试结果
1.执行testCreateDB()
2.执行testSave()
3.执行testGet()
4.执行testDelete()【因为casecade=all,即所有操作都级联】
错误原因分析:
因为创建中间表时,表字段设置为了不为空,而casecade级联操作中,在一对多的关系中,如果一的一端设置为delete【all包括delete】时,多的
一端不能指明外键为非空.
执行testCreareDB()创建表时,中间表的定义如下: