对双向相关bean的更多思考

来源:互联网 发布:淘宝宝贝详情页图片 编辑:程序博客网 时间:2024/05/17 17:41

  • 对双向相关bean的更多思考

对双向相关bean的更多思考

上次我们讨论了如何用双向相关bean实现一对多关系,今天我们来讨论另一种重要的关系,即多对多关系。为了能更好的说明这种关系,我们用作者(Writer)和书(Book)的关系来说明。
- 以下代码描述了一个图书类(Book)和一个作者类(Writer)以及它们共同继承的基类(PojoSupport),图书和作者关系为“一本书可能由多个作者创作,一位作者可能写了多本书,为此我们还需要一个体现作者和图书关系的BookWriter类。”

public class Book extends PojoSupport<Book> {    public int id;    public java.lang.String title;    public java.util.Collection<BookWriter> bookWriter;    public java.util.Collection<BookWriter> getBookWriter() {        if (bookWriter == null)            bookWriter = new java.util.LinkedHashSet<BookWriter>();        return bookWriter;    }    public java.util.Iterator<BookWriter> getIteratorBookWriter() {        if (bookWriter == null)            bookWriter = new java.util.LinkedHashSet<BookWriter>();        return bookWriter.iterator();    }    public void setBookWriter(java.util.Collection<BookWriter> newBookWriter) {        removeAllBookWriter();        for (java.util.Iterator<BookWriter> iter = newBookWriter.iterator(); iter                .hasNext();)            addBookWriter((BookWriter) iter.next());    }    public void addBookWriter(BookWriter newBookWriter) {        if (newBookWriter == null)            return;        if (this.bookWriter == null)            this.bookWriter = new java.util.LinkedHashSet<BookWriter>();        if (!this.bookWriter.contains(newBookWriter)) {            this.bookWriter.add(newBookWriter);            newBookWriter.setBook(this);        }    }    public void removeBookWriter(BookWriter oldBookWriter) {        if (oldBookWriter == null)            return;        if (this.bookWriter != null)            if (this.bookWriter.contains(oldBookWriter)) {                this.bookWriter.remove(oldBookWriter);                oldBookWriter.setBook((Book) null);            }    }    public void removeAllBookWriter() {        if (bookWriter != null) {            BookWriter oldBookWriter;            for (java.util.Iterator<BookWriter> iter = getIteratorBookWriter(); iter                    .hasNext();) {                oldBookWriter = (BookWriter) iter.next();                iter.remove();                oldBookWriter.setBook((Book) null);            }        }    }    @Override    public int getId() {        return id;    }    @Override    public void setId(int id) {        this.id = id;    }    public java.lang.String getTitle() {        return title;    }    public void setTitle(java.lang.String title) {        this.title = title;    }}
public class Writer extends PojoSupport<Writer> {    public int id;    public java.lang.String name;    public java.util.Collection<BookWriter> bookWriter;    public java.util.Collection<BookWriter> getBookWriter() {        if (bookWriter == null)            bookWriter = new java.util.LinkedHashSet<BookWriter>();        return bookWriter;    }    public java.util.Iterator<BookWriter> getIteratorBookWriter() {        if (bookWriter == null)            bookWriter = new java.util.LinkedHashSet<BookWriter>();        return bookWriter.iterator();    }    public void setBookWriter(java.util.Collection<BookWriter> newBookWriter) {        removeAllBookWriter();        for (java.util.Iterator<BookWriter> iter = newBookWriter.iterator(); iter                .hasNext();)            addBookWriter((BookWriter) iter.next());    }    public void addBookWriter(BookWriter newBookWriter) {        if (newBookWriter == null)            return;        if (this.bookWriter == null)            this.bookWriter = new java.util.LinkedHashSet<BookWriter>();        if (!this.bookWriter.contains(newBookWriter)) {            this.bookWriter.add(newBookWriter);            newBookWriter.setWriter(this);        }    }    public void removeBookWriter(BookWriter oldBookWriter) {        if (oldBookWriter == null)            return;        if (this.bookWriter != null)            if (this.bookWriter.contains(oldBookWriter)) {                this.bookWriter.remove(oldBookWriter);                oldBookWriter.setWriter((Writer) null);            }    }    public void removeAllBookWriter() {        if (bookWriter != null) {            BookWriter oldBookWriter;            for (java.util.Iterator<BookWriter> iter = getIteratorBookWriter(); iter                    .hasNext();) {                oldBookWriter = (BookWriter) iter.next();                iter.remove();                oldBookWriter.setWriter((Writer) null);            }        }    }    @Override    public int getId() {        return id;    }    @Override    public void setId(int id) {        this.id = id;    }    public java.lang.String getName() {        return name;    }    public void setName(java.lang.String name) {        this.name = name;    }}

辅助类PojoSupport的用处是提供一些辅助方法,使得从数据库中加载的对象可以像java本地对象一样具有等价替换的功能

