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

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

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

    隨筆 - 117  文章 - 72  trackbacks - 0

    聲明:原創作品(標有[原]字樣)轉載時請注明出處,謝謝。

    常用鏈接

    常用設置
    常用軟件
    常用命令
     

    訂閱

    訂閱

    留言簿(7)

    隨筆分類(130)

    隨筆檔案(123)

    搜索

    •  

    積分與排名

    • 積分 - 155602
    • 排名 - 391

    最新評論

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

    [正文]:
        Hibernate一對多關聯,例如一個用戶有多張銀行卡(只考慮用戶到銀行卡的單向一對多關聯)。由于是學習Hibernate原理,并沒有使用工具自動生成代碼等。
        單向一對多關聯只需要在"一方"進行配置即可,"多方"無需額外配置。

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

    public class Card{
        ...
    }


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

    c.數據庫中的一對多:
    而對應的數據庫中,只要相應在Card對應的物理表中添加外鍵userId(不要設為NOT NULL)即可。


    詳細的MyEclipse WebProject如下:
    1、實體類:
    用戶類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、數據庫表:
    數據庫是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、使用測試:
    /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"時,所以無需手動保存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、運行結果:
    控制臺顯示:
    ......
    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頁面顯示:
    id:402881e421d4d0be0121d4d20e140005
    name:Tom
    cards:
        cardId:402881e421d4d0be0121d4d20e230008
        balance:654.8
        cardId:402881e421d4d0be0121d4d20e230006
        balance:7641.96
        cardId:402881e421d4d0be0121d4d20e230007
        balance:3650.0


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

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

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

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


    ---------------------------------
    解開權限與業務耦合,提高開發效率
    細粒度權限管理軟件 試用版下載
    http://www.metadmin.com

      回復  更多評論
      
    # re: [原]Hibernate一對多(單向) 2011-07-27 14:31 heoolo
    謝謝分享,很詳細  回復  更多評論
      
    # re: [原]Hibernate一對多(單向) 2014-04-29 11:54 11
    很帥氣~  回復  更多評論
      
    # re: [原]Hibernate一對多(單向) 2016-03-04 15:04 87
    太感謝了 非常仔細
      回復  更多評論
      
    主站蜘蛛池模板: 任你躁在线精品免费| 一本色道久久综合亚洲精品蜜桃冫| 国产精品无码亚洲一区二区三区| 亚洲精品视频免费看| 亚洲最大福利视频网站| 91青青国产在线观看免费| 亚洲精品蜜桃久久久久久| 久久精品国产免费一区| 亚洲成色999久久网站| 国产成人久久AV免费| 18gay台湾男同亚洲男同| 91久久精品国产免费直播| 亚洲国产成人超福利久久精品| 国产免费不卡视频| 久久乐国产综合亚洲精品| 日本免费观看网站| 边摸边脱吃奶边高潮视频免费| 亚洲视频在线一区二区| 国产成人免费ā片在线观看老同学| 亚洲欧洲在线观看| 一二三四影视在线看片免费| 亚洲国产精品久久久久秋霞小| 免费一级成人毛片| 成在线人免费无码高潮喷水| 亚洲视频在线一区| 女人18毛片免费观看| 一级毛片免费全部播放| 亚洲精品无码乱码成人| 免费能直接在线观看黄的视频 | 在线a人片天堂免费观看高清 | 免费精品久久久久久中文字幕| 激情97综合亚洲色婷婷五| 91老湿机福利免费体验| 国产成人精品亚洲一区| 亚洲国产精品VA在线看黑人| 免费阿v网站在线观看g| 无遮挡a级毛片免费看| 亚洲av日韩av天堂影片精品| 毛片视频免费观看| 中文精品人人永久免费| 亚洲色精品VR一区区三区|