數據庫表關系及配置--多對多&一對多


1.數據庫表中的關系

  一對一

  一對多(多對一)

  多對多

2.如何確立和實現數據庫中的表關系

  一對多的表關系實現:

    使用外鍵約束

    我們習慣把一的方稱為主表,把多的方稱為從表  

    外鍵:從表中有一列,除了null之外,只能來源於主表的主鍵

       默認情況下,外鍵的字段是可以重復的

  多對多的表關系在數據庫中實現:

    使用中間表

    中間表有兩個外鍵,引用兩個多對多表的主鍵

    不能有其它字段信息,至於中間表的主鍵,應該采用聯合主鍵

    任何一個多方表和中間表去比較都是一對多的關系

  一對一的表關系再數據庫中實現:

    有兩種:

      1.以建立外鍵的方式

        使用外鍵約束,唯一約束,非空約束

        他是把外鍵字段加上了非空和唯一約束,從而實現一對一

      2.使用主鍵的方式

        讓其中一張表即是主鍵,又是外鍵。

3.多表映射配置要遵循的步驟

  第一步:確定兩張表之間的關系

  第二步:在數據庫中實現兩張表之間的關系建立

  第三步:在實體類中描述出兩個實體之間的關系

  第四步:在映射配置文件中簡歷兩個實體和兩個表之間的關系

4.一對多關系映射配置及操作

  示例:人員表和角色表

  第一步:確定兩個表之間的關系

      一個角色可以對應多個人員

      role角色表是主表,person人員表是從表

  第二步:在數據庫表中簡歷聯系

      實現一對多關系,靠外鍵

      person表中的r_id外鍵,是person的主鍵。

代碼示例:

1.數據庫表

 

2.hibernate.md.xml配置

<?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>
    <!--SessionFactory用來創建Session對象,Session對象時操作數據庫的核心-->
    <!--SessionFactory必要部分:1.連接數據庫信息;2.hibernate的可選配置;3.映射文件配置-->
    <session-factory>
        <!-- 1.連接數據庫的基本信息 -->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://127.0.0.1:3306/mybatis</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">root</property>

        <!-- 2.hibernate的可選配置 -->
        <!-- hibernate里的配置,數據庫使用的方言,開發過程中要在控制台顯示,sql -->
        <!--<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>-->
        <property name="hibernate.show_sql">true</property>
       <!-- <property name="hibernate.format_sql">true</property>-->
        <property name="hibernate.hbm2ddl.auto">update</property>
        <!--綁定線程和session,實現一個session只有一個線程。-->
        <property name="hibernate.current_session_context_class">thread</property>


        <!-- c3p0的配置 -->
        <!-- hibernate.connection.provider_class使用c3p0數據庫連接池的一個配置 -->
        <property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>

        <!--3.映射文件配置-->
        <!-- ORM映射關系 ,導入相應模型的絕對路徑-->
        <mapping resource="person.hbm.xml"/>
        <mapping resource="role.hbm.xml"/>

    </session-factory>

</hibernate-configuration>

3.person.hbm.xml

<?xml version="1.0" encoding="utf-8" ?>
        <!--導入dbd約束-->
        <!DOCTYPE hibernate-mapping PUBLIC
                "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
                "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.bean">
    <class name="Person" table="person">
        <id name="pId" column="p_id">
            <generator class="native"></generator>
        </id>
        <property name="pName" column="p_name"></property>
        <property name="pAddress" column="p_address"></property>
        <!--一對多關系映射:從表實體的映射配置
            涉及的標簽: many-to-one
            作用:建立多對一的映射配置
            屬性:name 從實體中映入主表實體對象的引用名稱
                 class 指定屬性對應的實體類名稱
                 column 指定從表中外鍵字段的名稱
        -->
        <many-to-one name="role" class="Role" column="p_r_id"></many-to-one>
    </class>
</hibernate-mapping>

4.role.hbm.xml

<?xml version="1.0" encoding="utf-8" ?>
<!--導入dbd約束-->
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.bean">
    <class name="Role" table="role">
        <id name="rId" column="r_id">
            <generator class="native"></generator>
        </id>
        <property name="rName" column="r_name"></property>
        <!--一對多關系映射:主表實體的映射配置
            涉及的標簽: set/list  key  many-to-one
            作用:用於配置set/list集合屬性
            屬性:name 指定實體中set/list集合屬性名稱
                 table 指定從表名稱。一對多配置可以補血
            key作用:用於映射外鍵字段
               屬性:column 指定外鍵名稱
            many-to-one作用:建立一對多的映射配置
                       屬性:calss 指定從表實體的名稱
                            cascade="save-update" 級聯更新為true
            級聯刪除需要配置inverse="true" cascade="save-update,delete"(開發中一般慎用)
        -->
        <set name="set"   table="person" inverse="true" cascade="save-update,delete">
            <key column="p_r_id" ></key>
            <one-to-many class="Person"></one-to-many>
        </set>
    </class>
