zoukankan      html  css  js  c++  java
  • hibernate关联关系(多对多)

    一、一对多自关联实例:

    数据库表 t_hibernate_sys_tree_node:

    实体类 TreeNode:

    package com.liuwenwu.four.entity;
    
    import java.util.HashSet;
    import java.util.Set;
    
    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;
    //    0是代表懒加载  1强制加载子节点  2强制加载用户  3强制加载两个
    
        public Integer getNodeId() {
            return nodeId;
        }
    
        public void setNodeId(Integer nodeId) {
            this.nodeId = nodeId;
        }
    
        public String getNodeName() {
            return nodeName;
        }
    
        public void setNodeName(String nodeName) {
            this.nodeName = nodeName;
        }
    
        public Integer getTreeNodeType() {
            return treeNodeType;
        }
    
        public void setTreeNodeType(Integer treeNodeType) {
            this.treeNodeType = treeNodeType;
        }
    
        public Integer getPosition() {
            return position;
        }
    
        public void setPosition(Integer position) {
            this.position = position;
        }
    
        public String getUrl() {
            return url;
        }
    
        public void setUrl(String url) {
            this.url = url;
        }
    
        public TreeNode getParent() {
            return parent;
        }
    
        public void setParent(TreeNode parent) {
            this.parent = parent;
        }
    
        public Set<TreeNode> getChildren() {
            return children;
        }
    
        public void setChildren(Set<TreeNode> children) {
            this.children = children;
        }
    
        public Integer getInitChildren() {
            return initChildren;
        }
    
        public void setInitChildren(Integer initChildren) {
            this.initChildren = initChildren;
        }
    
        @Override
        public String toString() {
            return "TreeNode [nodeId=" + nodeId + ", nodeName=" + nodeName + ", treeNodeType=" + treeNodeType
                    + ", position=" + position + ", url=" + url + "]";
        }
    }

    配置实体类映射关系 TreeNode.hbm.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
        <class name="com.liuwenwu.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.liuwenwu.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.liuwenwu.four.entity.TreeNode"/>
            </set>
        </class>
    </hibernate-mapping>

    主配置文件 hibernate.cfg.xml添加

    <!-- 一对多的自关联 -->
    <mapping resource="com/liuwenwu/four/entity/TreeNode.hbm.xml"/>

    dao方法 TreeNodeDao:

    package com.liuwenwu.four.dao;
    
    import org.hibernate.Hibernate;
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    
    import com.liuwenwu.four.entity.TreeNode;
    import com.liuwenwu.two.util.SessionFactoryUtils;
    
    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;
        }
    }

    Junit测试类 TreeNodeDaoTest:

    package com.liuwenwu.four.dao;
    
    import org.junit.Test;
    
    import com.liuwenwu.four.entity.TreeNode;
    
    public class TreeNodeDaoTest {
        private TreeNodeDao treeNodeDao = new TreeNodeDao();
    
        @Test
        public void testLoad() {
            TreeNode treeNode = new TreeNode();
            treeNode.setNodeId(6);
            treeNode.setInitChildren(1);
            TreeNode t = this.treeNodeDao.load(treeNode);
    //        当前节点
            System.out.println(t);
    //        父节点
            System.out.println(t.getParent());
    //        子节点
            System.out.println(t.getChildren());
        }
    }

    不需要迭代也可以查出当前节点的父节点与子节点,看似很方便,但是关联的表越多 那if判断就要写得越多,维护起来麻烦 性能差   如下:

    package com.liuwenwu.four.dao;
    
    import org.hibernate.Hibernate;
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    
    import com.liuwenwu.four.entity.TreeNode;
    import com.liuwenwu.two.util.SessionFactoryUtils;
    
    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.getParent());
            }
            //强制加载用户
            if(t != null && new Integer(2).equals(treeNode.getInitChildren())) {
                Hibernate.initialize(t.getChildren());
            }
            //强制加载两个
            if(t != null && new Integer(3).equals(treeNode.getInitChildren())) {
                Hibernate.initialize(t.getChildren());
                Hibernate.initialize(t.getParent());
            }
            transaction.commit();
            session.close();
            return t;
        }
    }

    二、多对多实例:

    实体类 Book:

    package com.liuwenwu.four.entity;
    
    import java.io.Serializable;
    import java.util.HashSet;
    import java.util.Set;
    
    public class Book implements Serializable{
    //    book_id int primary key auto_increment,
    //       book_name varchar(50) not null,
    //       price float not null
        private Integer bookId;
        private String bookName;
        private Float price;
        
        private Set<Category> categories = new HashSet<Category>();
        private Integer initCategories = 0;
    
        public Integer getInitCategories() {
            return initCategories;
        }
    
        public void setInitCategories(Integer initCategories) {
            this.initCategories = initCategories;
        }
    
        public Integer getBookId() {
            return bookId;
        }
    
        public void setBookId(Integer bookId) {
            this.bookId = bookId;
        }
    
        public String getBookName() {
            return bookName;
        }
    
        public void setBookName(String bookName) {
            this.bookName = bookName;
        }
    
        public Float getPrice() {
            return price;
        }
    
        public void setPrice(Float price) {
            this.price = price;
        }
    
        public Set<Category> getCategories() {
            return categories;
        }
    
        public void setCategories(Set<Category> categories) {
            this.categories = categories;
        }
    
        @Override
        public String toString() {
            return "Book [bookId=" + bookId + ", bookName=" + bookName + ", price=" + price + "]";
        }
    
        public Book(Integer bookId, String bookName) {
            super();
            this.bookId = bookId;
            this.bookName = bookName;
        }
    
        public Book() {
            super();
        }
    }

    实体类 Category:

    package com.liuwenwu.four.entity;
    
    import java.io.Serializable;
    import java.util.HashSet;
    import java.util.Set;
    
    public class Category implements Serializable{
    //    category_id int primary key auto_increment,
    //       category_name varchar(50) not null
        private Integer categoryId;
        private String categoryName;
        private Set<Book> books = new HashSet<Book>();
        public Integer getCategoryId() {
            return categoryId;
        }
        public void setCategoryId(Integer categoryId) {
            this.categoryId = categoryId;
        }
        public String getCategoryName() {
            return categoryName;
        }
        public void setCategoryName(String categoryName) {
            this.categoryName = categoryName;
        }
        public Set<Book> getBooks() {
            return books;
        }
        public void setBooks(Set<Book> books) {
            this.books = books;
        }
        @Override
        public String toString() {
            return "Category [categoryId=" + categoryId + ", categoryName=" + categoryName + "]";
        }
        
    }

    配置实体类映射关系 book.hbm.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
        <class name="com.liuwenwu.four.entity.Book" table="t_hibernate_book">
            <id name="bookId" type="java.lang.Integer" column="book_id">
                <generator class="increment" />
            </id>
            <property name="bookName" type="java.lang.String"
                column="book_name">
            </property>
            <property name="price" type="java.lang.Float"
                column="price">
            </property>
            <!-- 
                table:代表的是中间表
                name:书籍类的关联属性
                inverse:中间表交于对方维护
                key:当前类对应的表列段在中间表(t_hibernate_book_category)中的外键(bid)
                many-to-many:
                    column:对应的是上面key查出来的中间表(t_hibernate_book_category)的另一个字段(cid),
                                 当做关联表的主键(category_id)进行查询
                    class:上述查出来的主键对应的实体类
                
                流程:已查询book_id=1圣墟这本书为例
                    1、通多建模反射自动生成sql,可以拿到book_id=8这条记录的基本信息{book_id=1,book_name=西游记,price=50}
                    2、book_id=1->bid=1去查询中间表(t_hibernate_book_category)
                        拿到了cid=1,2
                    3、cid=1,2->t_hibernate_book_category的category_id=1,2
                    4、拿到了当前book实例对应的category的集合
                    5、最终{book_id=1,book_name=西游记,price=50}
                       ->{book_id=1,book_name=西游记,price=50,categories=[categoryId=2, categoryName=神话], Category [categoryId=1, categoryName=古典]}
             -->
            <set table="t_hibernate_book_category" name="categories" cascade="save-update" inverse="true">
                <!-- one -->
                <key column="bid"></key>
                <!-- many -->
                <many-to-many column="cid" class="com.liuwenwu.four.entity.Category"></many-to-many>
            </set>
        </class>
    </hibernate-mapping>

    配置实体类映射关系 category.hbm.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
        <class name="com.liuwenwu.four.entity.Category" table="t_hibernate_category">
            <id name="categoryId" type="java.lang.Integer" column="category_id">
                <generator class="increment" />
            </id>
            <property name="categoryName" type="java.lang.String"
                column="category_name">
            </property>
            
            <set table="t_hibernate_book_category" name="books" cascade="save-update" inverse="true">
                <key column="cid"></key>
                <many-to-many column="bid" class="com.liuwenwu.four.entity.Book"></many-to-many>
            </set>
        </class>
    </hibernate-mapping>

    主配置文件 hibernate.cfg.xml:

    <!-- 多对多关联 -->
    <mapping resource="com/liuwenwu/four/entity/Book.hbm.xml"/>
    <mapping resource="com/liuwenwu/four/entity/Category.hbm.xml"/>

    dao方法 BookDao :

    package com.liuwenwu.four.dao;
    
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import org.hibernate.Hibernate;
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    import org.hibernate.query.Query;
    
    import com.liuwenwu.four.entity.Book;
    import com.liuwenwu.four.entity.Category;
    import com.liuwenwu.two.util.SessionFactoryUtils;
    
    import antlr.StringUtils;
    
    public class BookDao{
        public Integer addBook(Book book) {
            Session session = SessionFactoryUtils.openSession();
            Transaction transaction = session.beginTransaction();
            Integer bid = (Integer) session.save(book);
            transaction.commit();
            session.close();
            return bid;
        }
        
        public Integer addCategory(Category category) {
            Session session = SessionFactoryUtils.openSession();
            Transaction transaction = session.beginTransaction();
            Integer cid = (Integer) session.save(category);
            transaction.commit();
            session.close();
            return cid;
        }
        
        public Category getCategory(Category category) {
            Session session = SessionFactoryUtils.openSession();
            Transaction transaction = session.beginTransaction();
            Category c = session.get(Category.class, category.getCategoryId());
            transaction.commit();
            session.close();
            return c;
        }
        
        public Book getBook(Book book) {
            Session session = SessionFactoryUtils.openSession();
            Transaction transaction = session.beginTransaction();
            Book b = session.get(Book.class, book.getBookId());
            if (b != null && new Integer(1).equals(book.getInitCategories())) {
                Hibernate.initialize(b.getCategories());
            }
            transaction.commit();
            session.close();
            return b;
        }
        
        public void delBook(Book book) {
            Session session = SessionFactoryUtils.openSession();
            Transaction transaction = session.beginTransaction();
            session.delete(book);
            transaction.commit();
            session.close();
        }
        
        public void delCategory(Category category) {
            Session session = SessionFactoryUtils.openSession();
            Transaction transaction = session.beginTransaction();
            Category c = session.get(Category.class, category.getCategoryId());
            if(c!=null) {
                for (Book b : c.getBooks()) {
    //                通过在被控方通过主控方来解除关联关系,最后被控方再做删除
                    b.getCategories().remove(c);
                }
            }
            session.delete(c);
            transaction.commit();
            session.close();
        }
    }

    Junit测试类 BookDaoTest:

    package com.liuwenwu.four.dao;
    import org.junit.Test;
    import com.liuwenwu.four.entity.Book;
    import com.liuwenwu.four.entity.Category;
    
    public class BookDaoTest {
        private BookDao bookDao = new BookDao();
    
        @Test
        public void testGetBook() {
            Book book = new Book();
            book.setBookId(1);
            book.setInitCategories(1);
            Book b = this.bookDao.getBook(book );
            System.out.println(b.getBookName());
            System.out.println(b.getCategories());
        }
        
        /**
         * book.hbm.xml    inverse=fasle
         * category.hbm.xml inverse=true
         * 数据添加正常
         * 书籍表、桥接表各新增一条数据(级联新增)
         */
        @Test
        public void test1() {
            Book book = new Book();
            book.setBookName("少年阿宾2");
            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);
        }
    
        /**
         * book.hbm.xml    inverse=true
         * category.hbm.xml inverse=true
         * 只增加书籍表数据
         * 桥接表不加数据
         * 原因:双方都没有去维护关系
         */
        @Test
        public void test2() {
            Book book = new Book();
            book.setBookName("诡秘之主");
            book.setPrice(99f);
            Category category = new Category();
            category.setCategoryId(4);
            Category c = this.bookDao.getCategory(category);
            
            book.getCategories().add(c);
            this.bookDao.addBook(book);
    //        c.getBooks().add(book);
        }
    }

    联级查询 已知书本ID查出书本信息以及书本所属类别

        /**
         * 联级查询
         */
        @Test
        public void testGetBook() {
            Book book = new Book();
            book.setBookId(1);
            book.setInitCategories(1);
            Book b = this.bookDao.getBook(book );
            System.out.println(b.getBookName());
            System.out.println(b.getCategories());
        }
    西游记
    [Category [categoryId=2, categoryName=神话], Category [categoryId=1, categoryName=古典]]

    inverse属性的使用 :

        /**
         * book.hbm.xml    inverse=fasle
         * category.hbm.xml inverse=true
         * 数据添加正常
         * 书籍表、桥接表各新增一条数据(级联新增)
         */
        @Test
        public void test1() {
            Book book = new Book();
            book.setBookName("少年阿宾2");
            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);
        }

    book.hbm.xml和category.hbm.xml两个配置文件中都有inverse属性 

    inverse=true 表示中间表交于对方维护 

    inverse=fasle 表示同意维护

    如果双方都为 true 则双方都不进行维护 中间表就不会新增数据

    如果双方都为 fasle 则双方都会维护 中间表数据会新增两次

  • 相关阅读:
    GitLab 介绍
    git 标签
    git 分支
    git 仓库 撤销提交 git reset and 查看本地历史操作 git reflog
    git 仓库 回退功能 git checkout
    python 并发编程 多进程 练习题
    git 命令 查看历史提交 git log
    git 命令 git diff 查看 Git 区域文件的具体改动
    POJ 2608
    POJ 2610
  • 原文地址:https://www.cnblogs.com/liuwenwu9527/p/11203243.html
Copyright © 2011-2022 走看看