<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆 - 117  文章 - 72  trackbacks - 0

    聲明:原創(chuàng)作品(標(biāo)有[原]字樣)轉(zhuǎn)載時(shí)請(qǐng)注明出處,謝謝。

    常用鏈接

    常用設(shè)置
    常用軟件
    常用命令
     

    訂閱

    訂閱

    留言簿(7)

    隨筆分類(130)

    隨筆檔案(123)

    搜索

    •  

    積分與排名

    • 積分 - 155593
    • 排名 - 391

    最新評(píng)論

    [標(biāo)題]:Hibernate一對(duì)多(單向)
    [時(shí)間]:2009-6-12
    [摘要]:單向一對(duì)多關(guān)聯(lián)只需要在"一方"進(jìn)行配置即可,"多方"無(wú)需額外配置。
    [關(guān)鍵字]:外鍵,inverse,Hibernate,Set,一對(duì)多,單向,ORM,mapping,關(guān)系數(shù)據(jù)庫(kù),映射
    [環(huán)境]:MyEclipse7 , JDK6,Hibernate3.2,Tomcat6,MySQL 5.1.34-community
    [作者]:Winty (wintys@gmail.com) http://m.tkk7.com/wintys

    [正文]:
        Hibernate一對(duì)多關(guān)聯(lián),例如一個(gè)用戶有多張銀行卡(只考慮用戶到銀行卡的單向一對(duì)多關(guān)聯(lián))。由于是學(xué)習(xí)Hibernate原理,并沒(méi)有使用工具自動(dòng)生成代碼等。
        單向一對(duì)多關(guān)聯(lián)只需要在"一方"進(jìn)行配置即可,"多方"無(wú)需額外配置。

    a.Java程序中所要做的一對(duì)多:
    public class User{
        ...
        private Set<Card> cards;
        ...
    }

    public class Card{
        ...
    }


    b.Hibernate中所要做的一對(duì)多:
    User.hbm.xml:
    ...
    <set name="cards" inverse="false" cascade="all">
        <key column="userId" />
        <one-to-many class="wintys.hibernate.onetomany.Card" />
    </set>
    ...

    c.數(shù)據(jù)庫(kù)中的一對(duì)多:
    而對(duì)應(yīng)的數(shù)據(jù)庫(kù)中,只要相應(yīng)在Card對(duì)應(yīng)的物理表中添加外鍵userId(不要設(shè)為NOT NULL)即可。


    詳細(xì)的MyEclipse WebProject如下:
    1、實(shí)體類:
    用戶類User.java:
    package wintys.hibernate.onetomany;

    import java.util.Set;

    public class User {
        private String id;
        private String name;
        private Set<Card> cards;
        
        public String getId() {
            return id;
        }
        public void setId(String id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public void setCards(Set<Card> cards) {
            this.cards = cards;
        }
        public Set<Card> getCards() {
            return cards;
        }   
    }

    銀行卡類Card.java:
    package wintys.hibernate.onetomany;

    public class Card {
        private String id;
        private float balance;
        
        public Card(){
        }
        public Card(float balance){
            this.balance = balance;
        }
        public String getId() {
            return id;
        }
        public void setId(String id) {
            this.id = id;
        }
        public float getBalance() {
            return balance;
        }
        public void setBalance(float balance) {
            this.balance = balance;
        }   
    }

    2、數(shù)據(jù)庫(kù)表:
    數(shù)據(jù)庫(kù)是MySQL 5.1.34-community。

    用戶表:
    CREATE TABLE myuser(
        id               VARCHAR(50)  NOT NULL,
        name         VARCHAR(100),
        PRIMARY KEY(id)
    );

    銀行卡表:
    CREATE TABLE mycard(
        id               VARCHAR(50)  NOT NULL,
        balance      FLOAT(7,2),
        userId       VARCHAR(50),
        PRIMARY KEY(id)
    );


    3、映射文件:
    用戶類映射文件/src/wintys/hibernate/onetomany/User.hbm.xml:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <!--
        Mapping file autogenerated by MyEclipse Persistence Tools
    -->

    <hibernate-mapping>
        <class name="wintys.hibernate.onetomany.User" table="myuser" catalog="db">
            <id name="id" type="string">
                <column name="id" not-null="true"/>
                <generator class="uuid.hex" />
            </id>
            <property name="name" type="java.lang.String" column="name" />
            
            <set name="cards" inverse="false" cascade="all">
                <key column="userId" />
                <one-to-many class="wintys.hibernate.onetomany.Card" />
            </set>
        </class>
    </hibernate-mapping>


    銀行卡映射文件/src/wintys/hibernate/onetomany/User.hbm.xml:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <!--
        Mapping file autogenerated by MyEclipse Persistence Tools
    -->

    <hibernate-mapping>
        <class name="wintys.hibernate.onetomany.Card" table="mycard" catalog="db">
            <id name="id" type="string">
                <column name="id" not-null="true"/>
                <generator class="uuid.hex" />
            </id>
            <property name="balance" />
        </class>
    </hibernate-mapping>


    Hibernate配置文件:/src/hibernate.cfg.xml:
    <?xml version='1.0' encoding='UTF-8'?>
    <!DOCTYPE hibernate-configuration PUBLIC
              "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
              "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

    <!-- Generated by MyEclipse Hibernate Tools.                   -->
    <hibernate-configuration>

    <session-factory>
        <property name="connection.username">root</property>
        <property name="connection.url">
            jdbc:mysql://localhost:3306/db?useUnicode=true&amp;characterEncoding=utf-8
        </property>
        <property name="dialect">
            org.hibernate.dialect.MySQLDialect
        </property>
        <property name="myeclipse.connection.profile">MySQLDriver</property>
        <property name="connection.password">root</property>
        <property name="connection.driver_class">
            com.mysql.jdbc.Driver
        </property>
        <property name="show_sql">true</property>
        <mapping resource="wintys/hibernate/onetomany/User.hbm.xml" />
        <mapping resource="wintys/hibernate/onetomany/Card.hbm.xml" />

    </session-factory>

    </hibernate-configuration>


    4、使用測(cè)試:
    /src/wintys/hibernate/onetomany/HibernateDAO.java:
    package wintys.hibernate.onetomany;
    import java.util.List;

    public interface HibernateDAO {
        public void insert();
        public List<User> selectAll();
    }



    /src/wintys/hibernate/onetomany/HibernateDAOBean.java:
    package wintys.hibernate.onetomany;

    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;

    import org.hibernate.HibernateException;
    import org.hibernate.Query;
    import org.hibernate.Session;
    import org.hibernate.Transaction;

    public class HibernateDAOBean implements HibernateDAO {

        public void insert() throws HibernateException {
            Transaction tc = null;
            try{
                Set<Card> cards = new HashSet<Card>();
                Card c1,c2,c3;
                c1 = new Card(7641.96f);
                c2 = new Card(654.8f);
                c3 = new Card(3650f);
                
                cards.add(c1);
                cards.add(c2);
                cards.add(c3);
                
                User user = new User();
                user.setName("Tom");
                user.setCards(cards);
                
                Session session = HibernateUtil.getSession();
                tc = session.beginTransaction();
                            
                /*
                配置文件中的cascade="true"時(shí),所以無(wú)需手動(dòng)保存c1,c2,c3
                session.save(c1);
                session.save(c2);
                session.save(c3);
                */
                session.save(user);
                
                tc.commit();
            }catch(HibernateException e){
                try{
                    if(tc != null)
                        tc.rollback();
                }catch(Exception ex){
                    System.err.println(ex.getMessage());
                }
                System.err.println(e.getMessage());
            }finally{
                HibernateUtil.closeSession();           
            }
        }

        @SuppressWarnings("unchecked")
        public List<User> selectAll() throws HibernateException {
            List<User> users = null;
            Transaction tc = null;
            try{
                Session session = HibernateUtil.getSession();
                tc = session.beginTransaction();
                            
                Query query = session.createQuery("from User");
                users = query.list();
                
                tc.commit();
            }catch(HibernateException e){
                try{
                    if(tc != null){
                        tc.rollback();
                        users = null;
                    }
                }catch(Exception ex){
                    System.err.println(ex.getMessage());
                }
                System.err.println(e.getMessage());
            }finally{
                //HibernateUtil.closeSession();         
            }
            
            return users;
        }
    }



    /src/wintys/hibernate/onetomany/HibernateUtil.java:
    package wintys.hibernate.onetomany;

    import org.hibernate.HibernateException;
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.Configuration;

    /**
     * Hibernate Session管理
     * @author Winty
     */
    public class HibernateUtil {
        private static SessionFactory factory = null;
        private static ThreadLocal<Session> threadLocal;
            
        static {
            try{
                factory = new Configuration()
                        .configure()
                        .buildSessionFactory();
            }catch(HibernateException e){
                System.err.println(e.getMessage());
            }
            
            threadLocal = new ThreadLocal<Session>();
        }
        
        private HibernateUtil(){    
        }
        
        public static Session getSession()throws HibernateException{
            Session session = threadLocal.get();
            if(session == null){
                session = factory.openSession();
                threadLocal.set(session);
            }
            
            return session;
        }
        
        public static void closeSession()throws HibernateException{
            Session session = threadLocal.get();
            if(session != null){
                session.close();
            }
            threadLocal.set(null);
        }
    }



    /index.jsp:
    <%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>
    <%@ page import="wintys.hibernate.onetomany.*"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <title>My JSP 'index.jsp' starting page</title>
      </head>
     
      <body>
        <%
            List<User> users = null;
            HibernateDAO dao = new HibernateDAOBean();
            dao.insert();
            users = dao.selectAll();
            
            Iterator<User> it = users.iterator();
            while(it.hasNext()){
                User user = it.next();
                String id = user.getId();
                String name = user.getName();
                out.println("id:" + id + "<br />");
                out.println("name:" + name + "<br />");
                out.println("cards:<br />");
                
                Set<Card> cards = user.getCards();
                Iterator<Card> itc = cards.iterator();
                while(itc.hasNext()){
                    Card card = itc.next();
                    String cardId = card.getId();
                    float balance = card.getBalance();
                    out.println("&nbsp;&nbsp;&nbsp; cardId:" + cardId + "<br />");
                    out.println("&nbsp;&nbsp;&nbsp; balance:" + balance + "<br />");
                }
                out.println("<hr/>");
            }
        
         %>

      </body>
    </html>


    5、運(yùn)行結(jié)果:
    控制臺(tái)顯示:
    ......
    Hibernate: insert into db.myuser (name, id) values (?, ?)
    Hibernate: insert into db.mycard (balance, id) values (?, ?)
    Hibernate: insert into db.mycard (balance, id) values (?, ?)
    Hibernate: insert into db.mycard (balance, id) values (?, ?)
    Hibernate: update db.mycard set userId=? where id=?
    Hibernate: update db.mycard set userId=? where id=?
    Hibernate: update db.mycard set userId=? where id=?
    ......


    index.jsp頁(yè)面顯示:
    id:402881e421d4d0be0121d4d20e140005
    name:Tom
    cards:
        cardId:402881e421d4d0be0121d4d20e230008
        balance:654.8
        cardId:402881e421d4d0be0121d4d20e230006
        balance:7641.96
        cardId:402881e421d4d0be0121d4d20e230007
        balance:3650.0


    6、注意的問(wèn)題:
    a、錯(cuò)誤提示:Field 'userId' doesn't have a default value。
        一開始把"userId"設(shè)成NOT NULL,但是Hibernate先執(zhí)行的是:
    "insert into db.mycard (balance, id) values (?, ?)"
    然后才執(zhí)行"update db.mycard set userId=? where id=?",
    而userId在insert時(shí)是沒(méi)有寫入值的,所以就會(huì)報(bào)錯(cuò)。把userId的NOT NULL去掉即可。
    b、User.hbm.xml中要設(shè)置cascade="all",或其它有效值,不然,在保存User對(duì)象時(shí),相關(guān)的Card對(duì)象不會(huì)被保存。
    c、User.hbm.xml中set標(biāo)簽的inverse屬性不能設(shè)置為"true",inverse的默認(rèn)值是"false",所以不加inverse也可以??磿险f(shuō):在一對(duì)多的關(guān)聯(lián)關(guān)系實(shí)現(xiàn)中,最好設(shè)置inverse="true",將有助于性能的改善。所以一開始就用了inverse="true",User和Card對(duì)象都分別正確寫入數(shù)據(jù)庫(kù)了,但是就是userId字段沒(méi)有被自動(dòng)寫入。
    myuser表:
    +--------------------------------------------+------+
    | id                                 | name |
    +--------------------------------------------+------+
    | 402881e421d4d0be0121d4d20e140005  | Tom  |
    +--------------------------------------------+------+
    mycard表:
    +--------------------------------------------+---------+---------
    | id                                | balance | userId
    +--------------------------------------------+---------+---------
    | 402881e421d4d0be0121d4d20e230006  | 7641.96 | NULL
    | 402881e421d4d0be0121d4d20e230007  | 3650.00 | NULL
    |
    | 402881e421d4d0be0121d4d20e230008  |  654.80  | NULL
    +--------------------------------------------+---------+---------
    搞了半天,原來(lái)在本例應(yīng)該把inverse設(shè)為false。inverse還是很有用的,只是用錯(cuò)了地方。

    [參考資料]:
    [1] Hibernate 一對(duì)多外鍵單向關(guān)聯(lián)--熔 巖 : http://lavasoft.blog.51cto.com/62575/39317
    [2] Hibernate應(yīng)用(二)單向一對(duì)多及雙向一對(duì)多的配置: http://suhaoyuan.spaces.live.com/Blog/cns!2659D3AC8253C554!217.entry
    [3] Hibernate單向一對(duì)多應(yīng)注意的問(wèn)題 : http://blog.chinaunix.net/u2/88320/showart_1716296.html
    [4] hibernate一對(duì)多例子-已更新(二) : http://m.tkk7.com/wujun/archive/2008/08/04/39700.html
    原創(chuàng)作品,轉(zhuǎn)載請(qǐng)注明出處。
    作者:Winty (wintys@gmail.com)
    博客:http://m.tkk7.com/wintys

    posted on 2009-06-13 00:12 天堂露珠 閱讀(12838) 評(píng)論(4)  編輯  收藏 所屬分類: Hibernate

    FeedBack:
    # re: [原]Hibernate一對(duì)多(單向) 2009-06-13 09:19 metadmin
    級(jí)聯(lián)查詢,好復(fù)雜,而且容易出錯(cuò)。我和周邊搞金融開發(fā)的朋友都不大用。


    ---------------------------------
    解開權(quán)限與業(yè)務(wù)耦合,提高開發(fā)效率
    細(xì)粒度權(quán)限管理軟件 試用版下載
    http://www.metadmin.com

      回復(fù)  更多評(píng)論
      
    # re: [原]Hibernate一對(duì)多(單向) 2011-07-27 14:31 heoolo
    謝謝分享,很詳細(xì)  回復(fù)  更多評(píng)論
      
    # re: [原]Hibernate一對(duì)多(單向) 2014-04-29 11:54 11
    很帥氣~  回復(fù)  更多評(píng)論
      
    # re: [原]Hibernate一對(duì)多(單向) 2016-03-04 15:04 87
    太感謝了 非常仔細(xì)
      回復(fù)  更多評(píng)論
      
    主站蜘蛛池模板: 亚洲精品色午夜无码专区日韩| 国产免费播放一区二区| 亚洲成人中文字幕| 免费在线一级毛片| 毛片免费在线观看网址| 99久久免费看国产精品| 精品一区二区三区免费视频| 亚洲国产精品无码久久九九大片 | 亚洲冬月枫中文字幕在线看| 亚洲最大激情中文字幕| 亚洲Av无码乱码在线观看性色| www视频免费看| 在线观看免费av网站| 今天免费中文字幕视频| 国产免费牲交视频免费播放| 国产亚洲Av综合人人澡精品| 亚洲无码一区二区三区| 亚洲午夜电影在线观看高清| 久久亚洲日韩精品一区二区三区| 久久精品国产亚洲AV麻豆不卡| 亚洲色欲色欲www在线丝| 久久久久亚洲av毛片大| 亚洲男人天堂2020| 亚洲国产一区视频| 婷婷综合缴情亚洲狠狠尤物| 伊人久久亚洲综合影院| 国产jizzjizz视频全部免费| 国产美女无遮挡免费视频| 午夜成人免费视频| 日本免费网站观看| 又粗又大又猛又爽免费视频| 亚洲成a人片在线观看日本麻豆| 免费一级毛片一级毛片aa| 日本中文一区二区三区亚洲| 亚洲乱码中文字幕手机在线| 国产亚洲精品线观看动态图| 国产亚洲人成A在线V网站| 亚洲精品成人网站在线观看| 亚洲成熟xxxxx电影| 色拍自拍亚洲综合图区| 亚洲一级高清在线中文字幕|