Hibarnate关联关系(多对多)

在Hibarbate如果你想实现权限表的话,我们可以使用一对多的自关联关系来实现:
首先实体类:

public class TreeNode {
	private Integer nodeId;
	private String nodeName;
	private Integer treeNodeType;
	private Integer position;
	private String url;
	private TreeNode parent;
	private Set<TreeNode> children = new HashSet<TreeNode>();
	private Integer initChildren = 0;
}

提供set/get方法,
这里可以看到 Set TreeNode children 这里面放的是自己,
所以他是自关联关系。
在xml里的配置如下:

<hibernate-mapping>
	<class name="com.zlk.four.entity.TreeNode" table="t_hibernate_sys_tree_node">
		<id name="nodeId" type="java.lang.Integer" column="tree_node_id">
			<generator class="increment" />
		</id>
		<property name="nodeName" type="java.lang.String"
			column="tree_node_name">
		</property>
		<property name="treeNodeType" type="java.lang.Integer"
			column="tree_node_type">
		</property>
		<property name="position" type="java.lang.Integer"
			column="position">
		</property>
		<property name="url" type="java.lang.String"
			column="url">
		</property>
		
		<many-to-one name="parent" class="com.zlk.four.entity.TreeNode" column="parent_node_id"/>
		
		<set name="children" cascade="save-update" inverse="true">
			<key column="parent_node_id"></key>
			<one-to-many class="com.zlk.four.entity.TreeNode"/>
		</set>
	</class>
</hibernate-mapping>

因为是自关联,所以两个配置都写在一个xml里面,
方法:

public class TreeNodeDao {
	public TreeNode load(TreeNode treeNode) {
		Session session = SessionFactoryUtils.openSession();
		Transaction transaction = session.beginTransaction();
		TreeNode t = session.load(TreeNode.class, treeNode.getNodeId());
		if(t != null && new Integer(1).equals(treeNode.getInitChildren())) {
			Hibernate.initialize(t.getChildren());
			Hibernate.initialize(t.getParent());
		}
		transaction.commit();
		session.close();
		return t;
	}

上篇博客中提到过,initChildren是用来控制是否强加载的,因为权限表,即有子节点也有父节点,当你查找的时候会很耗性能,会把所有资源全加载出来,但你可能只需要一个表的资源,所以用到initChildren来控制,但这样也有个坏处,那就是如果你的表中有更多个的话,if判断语句会有更多,这样就造成代码臃肿。
那有什么方法可以解决呢?

这里可以运用Hibarnate的其他关联关系:多地对多。
在这里我运用二星权限表来演示一下,
实体类 :

public class Book{
	private Integer bookId;
	private String bookName;
	private Float price;
	private Set<Category> categories = new HashSet<Category>();
	private Integer initCategories = 0;
		//		set/get
}
public class Category{
	private Integer categoryId;
	private String categoryName;
	private Set<Book> books = new HashSet<Book>();
		//		set/get
}

书可以有多个类型,而每个类型可以有多本书,即多对多。
二星权限中第有一个中间表,但这个中间表在这里是可以不实例化的。交给这两个表来维护即可。
但是还是要数据库表的,两条列即可,bookId 和 categoryId 。进行相对应。
book xml配置:

<!-- 
			table:代表的是中间表
			name:书籍类的关联属性
			inverse:中间表交于对方维护
			
			key:当前类的主键在中间表对应的列段
			many-to-many:
				column:关联表的主键在中间表的列段
				class:中间表的实体类
		 -->
		<set table="t_hibernate_book_category" name="categories" cascade="save-update" inverse="false">
			<!-- one -->
			<key column="bid"></key>
			<!-- many -->
			<many-to-many column="cid" class="com.zlk.four.entity.Category"></many-to-many>
		</set>

category xml配置 :

<set table="t_hibernate_book_category" name="books" cascade="save-update" inverse="false">
	<key column="cid"></key>
	<many-to-many column="bid" class="com.zlk.four.entity.Book"></many-to-many>
</set>

其实两个配置是一样的,因为是多对多。
之所以 categories 和 books里面有值就是通过这个set获得值的,
顺序是:
首先获得书的id然后通过key获得中间表中的对应的cid,再通过cid获得类型表,即通过cid得到类型的集合,即获得成功。

在这里要注意的是inverse=“false”,这个的意思就是交由谁来维护。

测试:

/**
	 * book.hbm.xml	inverse=fasle
	 * category.hbm.xml inverse=true
	 * 数据添加正常
	 * 书籍表、桥接表各新增一条数据
	 */
	@Test
	public void test1() {
		Book book = new Book();
		book.setBookName("b");
		book.setPrice(10f);
		Category category = new Category();
		category.setCategoryId(5);
//		直接将category对象加入到新建的book中是错误的,因为此时的category是临时态的,hibernate是不会管理的
//		book.getCategories().add(category);
		Category c = this.bookDao.getCategory(category);
		
//		c.getBooks().add(book);
		book.getCategories().add(c);
		this.bookDao.addBook(book);
	}

两个数据表中都增加了数据进去。即成功

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值