美文网首页
常见的映射关系

常见的映射关系

作者: soloist001 | 来源:发表于2019-09-30 23:17 被阅读0次
    热烈庆祝中华人民共和国建国70周年

    Hibernate介绍

    Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的JaveEE架构中取代CMP,完成数据持久化的重任。
    常见的映射关系主要有:

    • 一对一主键映射
    • 一对一外键映射
    • 一对多外键映射
    • 多对多关系映射

    一对一主键映射

    首先我们来分析一下一对一主键映射:一对一主键映射拿生活中常见的事务来举例:就像一个人对应一张身份证,一张身份证对应一个人,一个人只能拥有一张中华人民共和国身份证,也只有一个身份证号。所以一个人和身份证就构成了一对一的映射,商品和商品详情也构成了一一映射关系,用户和用户详情也构成了一一映射的关系,等等......
    一对一映射将用户和用户详情来举例说明:

    1.设计数据库表

    -- ----用户表
    create table user_t(
    userid int primary key auto_increment,
    username varchar(20),
    sex varchar(10),
    age int
    );
    
    -- --用户详情表--  
    create table userdetail_t(
    userid int primary key auto_increment,
    idcard varchar(20),
    address varchar(100),
    decx varchar(100)
    );
    

    2.反向生成用户表和用户详情表对应的配置文件

    • 用户表设置如下:
    package cn.hd.onetoone;
    /**
     * 主键关联,用户表作为主表
     */
    public class UserT implements java.io.Serializable {
        // Fields
        private Integer userid;
        private String username;
        private String sex;
        private Integer age;
        //
        private UserdetailT details;
        // Constructors
        /** default constructor */
        public UserT() {
        }
        /** full constructor */
        public UserT(String username, String sex, Integer age) {
            this.username = username;
            this.sex = sex;
            this.age = age;
        }
        // Property accessors
        public Integer getUserid() {
            return this.userid;
        }
        public void setUserid(Integer userid) {
            this.userid = userid;
        }
        public String getUsername() {
            return this.username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public String getSex() {
            return this.sex;
        }
        public void setSex(String sex) {
            this.sex = sex;
        }
        public Integer getAge() {
            return this.age;
        }
        public void setAge(Integer age) {
            this.age = age;
        }
        public UserdetailT getDetails() {
            return details;
        }
        public void setDetails(UserdetailT details) {
            this.details = details;
        }
    }
    
    • 用户表配置文件设置如下:
    <?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">
    <!-- 
        Mapping file autogenerated by MyEclipse Persistence Tools
    -->
    <hibernate-mapping>
        <class name="cn.hd.onetoone.UserT" table="user_t" catalog="eleshop">
            <id name="userid" type="java.lang.Integer">
                <column name="userid" />
                <!--主键关联主表的主键自动增长,用用户自己控制,从表的主键要根据主表来变  -->
                <generator class="increment"/>
            </id>
            <property name="username" type="java.lang.String">
                <column name="username" length="20" />
            </property>
            <property name="sex" type="java.lang.String">
                <column name="sex" length="10" />
            </property>
            <property name="age" type="java.lang.Integer">
                <column name="age" />
            </property>
            <!-- 主表要添加,从表名称和路径 -->
            <one-to-one name="details" class="cn.hd.onetoone.UserdetailT" cascade="all"></one-to-one>
        </class>
    </hibernate-mapping>
    
    
    • 用户详情表设置如下:
    package cn.hd.onetoone;
    /**
     * 主键关联,从表
     */
    public class UserdetailT implements java.io.Serializable {
        // Fields
        private Integer userid;
        private String idcard;
        private String address;
        private String decx;
    
        private UserT user;
        // Constructors
    
        /** default constructor */
        public UserdetailT() {
        
        }
    
        /** full constructor */
        public UserdetailT(String idcard, String address, String decx) {
            this.idcard = idcard;
            this.address = address;
            this.decx = decx;
        }
    
        // Property accessors
    
        public Integer getUserid() {
            return this.userid;
        }
    
        public void setUserid(Integer userid) {
            this.userid = userid;
        }
    
        public String getIdcard() {
            return this.idcard;
        }
    
        public void setIdcard(String idcard) {
            this.idcard = idcard;
        }
    
        public String getAddress() {
            return this.address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        public String getDecx() {
            return this.decx;
        }
    
        public void setDecx(String decx) {
            this.decx = decx;
        }
    
        public UserT getUser() {
            return user;
        }
    
        public void setUser(UserT user) {
            this.user = user;
        }
    
    }
    
    
    • 用户详情表配置文件设置如下:
    <?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">
    <!-- 
        Mapping file autogenerated by MyEclipse Persistence Tools
    -->
    <hibernate-mapping>
        <class name="cn.hd.onetoone.UserdetailT" table="userdetail_t" catalog="eleshop">
            <id name="userid" type="java.lang.Integer">
                <column name="userid" />
                <!--从表的主键设置  -->
                <generator class="foreign" >
                    <param name="property">user</param>
                </generator>
            </id>
            <property name="idcard" type="java.lang.String">
                <column name="idcard" length="20" />
            </property>
            <property name="address" type="java.lang.String">
                <column name="address" length="100" />
            </property>
            <property name="decx" type="java.lang.String">
                <column name="decx" length="100" />
            </property>
            <one-to-one name="user" class="cn.hd.onetoone.UserT"></one-to-one>
        </class>
    </hibernate-mapping>
    
    
    • 测试:
    package cn.hd.test;
    
    import static org.junit.Assert.*;
    
    import org.hibernate.Session;
    import org.junit.Test;
    
    import cn.hd.onetoone.UserT;
    import cn.hd.onetoone.UserdetailT;
    import cn.hd.utils.HibernateSessionFactory;
    
    public class oneToneTest {
    
        @Test
        public void test() {
            /**
             * 查询
             */
            /*
            Session session = HibernateSessionFactory.getSession();
            UserT userT =  session.get(UserT.class, 100);
            System.out.println(userT.getUsername());
            System.out.println(userT.getDetails().getAddress());
            HibernateSessionFactory.closeSession();
            */
            
            /**
             * 保存
             */
            
            //主表
            /*
            UserT userT = new UserT();
            userT.setUsername("测试01");
            userT.setSex("男");
            userT.setAge(24);
            //从表
            UserdetailT userdetailT = new UserdetailT();
            userdetailT.setIdcard("11111111");
            userdetailT.setAddress("广东");
            userdetailT.setDecx("描述描述");
            //相互设置
            userT.setDetails(userdetailT);
            userdetailT.setUser(userT);
            HibernateSessionFactory.save(userT);
            
            */
            
            /**
             * 更新
             */
            
            /*
            
            UserT userT = new UserT();
            userT.setUserid(102);
            userT.setUsername("测试02");
            userT.setSex("女");
            userT.setAge(24);
            //从表
            UserdetailT userdetailT = new UserdetailT();
            //如果这里不设置主键值,详情会进行插入操作,若果指定了,主表和从表都会进行更新
    //      userdetailT.setUserid(102);
            userdetailT.setIdcard("22222222");
            userdetailT.setAddress("兰州");
            userdetailT.setDecx("兰州人");
            //相互设置
            userT.setDetails(userdetailT);
            userdetailT.setUser(userT);
            HibernateSessionFactory.update(userT);
            
            */
            
            /**
             * 删除
             */
            
            UserT userT = new UserT();
            userT.setUserid(102);
            userT.setUsername("测试02");
            userT.setSex("女");
            userT.setAge(24);
            //从表
            UserdetailT userdetailT = new UserdetailT();
            userdetailT.setUserid(102);
            userdetailT.setIdcard("22222222");
            userdetailT.setAddress("兰州");
            userdetailT.setDecx("兰州人");
            //相互设置
            userT.setDetails(userdetailT);
            userdetailT.setUser(userT);
            HibernateSessionFactory.delete(userT);  
        }
    }
    
    

    测试结果:

    22:04:05,521  INFO [main] Version:37 - HHH000412: Hibernate Core {5.1.0.Final}
    22:04:05,530  INFO [main] Environment:198 - HHH000205: Loaded properties from resource hibernate.properties: {hibernate.connection.driver_class=org.h2.Driver, hibernate.service.allow_crawling=false, hibernate.dialect=org.hibernate.dialect.H2Dialect, hibernate.max_fetch_depth=5, hibernate.format_sql=true, hibernate.generate_statistics=true, hibernate.connection.username=sa, hibernate.connection.url=jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1, hibernate.bytecode.use_reflection_optimizer=false, hibernate.connection.pool_size=5}
    22:04:05,531  INFO [main] Environment:317 - HHH000021: Bytecode provider name : javassist
    22:04:06,071  INFO [main] Version:66 - HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
    22:04:07,410  WARN [main] connections:71 - HHH10001002: Using Hibernate built-in connection pool (not for production use!)
    22:04:07,418  INFO [main] connections:127 - HHH10001005: using driver [com.mysql.jdbc.Driver] at URL [jdbc:mysql://localhost:3306/eleshop]
    22:04:07,419  INFO [main] connections:136 - HHH10001001: Connection properties: {user=root, password=****}
    22:04:07,419  INFO [main] connections:141 - HHH10001003: Autocommit mode: false
    22:04:07,422  INFO [main] DriverManagerConnectionProviderImpl:39 - HHH000115: Hibernate connection pool size: 5 (min=1)
    Mon Sep 30 22:04:07 CST 2019 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
    22:04:07,818  INFO [main] Dialect:156 - HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
    22:04:08,136  INFO [main] EnversServiceImpl:91 - Envers integration enabled? : true
    22:04:08,688  INFO [main] Version:30 - HV000001: Hibernate Validator 5.2.4.Final
    22:04:08,877  INFO [main] Version:26 - HSEARCH000034: Hibernate Search 5.5.2.Final
    22:04:09,351  WARN [main] ConfigContext:346 - HSEARCH000075: Configuration setting hibernate.search.lucene_version was not specified: using LUCENE_CURRENT.
    Hibernate: 
        select
            usert0_.userid as userid1_0_0_,
            usert0_.username as username2_0_0_,
            usert0_.sex as sex3_0_0_,
            usert0_.age as age4_0_0_,
            userdetail1_.userid as userid1_2_1_,
            userdetail1_.idcard as idcard2_2_1_,
            userdetail1_.address as address3_2_1_,
            userdetail1_.decx as decx4_2_1_ 
        from
            eleshop.user_t usert0_ 
        left outer join
            eleshop.userdetail_t userdetail1_ 
                on usert0_.userid=userdetail1_.userid 
        where
            usert0_.userid=?
    张三
    北京
    }
    
    

    一对一外键映射

    一对一外键映射,将用户表看作是主表,用户详情表看作是从表,在从表中设置一个外键,设置从表中外键的唯一性。

    1.设计数据库表

    -- ----用户表
    create table userfk(
    userid int primary key auto_increment,
    username varchar(20),
    sex varchar(10),
    age int
    );
    
    -- --用户详情表--  
    create table userconf(
    id int primary key auto_increment,
    idcard varchar(20),
    address varchar(100),
    decx varchar(100),
    userid unique
    );
    
    为用户详情表设置外键

    反向生成用户表主表

    package cn.hd.onetoone2;
    
    import java.util.HashSet;
    import java.util.Set;
    
    /**
     * 1对1 外键关联主表
     */
    
    public class Userfk implements java.io.Serializable {
    
        // Fields
    
        private Integer userid;
        private String username;
        private String sex;
        private Integer age;
    
        //
        private Userconf conf;
        
        // Constructors
    
        /** default constructor */
        public Userfk() {
        }
    
        /** full constructor */
        public Userfk(String username, String sex, Integer age) {
            this.username = username;
            this.sex = sex;
            this.age = age;
        }
    
        // Property accessors
    
        public Integer getUserid() {
            return this.userid;
        }
    
        public void setUserid(Integer userid) {
            this.userid = userid;
        }
    
        public String getUsername() {
            return this.username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getSex() {
            return this.sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    
        public Integer getAge() {
            return this.age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public Userconf getConf() {
            return conf;
        }
    
        public void setConf(Userconf conf) {
            this.conf = conf;
        }
    
    
    }
    

    用户表主表配置文件配置:

    <?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">
    <!-- 
        Mapping file autogenerated by MyEclipse Persistence Tools
    -->
    <hibernate-mapping>
        <class name="cn.hd.onetoone2.Userfk" table="userfk" catalog="eleshop">
            <id name="userid" type="java.lang.Integer">
                <column name="userid" />
                <generator class="increment" />
            </id>
            <property name="username" type="java.lang.String">
                <column name="username" length="20" />
            </property>
            <property name="sex" type="java.lang.String">
                <column name="sex" length="10" />
            </property>
            <property name="age" type="java.lang.Integer">
                <column name="age" />
            </property>
            <one-to-one name="conf" property-ref="user" class="cn.hd.onetoone2.Userconf"></one-to-one>
        </class>
    </hibernate-mapping>
    
    

    用户详情表从表:

    package cn.hd.onetoone2;
    
    /**
     * 1对1 外键关联 从表
     */
    
    public class Userconf implements java.io.Serializable {
    
        // Fields
    
        private Integer did;
        private String idcard;
        private String address;
        private String decx;
    
        private Userfk user;
        
        // Constructors
    
        /** default constructor */
        public Userconf() {
        }
    
        /** full constructor */
        public Userconf(String idcard, String address, String decx) {
            this.idcard = idcard;
            this.address = address;
            this.decx = decx;
        }
    
        // Property accessors
    
        public Integer getDid() {
            return this.did;
        }
    
        public void setDid(Integer did) {
            this.did = did;
        }
    
    
        public String getIdcard() {
            return this.idcard;
        }
    
        public void setIdcard(String idcard) {
            this.idcard = idcard;
        }
    
        public String getAddress() {
            return this.address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        public String getDecx() {
            return this.decx;
        }
    
        public void setDecx(String decx) {
            this.decx = decx;
        }
    
        public Userfk getUser() {
            return user;
        }
    
        public void setUser(Userfk user) {
            this.user = user;
        }
    
    }
    

    用户详情表从表配置文件配置:

    <?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">
    <!-- 
        Mapping file autogenerated by MyEclipse Persistence Tools
    -->
    <hibernate-mapping>
        <class name="cn.hd.onetoone2.Userconf" table="userconf" catalog="eleshop">
            <id name="did" type="java.lang.Integer">
                <column name="did" />
                <generator class="increment" />
            </id>
            <property name="idcard" type="java.lang.String">
                <column name="idcard" length="20" />
            </property>
            <property name="address" type="java.lang.String">
                <column name="address" length="100" />
            </property>
            <property name="decx" type="java.lang.String">
                <column name="decx" length="100" />
            </property>
            <many-to-one name="user" class="cn.hd.onetoone2.Userfk" unique="true">
            <!-- 设置外键的字段 -->
                <column name="userid"></column>
            </many-to-one>
        </class>
    </hibernate-mapping>
    

    单元测试代码

    package cn.hd.onetoone2;
    
    import static org.junit.Assert.*;
    
    import org.hibernate.Session;
    import org.junit.Test;
    
    import cn.hd.utils.HibernateSessionFactory;
    
    public class oneToone2 {
    
        @Test
        public void test() {
            Session session = HibernateSessionFactory.getSession();
            Userfk userfk =  session.get(Userfk.class, 10);
            System.out.println(userfk.getUsername());
            System.out.println(userfk.getConf().getAddress());
            HibernateSessionFactory.closeSession();
        }
    
    }
    
    

    单元测试代码输出:

    22:28:13,541  INFO [main] Version:37 - HHH000412: Hibernate Core {5.1.0.Final}
    22:28:13,550  INFO [main] Environment:198 - HHH000205: Loaded properties from resource hibernate.properties: {hibernate.connection.driver_class=org.h2.Driver, hibernate.service.allow_crawling=false, hibernate.dialect=org.hibernate.dialect.H2Dialect, hibernate.max_fetch_depth=5, hibernate.format_sql=true, hibernate.generate_statistics=true, hibernate.connection.username=sa, hibernate.connection.url=jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1, hibernate.bytecode.use_reflection_optimizer=false, hibernate.connection.pool_size=5}
    22:28:13,551  INFO [main] Environment:317 - HHH000021: Bytecode provider name : javassist
    22:28:14,083  INFO [main] Version:66 - HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
    22:28:15,744  WARN [main] connections:71 - HHH10001002: Using Hibernate built-in connection pool (not for production use!)
    22:28:15,752  INFO [main] connections:127 - HHH10001005: using driver [com.mysql.jdbc.Driver] at URL [jdbc:mysql://localhost:3306/eleshop]
    22:28:15,752  INFO [main] connections:136 - HHH10001001: Connection properties: {user=root, password=****}
    22:28:15,753  INFO [main] connections:141 - HHH10001003: Autocommit mode: false
    22:28:15,756  INFO [main] DriverManagerConnectionProviderImpl:39 - HHH000115: Hibernate connection pool size: 5 (min=1)
    Mon Sep 30 22:28:15 CST 2019 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
    22:28:16,167  INFO [main] Dialect:156 - HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
    22:28:16,484  INFO [main] EnversServiceImpl:91 - Envers integration enabled? : true
    22:28:16,901  INFO [main] Version:30 - HV000001: Hibernate Validator 5.2.4.Final
    22:28:17,123  INFO [main] Version:26 - HSEARCH000034: Hibernate Search 5.5.2.Final
    Hibernate: 
        alter table eleshop.userconf 
            add constraint FKqyhe8oqv66vaxqoi92l14p002 
            foreign key (userid) 
            references eleshop.userfk (userid)
    22:28:17,751  WARN [main] ConfigContext:346 - HSEARCH000075: Configuration setting hibernate.search.lucene_version was not specified: using LUCENE_CURRENT.
    Hibernate: 
        select
            userfk0_.userid as userid1_3_0_,
            userfk0_.username as username2_3_0_,
            userfk0_.sex as sex3_3_0_,
            userfk0_.age as age4_3_0_,
            userconf1_.did as did1_1_1_,
            userconf1_.idcard as idcard2_1_1_,
            userconf1_.address as address3_1_1_,
            userconf1_.decx as decx4_1_1_,
            userconf1_.userid as userid5_1_1_ 
        from
            eleshop.userfk userfk0_ 
        left outer join
            eleshop.userconf userconf1_ 
                on userfk0_.userid=userconf1_.userid 
        where
            userfk0_.userid=?
    厂产
    兰州
    }
    

    一对多外键映射

    一对多外键映射简单的分析一下,如:部门和员工之间的关系,一个部门有多个员工,但一个员工只能有一个部门,我们可以在部门表添加外键,在员工表中的外键不能唯一,就构成一对多的映射关系。

    设计:部门表和员工表

    - --部门表 
    create table t_department(
    did int primary key auto_increment,
    dname varchar(20),
    decx varchar(100)
    );
    
    -- 员工表-- 
    create table t_emplyee(
    eid int primary key auto_increment,
    ename varchar(20),
    did int
    );
    
    

    为员工表添加外键did

    ADD CONSTRAINT `fk_did`
      FOREIGN KEY (`did`)
      REFERENCES `eleshop`.`t_department` (`did`)
      ON DELETE NO ACTION
      ON UPDATE NO ACTION;
    

    反向生成部门表,部门表作为主表文件

    package cn.hd.oneTomany;
    
    import java.util.HashSet;
    import java.util.Set;
    
    /**
     * TDepartment entity. @author MyEclipse Persistence Tools
     */
    
    public class TDepartment implements java.io.Serializable {
    
        // Fields
    
        private Integer did;
        private String dname;
        private String decx;
        private Set<TEmplyee> empts = new HashSet<TEmplyee>();
        // Constructors
    
        /** default constructor */
        public TDepartment() {
        }
    
        /** full constructor */
        public TDepartment(String dname, String decx) {
            this.dname = dname;
            this.decx = decx;
        }
    
        // Property accessors
    
        public Integer getDid() {
            return this.did;
        }
    
        public void setDid(Integer did) {
            this.did = did;
        }
    
        public String getDname() {
            return this.dname;
        }
    
        public void setDname(String dname) {
            this.dname = dname;
        }
    
        public String getDecx() {
            return this.decx;
        }
    
        public void setDecx(String decx) {
            this.decx = decx;
        }
    
        public Set<TEmplyee> getEmpts() {
            return empts;
        }
    
        public void setEmpts(Set<TEmplyee> empts) {
            this.empts = empts;
        }
    
    
    
    }
    

    部门表配置文件:

    <?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="cn.hd.oneTomany.TDepartment" table="t_department" catalog="eleshop">
            <id name="did" type="java.lang.Integer">
                <column name="did" />
                <generator class="increment" />
            </id>
            <property name="dname" type="java.lang.String">
                <column name="dname" length="20" />
            </property>
            <property name="decx" type="java.lang.String">
                <column name="decx" length="100" />
            </property>
            <!-- inverse 是否放弃维护关系
                false:主表维护从表
                true:主表不维护从表
             -->
            <set name="empts" cascade="none" inverse="false">
            <!-- 外键设置 -->
                <key column="did"></key>
                <!-- 从主表到从表一对多 -->
                <one-to-many class="cn.hd.oneTomany.TEmplyee"/>
            </set>
        </class>
    </hibernate-mapping>
    

    员工表从表文件:

    package cn.hd.oneTomany;
    
    /**
     * TEmplyee entity. @author MyEclipse Persistence Tools
     */
    
    public class TEmplyee implements java.io.Serializable {
    
        // Fields
    
        private Integer eid;
        private String ename;
        private TDepartment department;
        // Constructors
    
        /** default constructor */
        public TEmplyee() {
        }
    
        /** full constructor */
        public TEmplyee(String ename) {
            this.ename = ename;
        }
    
        // Property accessors
    
        public Integer getEid() {
            return this.eid;
        }
    
        public void setEid(Integer eid) {
            this.eid = eid;
        }
    
        public String getEname() {
            return this.ename;
        }
    
        public void setEname(String ename) {
            this.ename = ename;
        }
    
        public TDepartment getDepartment() {
            return department;
        }
    
        public void setDepartment(TDepartment department) {
            this.department = department;
        }
    
    }
    

    员工表从表配置文件:

    <?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">
    <!-- 
        Mapping file autogenerated by MyEclipse Persistence Tools
    -->
    <hibernate-mapping>
        <class name="cn.hd.oneTomany.TEmplyee" table="t_emplyee" catalog="eleshop">
            <id name="eid" type="java.lang.Integer">
                <column name="eid" />
                <generator class="increment" />
            </id>
         
            <property name="ename" type="java.lang.String">
                <column name="ename" length="20" />
            </property>
            <many-to-one name="department" class="cn.hd.oneTomany.TDepartment">
                <column name="did"></column>
            </many-to-one>
        </class>
    </hibernate-mapping>
    
    

    单元测试并输出:

    package cn.hd.test;
    
    import static org.junit.Assert.*;
    
    import java.util.HashSet;
    import java.util.Set;
    
    import org.hibernate.Session;
    import org.junit.Test;
    
    import cn.hd.oneTomany.TDepartment;
    import cn.hd.oneTomany.TEmplyee;
    import cn.hd.utils.HibernateSessionFactory;
    
    public class oneTmanyTest {
    
        @Test
        public void test() {
            
            /**
             * 查询数据
             */
            //从部门到员工一对多,设置主表配置 只能从部门查询到员工
            /*
            Session session = HibernateSessionFactory.getSession();
            TDepartment department =  session.get(TDepartment.class, 1);
            System.out.println(department.getDname());
            System.out.println(department.getEmpts().size());
            HibernateSessionFactory.closeSession();
            */
            //如果从员工查到所在部门,要在员工配置设置
            /*
            Session session = HibernateSessionFactory.getSession();
            TEmplyee eloyee =  session.get(TEmplyee.class, 1);
            System.out.println(eloyee.getEname());
            System.out.println(eloyee.getDepartment().getDname());
            HibernateSessionFactory.closeSession();
            */
            
            
            
            /**
             * 保存数据
             */
            
            /*
            TDepartment department = new TDepartment();
            department.setDname("小卖部");
            
            TEmplyee e1 = new TEmplyee();
            e1.setEname("啊啊啊啊");
            //如果配置文件主表放弃维护主表 ,需要设置:
    //      e1.setDepartment(department);
            
            TEmplyee e2 = new TEmplyee();
            e2.setEname("bbbbb");
            
            //如果配置文件主表放弃维护主表 ,需要设置:
    //      e2.setDepartment(department);
            Set<TEmplyee> set = new HashSet<TEmplyee>();
            set.add(e1);
            set.add(e2);
            department.setEmpts(set);
            
            HibernateSessionFactory.save(department);
            */
            
            /**
             * 删除数据 1.删除主表和从表数据
             *  cascade="all" inverse="false"  级连关系,主表维护从表,要删除,主表先把只想从表的外键置为null,然后删除主表和从表
             *  cascade="all" inverse="true"   级连关系,主表不维护从表,要删除,先删除从表,再删除主表
             * 删除数据 2.只删除主表,不删除从表 
             *  cascade="none" inverse="true"  不是级连关系 主表不维护从表   要删除主表,主表在从表有外键约束 无法删除
             *  cascade="none" inverse="false"  不是级连关系 主表维护从表   要删除主表,主表会将从表的外键约束置为null,会将主表删除
             */
            Session session = HibernateSessionFactory.getSession();
            TDepartment department2 =  session.get(TDepartment.class, 2);
            HibernateSessionFactory.delete(department2);
            HibernateSessionFactory.closeSession();
            
        }
    }
    

    多对多映射关系

    多对多映射关系可以看作是双向的一对多,比如用户和角色之间的关系,一个用户用多种角色,一个用户可以是管理员,可以是普通用户,可以是vip用户,一个角色可以有多个用户。往往这种多对多关系的处理,需要一张中间表来关联,中间表的两个主键分别是两张表的外键。

    设计数据库表:

    -- 角色表
    create table t_role(
    rid int primary key auto_increment,
    rname varchar(10),
    rdecx varchar(20)
    );
    -- 菜单表
    create table t_menu(
    mid int primary key auto_increment,
    mname varchar(10),
    mdecx varchar(20)
    );
    -- 中间表
    create table t_role_menu(
    mid int,
    rid int
    );
    

    添加两个外键分别引用角色表和菜单表:


    用户表和角色表必须创建一个中间表来关联,mid指向菜单表,rid指向角色表

    反向生成角色表:

    package cn.hd.manyTomany;
    
    import java.util.HashSet;
    import java.util.Set;
    
    /**
     * TRole entity. @author MyEclipse Persistence Tools
     */
    
    public class TRole  implements java.io.Serializable {
    
    
        // Fields    
    
         private Integer rid;
         private String rname;
         private String rdecx;
         
         private Set<TMenu> menus = new HashSet<TMenu>();
    
        // Constructors
    
        /** default constructor */
        public TRole() {
        }
    
        /** full constructor */
        public TRole(String rname, String rdecx) {
            this.rname = rname;
            this.rdecx = rdecx;
        }
       
        // Property accessors
    
        public Integer getRid() {
            return this.rid;
        }
        
        public void setRid(Integer rid) {
            this.rid = rid;
        }
    
        public String getRname() {
            return this.rname;
        }
        
        public void setRname(String rname) {
            this.rname = rname;
        }
    
        public String getRdecx() {
            return this.rdecx;
        }
        
        public void setRdecx(String rdecx) {
            this.rdecx = rdecx;
        }
    
    
        public Set<TMenu> getMenus() {
            return menus;
        }
    
    
        public void setMenus(Set<TMenu> menus) {
            this.menus = menus;
        }
       
    }
    

    角色表配置文件:

    <?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">
    <!-- 
        Mapping file autogenerated by MyEclipse Persistence Tools
    -->
    <hibernate-mapping>
        <class name="cn.hd.manyTomany.TRole" table="t_role" catalog="eleshop">
            <id name="rid" type="java.lang.Integer">
                <column name="rid" />
                <generator class="increment" />
            </id>
            <property name="rname" type="java.lang.String">
                <column name="rname" length="20" />
            </property>
            <property name="rdecx" type="java.lang.String">
                <column name="rdecx" length="100" />
            </property>
            <set name="menus" cascade="all" inverse="true" table="t_role_menu" schema="root">
               <!-- 这个表的主键在中间表中所对应的外键 -->
               <key column="rid"></key>
               <many-to-many class="cn.hd.manyTomany.TMenu" column="mid"></many-to-many>
            </set>
        </class>
    </hibernate-mapping>
    

    反向生成菜单表:

    package cn.hd.manyTomany;
    
    import java.util.HashSet;
    import java.util.Set;
    
    /**
     * TMenu entity. @author MyEclipse Persistence Tools
     */
    
    public class TMenu  implements java.io.Serializable {
    
    
        // Fields    
    
         private Integer mid;
         private String mname;
         private String mdecx;
          
         private Set<TRole> roles = new HashSet<TRole>();
    
        // Constructors
    
        /** default constructor */
        public TMenu() {
        }
    
        
        /** full constructor */
        public TMenu(String mname, String mdecx) {
            this.mname = mname;
            this.mdecx = mdecx;
        }
    
       
        // Property accessors
    
        public Integer getMid() {
            return this.mid;
        }
        
        public void setMid(Integer mid) {
            this.mid = mid;
        }
    
        public String getMname() {
            return this.mname;
        }
        
        public void setMname(String mname) {
            this.mname = mname;
        }
    
        public String getMdecx() {
            return this.mdecx;
        }
        
        public void setMdecx(String mdecx) {
            this.mdecx = mdecx;
        }
    
    
        public Set<TRole> getRoles() {
            return roles;
        }
    
    
        public void setRoles(Set<TRole> roles) {
            this.roles = roles;
        }
       
    }
    

    菜单表配置文件配置:

    <?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">
    <!-- 
        Mapping file autogenerated by MyEclipse Persistence Tools
    -->
    <hibernate-mapping>
        <class name="cn.hd.manyTomany.TMenu" table="t_menu" catalog="eleshop">
            <id name="mid" type="java.lang.Integer">
                <column name="mid" />
                <generator class="increment" />
            </id>
            <property name="mname" type="java.lang.String">
                <column name="mname" length="20" />
            </property>
            <property name="mdecx" type="java.lang.String">
                <column name="mdecx" length="100" />
            </property>
            <set name="roles" cascade="all" inverse="false" table="t_role_menu" schema="root">
                <key column="mid"></key>
                <many-to-many class="cn.hd.manyTomany.TRole" column="rid"></many-to-many>
            </set>
        </class>
    </hibernate-mapping>
    

    单元测试并输出:

    
    import cn.hd.manyTomany.TMenu;
    import cn.hd.manyTomany.TRole;
    import cn.hd.utils.HibernateSessionFactory;
    
    public class manyToManyTest {
    
        @Test
        public void test() {
            
            Session session = HibernateSessionFactory.getSession();
            TRole role = new TRole();
            role.setRname("高级管理员");
            TMenu menu1 = new TMenu();
            menu1.setMname("权限管理");
            TMenu menu2 = new TMenu();
            menu2.setMname("角色管理");
            TMenu menu3 = new TMenu();
            menu3.setMname("系统管理");
            Set<TMenu> set = new HashSet<TMenu>();
            set.add(menu1);
            set.add(menu2);
            set.add(menu3);
            role.setMenus(set);
            HibernateSessionFactory.save(role);
            HibernateSessionFactory.closeSession();
        }
    
    }
    

    忘了的话可以拿出来翻一翻,关于一对一,一对多,多对多的一些配置就介绍到这里,如果有不妥之处欢迎批评指正。最后再补充一下Hibernate关于删除,修改和插入做一个简单的封装,因为涉及到数据库事务这方面。

    HibernateSessionFactory简单封装用于测试输出:

    package cn.hd.utils;
    
    import org.hibernate.HibernateException;
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;
    import org.hibernate.service.ServiceRegistry;
    
    import cn.hd.oneToone.UserT;
    
    import org.hibernate.boot.MetadataSources;
    import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
    
    /**
     * Configures and provides access to Hibernate sessions, tied to the
     * current thread of execution.  Follows the Thread Local Session
     * pattern, see {@link http://hibernate.org/42.html }.
     */
    public class HibernateSessionFactory {
    
        /** 
         * Location of hibernate.cfg.xml file.
         * Location should be on the classpath as Hibernate uses  
         * #resourceAsStream style lookup for its configuration file. 
         * The default classpath location of the hibernate config file is 
         * in the default package. Use #setConfigFile() to update 
         * the location of the configuration file for the current session.   
         */
        private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
        private static org.hibernate.SessionFactory sessionFactory;
        
        private static Configuration configuration = new Configuration();
        private static ServiceRegistry serviceRegistry; 
    
        static {
            try {
                configuration.configure();
                serviceRegistry = new StandardServiceRegistryBuilder().configure().build();
                try {
                    sessionFactory = new MetadataSources(serviceRegistry).buildMetadata().buildSessionFactory();
                } catch (Exception e) {
                    StandardServiceRegistryBuilder.destroy(serviceRegistry);
                    e.printStackTrace();
                }
            } catch (Exception e) {
                System.err.println("%%%% Error Creating SessionFactory %%%%");
                e.printStackTrace();
            }
        }
        private HibernateSessionFactory() {
        }
        
        /**
         * Returns the ThreadLocal Session instance.  Lazy initialize
         * the <code>SessionFactory</code> if needed.
         *
         *  @return Session
         *  @throws HibernateException
         */
        public static Session getSession() throws HibernateException {
            Session session = (Session) threadLocal.get();
    
            if (session == null || !session.isOpen()) {
                if (sessionFactory == null) {
                    rebuildSessionFactory();
                }
                session = (sessionFactory != null) ? sessionFactory.openSession()
                        : null;
                threadLocal.set(session);
            }
    
            return session;
        }
    
        /**
         *  Rebuild hibernate session factory
         *
         */
        public static void rebuildSessionFactory() {
            try {
                configuration.configure();
                serviceRegistry = new StandardServiceRegistryBuilder().configure().build();
                try {
                    sessionFactory = new MetadataSources(serviceRegistry).buildMetadata().buildSessionFactory();
                } catch (Exception e) {
                    StandardServiceRegistryBuilder.destroy(serviceRegistry);
                    e.printStackTrace();
                }
            } catch (Exception e) {
                System.err.println("%%%% Error Creating SessionFactory %%%%");
                e.printStackTrace();
            }
        }
    
        /**
         *  Close the single hibernate session instance.
         *
         *  @throws HibernateException
         */
        public static void closeSession() throws HibernateException {
            Session session = (Session) threadLocal.get();
            threadLocal.set(null);
    
            if (session != null) {
                session.close();
            }
        }
    
        /**
         *  return session factory
         *
         */
        public static org.hibernate.SessionFactory getSessionFactory() {
            return sessionFactory;
        }
        /**
         *  return hibernate configuration
         *
         */
        public static Configuration getConfiguration() {
            return configuration;
        }
        
        /**
         * 查询
         */
        
        public static UserT query(Object object) {
            Session session = getSession();
            UserT userT =   session.get(UserT.class, 100);
            closeSession();
            return userT;
        }
        
        /**
         * 保存
         */
        
        public static void save(Object object) {
            Session session = getSession();
            Transaction transaction = null;
            try {
                transaction = session.beginTransaction();
                session.save(object);
                transaction.commit();
            } catch (Exception e) {
                e.printStackTrace();
                transaction.rollback();
            }finally {
                closeSession();
            }
        }
        
        /**
         * 更新
         */
        
        public static void update(Object object) {
            Session session = getSession();
            Transaction transaction = null;
            try {
                transaction = session.beginTransaction();
                session.update(object);
                transaction.commit();
            } catch (Exception e) {
                e.printStackTrace();
                transaction.commit();
            }finally {
                closeSession();
            }
        }
        
        /**
         * 删除
         */
        
        public static void delete(Object object) {
            Session session = getSession();
            Transaction transaction = null;
            try {
                transaction = session.beginTransaction();
                session.delete(object);
                transaction.commit();
            } catch (Exception e) {
                e.printStackTrace();
                transaction.commit();
            }finally {
                closeSession();
            }
        }
    
    }
    

    相关文章

      网友评论

          本文标题:常见的映射关系

          本文链接:https://www.haomeiwen.com/subject/uouhpctx.html