</hibernate-mapping>

5.實體類

public class Person implements Serializable {
    private Integer pId;
    private String pName;
    private String pAddress;
    //一對多關系映射,從表實體包含主表實體的對象引用
    private Role role;
}  //省了get/set方法
public class Role implements Serializable {
    private Integer rId;
    private String rName;
    //一對多關系映射,主表實體應該包含從表實體的集引用
    private Set<Person> set;
} //省去get/set方法

6.測試類

public class TestHibernate01 {


    //查詢Person
    @Test
    public void test01() {
        Session s = HibernateUtils.getCurrnetSession();
        Transaction tx = s.beginTransaction();
        Query query = s.createQuery("from Person ");
        List list = query.list();
        for (Object o : list) {
            Person person = (Person) o;
            System.out.println(person.getpName() + ":" + person.getRole().getrName());
        }
        tx.commit();
    }

    //查詢所有的Role
    @Test
    public void test02() {
        Session s = HibernateUtils.getCurrnetSession();
        Transaction tx = s.beginTransaction();
        Query query = s.createQuery("from Role");
        List list = query.list();
        for (Object o : list) {
            Role role = (Role) o;
            System.out.println(role.getrName());
            for (Person person : role.getSet()) {
                System.out.println("set:" + person.getpName());
            }
        }
        tx.commit();
    }


    //修改角色的操作保存操作
    @Test
    public void test03() {
        Session s = HibernateUtils.getCurrnetSession();
        Transaction tx = s.beginTransaction();
        Role o = (Role) s.get(Role.class, 1);
        System.out.println("Role=" + o);
        Person o1 = (Person) s.get(Person.class, 2);
        o1.setRole(o);
        System.out.println("Person=" + o1);
        s.update(o1);
        tx.commit();
    }

    //級聯更新
    // set標簽的屬性cascade="save-update" 級聯更新為true
    @Test
    public void test04() {
        Session s = HibernateUtils.getCurrnetSession();
        Transaction tx = s.beginTransaction();
        Role o = (Role) s.get(Role.class, 3);
        o.setrName("大將");
        System.out.println("Role=" + o.getrName());
        s.save(o);
        tx.commit();
    }

    //級聯刪除
    // set標簽 級聯刪除需要配置inverse="true" cascade="save-update,delete"(開發中一般慎用)
    @Test
    public void test05() {
        Session s = HibernateUtils.getCurrnetSession();
        Transaction tx = s.beginTransaction();
        Role o = (Role) s.get(Role.class, 3);
        s.delete(o);
        tx.commit();
    }
}

 

5.多對多關系映射配置及操作

  使用中間表

  中間表有兩個外鍵,引用兩個多對多表的主鍵

需求:實現角色表和權限表之間的多對多,沒個角色多個權限,每個權限對應多個角色

1.修改Role角色類和創建Astrict權限類

public class Role implements Serializable {
    private Integer rId;
    private String rName;
    //一對多關系映射,主表實體應該包含從表實體的集引用
    private Set<Person> set=new HashSet<Person>(0);
    private Set<Astrict> astricts=new HashSet<Astrict>(0);

    public Set<Astrict> getAstricts() {
        return astricts;
    }

    public void setAstricts(Set<Astrict> astricts) {
        this.astricts = astricts;
    }

    @Override
    public String toString() {
        return "Role{" +
                "rId=" + rId +
                ", rName='" + rName + '\'' +
                ", set=" + set +
                '}';
    }

    public Set<Person> getSet() {
        return set;
    }

    public void setSet(Set<Person> set) {
        this.set = set;
    }

    public Integer getrId() {
        return rId;
    }

    public void setrId(Integer rId) {
        this.rId = rId;
    }

    public String getrName() {
        return rName;
    }

    public void setrName(String rName) {
        this.rName = rName;
    }
}
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

public class Astrict implements Serializable {
    private Integer aId;
    private String aName;
    private String aType;

    public Set<Role> getRoles() {
        return roles;
    }

    public void setRoles(Set<Role> roles) {
        this.roles = roles;
    }

    private Set<Role> roles=new HashSet<Role>(0);


    public String getaType() {
        return aType;
    }

    public void setaType(String aType) {
        this.aType = aType;
    }

    public Integer getaId() {
        return aId;
    }

    public void setaId(Integer aId) {
        this.aId = aId;
    }

    public String getaName() {
        return aName;
    }

    public void setaName(String aName) {
        this.aName = aName;
    }
}

2.配置astrict.hbm.xml和role.hbm.xml文件

