zoukankan      html  css  js  c++  java
  • dljd_(067-070)_hibernate_关联关系映射_自关联

    一、自关联

      是指,自己即充当一方,又充当多方,是1:n的变型。例如,对于新闻栏目NewsColumn,可以充当一方,即父栏目,也可以充当多方,即子栏目。而这些反映到数据库表中,只有一张表,这张表中具有一个外键,用于表示该栏目的父栏目。一级栏目的外键值为null,而子栏目则具有外键值。还有很多中这种例子,比如企业的员工表。每个员工都有自己的上级(除老板、老板的上级为null)、而自己的上级又在这张员工表中。

    二、程序示例(新闻条目类)

      新闻条目分为:父条目和子条目。

    package edu.aeon.beans;
    
    import java.util.HashSet;
    import java.util.Set;
    
    /**
     * [说明]:新闻条目类
     * @author aeon
     *
     */
    public class NewsLabel {
        /**新闻条目id*/
        private Integer newsId;
        /**新闻条目标题*/
        private String newsTitle;
        /**新闻条目内容*/
        private String newsContext;
        /**新闻父条目*/
        private NewsLabel parentNewsLabel;
        /**新闻子条目*/
        private Set<NewsLabel> childNewsLabels;
        public NewsLabel() {
            super();
            childNewsLabels=new HashSet<NewsLabel>();
        }
        public NewsLabel(String newsTitle, String newsContext) {
            this();
            this.newsTitle = newsTitle;
            this.newsContext = newsContext;
        }
    
        public Integer getNewsId() {
            return newsId;
        }
        public void setNewsId(Integer newsId) {
            this.newsId = newsId;
        }
        public String getNewsTitle() {
            return newsTitle;
        }
        public void setNewsTitle(String newsTitle) {
            this.newsTitle = newsTitle;
        }
        public String getNewsContext() {
            return newsContext;
        }
        public void setNewsContext(String newsContext) {
            this.newsContext = newsContext;
        }
        public NewsLabel getParentNewsLabel() {
            return parentNewsLabel;
        }
        public void setParentNewsLabel(NewsLabel parentNewsLabel) {
            this.parentNewsLabel = parentNewsLabel;
        }
        public Set<NewsLabel> getChildNewsLabels() {
            return childNewsLabels;
        }
        public void setChildNewsLabels(Set<NewsLabel> childNewsLabels) {
            this.childNewsLabels = childNewsLabels;
        }
        @Override
        public String toString() {
            return "NewsLabel [newId=" + newsId + ", newsTitle=" + newsTitle + ", newsContext=" + newsContext
                    + ", childNewsLabels=" + childNewsLabels + "]";
        }
    }
    NewsLabel.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 package="edu.aeon.beans">
        <class name="NewsLabel">
            <id name="newsId">
                <column name="newsId" sql-type="int(3)"/>
                <generator class="native"/>
            </id>
            <property name="newsTitle">
                <column name="newsTitle" sql-type="varchar(200)"/>
            </property>
            <property name="newsContext">
                <column name="newsContext" sql-type="varchar(1000)"/>
            </property>
            <!-- 关联属性的映射配置 -->
            <!-- name:关联属性的属性名 -->
            <set name="childNewsLabels"  cascade="save-update">
                <!-- 关联的外键 -->
                <key column="pid" />
                <!-- 关联到那个类 -->
                <one-to-many class="NewsLabel" />
            </set>
            <many-to-one name="parentNewsLabel" cascade="save-update" class="NewsLabel" column="pid" />
        </class>
    </hibernate-mapping>

    然后将NewsLabel.hbm.xml注册到hibernate的主配置文件里面:

      

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
    <hibernate-configuration>
        <session-factory>
            <!-- 配置数据库的四要素 -->
            <property name="hibernate.connection.driver">com.mysql.jdbc.Driver</property>
            <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/db_test</property>
            <property name="hibernate.connection.username">root</property>
            <property name="hibernate.connection.password">root</property>
            <!-- 配置数据库方言 -->
            <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
            <!-- 配置数据库连接池 -->
            <!-- <property name="hibernate.connection.provider_class">org.hibernate.c3p0.internal.C3P0ConnectionProvider</property> -->
            <!-- 注册当前session上下文 -->
            <property name="hibernate.current_session_context_class">thread</property>
            <!-- 自动建表 -->
            <property name="hibernate.hbm2ddl.auto">update</property>
            <!-- 显示sql -->
            <property name="hibernate.show_sql">true</property>
            <!-- 格式化sql -->
            <property name="hibernate.format_sql">true</property>
            <mapping resource="edu/aeon/beans/NewsLabel.hbm.xml"/>
        </session-factory>
    </hibernate-configuration>    

    单方(父条目)维护时的测试类

    package edu.aeon.hibernate.test;
    
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    import org.junit.Test;
    import edu.aeon.aeonutils.hibernate.getsessionutil.GetSessionUtil;
    import edu.aeon.beans.NewsLabel;
    
    /**
     * [说明]:测试自关联
     * @author aeon
     *
     */
    public class HibernateTest {
        /**
         * 自关联
         */
        @Test
        public  void testOne2Many(){
            Session session=null;
            Transaction transaction=null;
            try {
                session = GetSessionUtil.getSession();
                System.out.println(session);
                transaction = session.getTransaction();
                transaction.begin();
                NewsLabel child1=new NewsLabel("乒乓球", "乒乓球乒乓球乒乓球乒乓球乒乓球乒乓球");
                NewsLabel child2=new NewsLabel("篮球", "篮球篮球篮球篮球篮球篮球篮球篮球篮球篮球篮球");
                NewsLabel parent=new NewsLabel("体育", "这是体育!");
                //有parent去维护
                parent.getChildNewsLabels().add(child1);
                parent.getChildNewsLabels().add(child2);
                session.save(parent);//由谁维护保存谁
                transaction.commit();
            } catch (Exception e) {
                transaction.rollback();
                e.printStackTrace();
            }
        }
    }

    测试结果控制台:

      

    Hibernate: 
        
        create table NewsLabel (
            newsId int(3) not null auto_increment,
            newsTitle varchar(200),
            newsContext varchar(1000),
            pid integer,
            primary key (newsId)
        )
    Hibernate: 
        
        alter table NewsLabel 
            add constraint FKnxywagk83uy0fknne0t4nf59w 
            foreign key (pid) 
            references NewsLabel (newsId)
    ThreadLocalSessionContext.TransactionProtectionWrapper[SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])]
    Hibernate: 
        insert 
        into
            NewsLabel
            (newsTitle, newsContext, pid) 
        values
            (?, ?, ?)
    Hibernate: 
        insert 
        into
            NewsLabel
            (newsTitle, newsContext, pid) 
        values
            (?, ?, ?)
    Hibernate: 
        insert 
        into
            NewsLabel
            (newsTitle, newsContext, pid) 
        values
            (?, ?, ?)
    Hibernate: 
        update
            NewsLabel 
        set
            pid=? 
        where
            newsId=?
    Hibernate: 
        update
            NewsLabel 
        set
            pid=? 
        where
            newsId=?

    测试结果截图:

      

    数据库数据信息截图如下:
      

      

      

     由多方(子条目)维护关联关系时的测试类:

    package edu.aeon.hibernate.test;
    
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    import org.junit.Test;
    import edu.aeon.aeonutils.hibernate.getsessionutil.GetSessionUtil;
    import edu.aeon.beans.NewsLabel;
    
    /**
     * [说明]:测试自关联
     * @author aeon
     *
     */
    public class HibernateTest {
        /**
         * 自关联
         */
        @Test
        public  void testOne2Many(){
            Session session=null;
            Transaction transaction=null;
            try {
                session = GetSessionUtil.getSession();
                System.out.println(session);
                transaction = session.getTransaction();
                transaction.begin();
                NewsLabel parent=new NewsLabel("体育", "这是体育!");
                NewsLabel child=new NewsLabel("乒乓球", "乒乓球乒乓球乒乓球乒乓球乒乓球乒乓球");
                //有child去维护
                child.setParentNewsLabel(parent);
                session.save(child);//由谁维护保存谁
                transaction.commit();
            } catch (Exception e) {
                transaction.rollback();
                e.printStackTrace();
            }
        }
    }

     测试结果:

      

    Hibernate: 
        
        create table NewsLabel (
            newsId int(3) not null auto_increment,
            newsTitle varchar(200),
            newsContext varchar(1000),
            pid integer,
            primary key (newsId)
        )
    Hibernate: 
        
        alter table NewsLabel 
            add constraint FKnxywagk83uy0fknne0t4nf59w 
            foreign key (pid) 
            references NewsLabel (newsId)
    ThreadLocalSessionContext.TransactionProtectionWrapper[SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])]
    Hibernate: 
        insert 
        into
            NewsLabel
            (newsTitle, newsContext, pid) 
        values
            (?, ?, ?)
    Hibernate: 
        insert 
        into
            NewsLabel
            (newsTitle, newsContext, pid) 
        values
            (?, ?, ?)

    测试结果截图:

      

    此时我们去看下数据库中的数据信息:

      

      

      

      这样设计的表如何去区分父条目和子条目呢?满足pid is null的条目均为父条目,pid上有主键值指向的是子条目、且该主键值值为它的父条目的id

     

    如有任何疑问可联系邮箱: 给我发邮件、或直接联系QQ:1584875179 || 点返回首页

  • 相关阅读:
    洛谷 P2053 :[SCOI2007]修车(拆点+最小费用流)
    LightOJ
    spark简单入门
    crontab 应用
    HttpClient的使用
    build.sbt的定义格式
    Scalatra
    SBT 构建scala eclipse开发
    mysql 存在更新,不存在插入
    Flash Vector例子
  • 原文地址:https://www.cnblogs.com/aeon/p/10119841.html
Copyright © 2011-2022 走看看