public abstract class PojoSupport<T extends PojoSupport<T>> {    public int hashCode() {        final int prime = 31;        int result = 1;        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());        return result;    }    public boolean equals(Object obj) {        if (this == obj)            return true;        if (obj == null)            return false;        if (getClass() != obj.getClass())            return false;        PojoSupport<?> other = (PojoSupport<?>) obj;        if (getId() == null) {            if (other.getId() != null)                return false;        } else if (!getId().equals(other.getId()))            return false;        return true;    }}

以及一个专门用于描述Book和Writer关系的关系类BookWriter。我们约定,对于专门用于描述多对多关系的类,采用两个类名连写的方式命名(因此在此处命名BookWriter或者WriterBook都是可以的)。

public class BookWriter extends PojoSupport<BookWriter> {    public int id;    public Book book;    public Writer writer;    public Book getBook() {        return book;    }    public void setBook(Book newBook) {        if (this.book == null || !this.book.equals(newBook)) {            if (this.book != null) {                Book oldBook = this.book;                this.book = null;                oldBook.removeBookWriter(this);            }            if (newBook != null) {                this.book = newBook;                this.book.addBookWriter(this);            }        }    }    public Writer getWriter() {        return writer;    }    public void setWriter(Writer newWriter) {        if (this.writer == null || !this.writer.equals(newWriter)) {            if (this.writer != null) {                Writer oldWriter = this.writer;                this.writer = null;                oldWriter.removeBookWriter(this);            }            if (newWriter != null) {                this.writer = newWriter;                this.writer.addBookWriter(this);            }        }    }    @Override    public int getId() {        return id;    }    @Override    public void setId(int id) {        this.id = id;    }}

细心的读者可以已经看出来了,多对多关系其实就是两个一对多关系,只不过这两个“一”是同一个类。那我们写了这么多代码之后,这个模型的质量到底如何呢?我们使用以下代码来描述这样一个场景:

作者张三(w1)写了两本书,名为《3的故事》(b3)和《7的传奇》(b7),作者李四(w2)也写了两本书,名为《4的诗歌》(b4)和《7的传奇》(b7),其中《7的传奇》(b7)为张三李四合著。

        Writer w1 = new Writer();        w1.setId(1);        w1.setName("张三");        Writer w2 = new Writer();        w2.setId(2);        w2.setName("李四");        Book b3 = new Book();        b3.setId(3);        b3.setTitle("3的故事");        Book b4 = new Book();        b4.setId(4);        b4.setTitle("4的诗歌");        Book b7 = new Book();        b7.setId(7);        b7.setTitle("7的传奇");        BookWriter bw31 = new BookWriter();        bw31.setId(31);        bw31.setBook(b3);        bw31.setWriter(w1);        BookWriter bw42 = new BookWriter();        bw42.setId(42);        bw42.setBook(b4);        bw42.setWriter(w2);        BookWriter bw71 = new BookWriter();        bw71.setId(71);        bw71.setBook(b7);        bw71.setWriter(w1);        BookWriter bw72 = new BookWriter();        bw72.setId(72);        bw72.setBook(b7);        bw72.setWriter(w2);        w1.addBookWriter(bw31);        w1.addBookWriter(bw71);        w2.addBookWriter(bw42);        w2.addBookWriter(bw72);

我们会发现,把以上模型中w1、w2、b3、b4、b7任何一个序列化后,得到的信息量都是完全相同的。(具体原因可见我的前一篇博文《对于双向相关bean的一些思考》>http://blog.csdn.net/ro4074/article/details/43966013)

以把w1序列化为例,我们把它序列化后会发现:

    w1.name = "张三";    w1.bookWriter[0].book.title = "3的故事";    w1.bookWriter[1].book.title = "7的传奇";    w1.bookWriter[1].book.bookWriter[0].writer.name = "张三";    w1.bookWriter[1].book.bookWriter[1].writer.name = "李四";    w1.bookWriter[1].book.bookWriter[1].writer.bookWriter[0].book.title = "4的诗歌";    w1.bookWriter[1].book.bookWriter[1].writer.bookWriter[1].book.title = "7的传奇";

由此可见我们的模型还是很可靠的,就是调用的时候有些繁琐。但是在实际开发网络应用时,如果使用mybatis或其他orm工具,可以很轻易地做到这一点。比如一句像下面这样的代码:

writerService.loadBook(writer, bookWriterCondition);

就可以把指定writer的所有bookWriter全都装载进来,而这些bookWriter中又都包含了相应的book。

以上我们用代码诠释了多对多这一逻辑关系,看起来已经没有任何问题能难住我们了…………且慢,真实世界从来都是残酷的(对程序员来说尤甚),我们遇到的绝大部分对象关系都不是单纯的一对多或者多对多,而是两者的结合。比如:

还是writer和book间的关系,现在每本书都有且只有一个主要作者(mainWriter)和一些合著者(coWriter),同时这些书的英文版又需要高水平的译者,这些译者同样也是作家,所以我们假定每本书还需要一个唯一的主要译者(mainTranslator)和一些合作译者(coTranslator),这里面的mainWriter、coWriter、mainTranslator、coTranslator都属于Writer类,那要如何用双向相关bean实现Book和Writer的关系呢,这就放到下一篇博文《对双向相关bean的最终思考》来说吧。

0 0
原创粉丝点击