<?xml version="1.0" encoding="utf-8" ?>
<!--導入dbd約束-->
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.bean">
    <class name="Astrict" table="astrict">
        <id name="aId" column="a_id">
            <generator class="native"></generator>
        </id>
        <property name="aName" column="a_name"></property>
        <property name="aType" column="a_type"></property>

        <!--
            多對多 table指定中間表名稱
            many-to-many作用:建立多對多的映射配置
                        屬性:column 對方在中間表的外鍵字段名稱
                             calss 指定從表實體的名稱
        -->
        <set name="roles" table="astrict_role_ref">
            <key column="a_id"></key>
            <many-to-many class="Role" column="r_id"></many-to-many>
        </set>
    </class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8" ?>
<!--導入dbd約束-->
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.bean">
    <class name="Role" table="role">
        <id name="rId" column="r_id">
            <generator class="native"></generator>
        </id>
        <property name="rName" column="r_name"></property>
        <!--一對多關系映射:主表實體的映射配置
            涉及的標簽: set/list  key  many-to-one
            作用:用於配置set/list集合屬性
            屬性:name 指定實體中set/list集合屬性名稱
                 table 指定從表名稱。一對多配置可以補血
            key作用:用於映射外鍵字段
               屬性:column 指定外鍵名稱
            lazy="true"  懶加載
            many-to-one作用:建立一對多的映射配置
                       屬性:calss 指定從表實體的名稱
                            cascade="save-update" 級聯更新為true
            級聯刪除需要配置inverse="true" cascade="save-update,delete"(開發中一般慎用)
        -->
        <set name="set"   table="person" inverse="true" cascade="save-update,delete" lazy="true">
            <key column="p_r_id" ></key>
            <one-to-many class="Person"></one-to-many>
        </set>
        <!--
            inverse="true" 只有多對多只有一方執行操作
            多對多 table指定中間表名稱
            many-to-many作用:建立多對多的映射配置
                        屬性:column 對方在中間表的外鍵字段名稱
                             calss 指定從表實體的名稱
        -->
        <set name="astricts" table="astrict_role_ref" inverse="true">
            <key column="r_id"></key>
            <many-to-many class="Astrict" column="a_id"></many-to-many>
        </set>
    </class>
</hibernate-mapping>

3.在主配置文件添加映射

<mapping resource="astrict.hbm.xml"/>

4.測試

  多對多保存,多對多全部查詢,多對多添加查詢

    /**
* 多對多保存操作
* 需求:角色-主公的帶兵,獻計和封侯權限;軍事-主公的帶兵和獻計權限;大將-主公的帶兵
*/
@Test
public void test01() {
Session s = HibernateUtils.getCurrnetSession();
Transaction tx = s.beginTransaction();
Role r1 = (Role)s.get(Role.class, 1); //角色1 主公
Role r2 = (Role)s.get(Role.class, 2); //角色1 軍師
Role r3 = (Role)s.get(Role.class, 3); //角色1 大將

Astrict a1=new Astrict();
a1.setaName("帶兵");
Astrict a2=new Astrict();
a2.setaName("獻計");
Astrict a3=new Astrict();
a3.setaName("封侯");
//建立雙向聯系
//1.先建立角色的
//主公 -- 帶兵,獻計,封侯
r1.getAstricts().add(a1);
r1.getAstricts().add(a2);
r1.getAstricts().add(a3);
//軍師 -- 帶兵,封侯
r2.getAstricts().add(a1);
r2.getAstricts().add(a2);
//大將 -- 帶兵
r3.getAstricts().add(a1);

//2.在建立權限的
//帶兵 -- 主公,軍事,大將
a1.getRoles().add(r1);
a1.getRoles().add(r2);
a1.getRoles().add(r3);
//獻計 -- 主公,軍事
a2.getRoles().add(r1);
a2.getRoles().add(r2);
//封侯 -- 主公
a3.getRoles().add(r1);
s.update(r1);
s.update(r2);
s.update(r3);
s.save(a1);
s.save(a2);
s.save(a3);
tx.commit();
}

/**
* 多對多全部查詢
* 同過獲取屬性的方法,直接查詢p1.getRole().getAstricts()
*/
@Test
public void test02(){
Session s = HibernateUtils.getCurrnetSession();
Transaction tx = s.beginTransaction();
Query query=s.createQuery("from Person ");
List<Person> list = query.list();
for (Person person : list) {
System.out.println("姓名:"+person.getpName()+",角色:"+person.getRole().getrName());
Set<Astrict> set= person.getRole().getAstricts();
for (Astrict astrict : set) {
System.out.println(astrict.getaName());
}
}

tx.commit();
}

/**
* 多對多條件查詢
* 同過獲取屬性的方法,直接查詢p1.getRole().getAstricts()
*/
@Test
public void test03(){
Session s = HibernateUtils.getCurrnetSession();
Transaction tx = s.beginTransaction();
Person p1 = (Person)s.get(Person.class, 1);
System.out.println("姓名:"+p1.getpName()+",角色:"+p1.getRole().getrName());
Set<Astrict> set= p1.getRole().getAstricts();
for (Astrict astrict : set) {
System.out.println(astrict.getaName());
}
tx.commit();
}

}

 

 

 

 

  

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM