<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>.逆水行舟</title>
    <description>.Nobody can help me except myself.</description>
    <link>http://qmy.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
          <item>
        <title>我的YY：ORM的由来</title>
        <author>qmy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://qmy.javaeye.com">qmy</a>&nbsp;
                    链接：<a href="http://qmy.javaeye.com/blog/183573" style="color:red;">http://qmy.javaeye.com/blog/183573</a>&nbsp;
          发表时间: 2008年04月17日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          考虑这么一种情况：<br /><br />现有一个博客系统，用户可以写日志，可以给日志分类。<br /><br />那么我们需要两张表如下：<br /><br /><strong>T_BLOG</strong><br />=========<br />id<br />classId<br />title<br />content<br />publishTime<br /><br /><br /><strong>T_BLOG_CLASS</strong><br />=========<br />id<br />className<br /><br /><br />如果用传统的JDBC编码，PO应该是这么设计的<br /><br /><pre name="code" class="java">public class BlogPO{
    private String id;
    private String blogClassId;
    private String title;
    private String content;
    private Date publishTime;

    //setter & getter
}

public class BlogClassPO{
    private String id;
    private String className;

    //getter & setter
}</pre><br /><br />假设现在我们需要在页面显示日志列表及其分类的名称，我们的DAO中就需要一个查询的方法返回一个List&lt;BlogPO>，但是BlogPO没有className这个成员，如何显示className呢？难道再去数据库查询一次？这方法显然不太可取。于是有人想到了VO，创建一个和页面表单对应的VO，然后DAO里的这个查询方法用联接查询返回一个List&lt;VO>，这样只需要一次查询，就能得到页面需要的数据，问题似乎解决了。<br /><br />时间一久，项目慢慢变得庞大，页面越来越多，成堆的VO等着我们去维护，维护成本越来越高，于是有人开始寻找另外的解决方法，有人想到把BlogPO设计成这样：<br /><br /><pre name="code" class="java">public class BlogPO{
    private String id;
    private BlogClassPO blogClass;
    private String title;
    private String content;
    private Date publishTime;

    //setter & getter
}</pre><br /><br />DAO的查询方法直接返回一个List&lt;BlogPO>，需要className时，可以调用BlogPO.getBlogClass().getclassName()。于是ORM诞生了。<br /><br />最初的ORM是在加载BlogPO时自动加载BlogClassPO的，后来遇到BlogPO里有些成员是个集合（比如Set）或者是个Blob/Clob字段的情况，在不必要加载时候自动加载它会增加很多开销，于是出现了“延迟加载”技术。再后来…………<br /><br />自动生成SQL语句我觉得倒是次要的，ORM和传统的JDBC编程最本质的区别是：BlogPO里应该持有一个BlogClassPO成员还是一个String blogClassId成员。<br /><br />上面只是我的猜想，只是今天自己在写blog，不用hibernate而用jdbc来写，遇到这么个问题，然后想了这么多，突然觉得自己明白了ORM的用处。呵呵，YY而已。
          <br/>
          <span style="color:red;">
            <a href="http://qmy.javaeye.com/blog/183573#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/70' target='_blank'><span style="color:red;font-weight:bold;">第二届网络工程师侠客行大会5月24日杭州举行</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 17 Apr 2008 01:07:30 +0800</pubDate>
        <link>http://qmy.javaeye.com/blog/183573</link>
        <guid>http://qmy.javaeye.com/blog/183573</guid>
      </item>
          <item>
        <title>重写eq/hc方法有必要区分POJO一对一、一对多和多对多的情况吗？</title>
        <author>qmy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://qmy.javaeye.com">qmy</a>&nbsp;
                    链接：<a href="http://qmy.javaeye.com/blog/141017" style="color:red;">http://qmy.javaeye.com/blog/141017</a>&nbsp;
          发表时间: 2007年11月15日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          (起个标题很头疼……表达能力相当差)<br /><br /><a href="http://www.javaeye.com/post/47540" target="_blank">http://www.javaeye.com/post/47540</a><br />看了上面的那个帖子后，我觉得有必要区分。<br /><br />分析了一下，帖子里说ID作为主键会出问题主要是在用到Set的情况下（也就是一对多或者多对多），比如说某用户保存了两个新建的email。<br /><pre name="code" class="java">
......
User user = session.load(User.class,new Integer(1));
Email e1 = new Email();
Email e2 = new Email();
e1.setAddress("xxx@xx.com");
e2.setAddress("yyy@yy.com");
user.getEmails().add(e1);//这时候id为null，即使equals方法里逻辑是“id为空则返回false”
user.getEmails().add(e2);//hashcode值又该如何计算？所以这时候eq/hc方法要用业务关键属性来写
session.save(user);
.....
</pre><br /><br />但业务键值比对的方法有时候好像又不适用<br />举个例子吧：<br />一对一的情况。现在有两个表，用户表和用户联系方式表，用户表作为主表，联系方式表的主键作为外键与用户表关联。联系方式表除了主键其余字段都可为空，这时候如果用“值比对”的方式写eq/hc，很有可能逻辑上应该不相等的两个对象equals的结果是true（比如说两个不同对象的所有属性值都为空），得到的hashcode也是一样的。这时候为了避免这个问题，eq/hc方法可以用id来写。因为是一对一的关系，用不到Set，所以也不会产生上面提到的问题。<br /><br />总结了一下，就是：<br />1、不改写eq/hc，在跨session操作时会出现问题；<br />2、一对多或者多对多关系中，pojo的eq/hc不能用id来写，而应该用业务关键属性来写；<br />3、一对一关系中，pojo的eq/hc可以用id来写，如果用属性值比对反而有可能出问题。<br /><br /><br />以上只是个人观点，不知道对不对。
          <br/>
          <span style="color:red;">
            <a href="http://qmy.javaeye.com/blog/141017#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/70' target='_blank'><span style="color:red;font-weight:bold;">第二届网络工程师侠客行大会5月24日杭州举行</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 15 Nov 2007 22:27:27 +0800</pubDate>
        <link>http://qmy.javaeye.com/blog/141017</link>
        <guid>http://qmy.javaeye.com/blog/141017</guid>
      </item>
      </channel>
</rss>