0

首先让我说,我不是 Java 程序员,但我正在尝试学习一些新的(对我而言)东西。

我有以下两个 DAO: 货架

package org.sample.bookshelf.model;

import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity  
@Table(name="shelves") 
public class Shelf {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;
    private String name;

    @OneToMany(cascade=CascadeType.ALL)  
    @JoinTable(name="shelf_books",   
        joinColumns = {@JoinColumn(name="shelf_id", referencedColumnName="id")},  
        inverseJoinColumns = {@JoinColumn(name="book_id", referencedColumnName="id")}  
    )
    private Set<Book> shelfBooks; 

    public Shelf() {}

    public Shelf(String name) {
        this.name = name;
    }

    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }


    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    public Set<Book> getShelfBooks() {
        return shelfBooks;
    }
    public void setShelfBooks(Set<Book> shelfBooks) {
        this.shelfBooks = shelfBooks;
    }
}

package org.sample.bookshelf.model;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity  
@Table(name="books") 
public class Book {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;
    private String title;

    @OneToOne(cascade=CascadeType.ALL)
    @JoinTable(name="shelf_books",
        joinColumns = {@JoinColumn(name="book_id", referencedColumnName="id")},  
        inverseJoinColumns = {@JoinColumn(name="shelf_id", referencedColumnName="id")}  
    )
    private Shelf block;

    public Book() {
    }

    public Book(String title)
    {
        this.title = title;
    }

    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public Shelf getShelf() {
        return block;
    }

    public void setShelf(Shelf block) {
        this.block = block;
    }
}

如您所见,它们是按表关联的:*shelf_books*

现在在BookDaoImpl中,我想拥有一种全有或全无行为的方法,这可以让我保存多本书,如下所示:

@Override
public void saveMulti(List<Book> books) {
    Session sess = sessionFactory.openSession();
    org.hibernate.Transaction tx = null;
    try {
        tx = sess.beginTransaction();
        int i = 0;
        for (Book b : books) {
            logger.debug(String.format("%d %s ", b.getId(), b.getTitle()));
            sess.saveOrUpdate(b);

            i++;
            if (i == 20) {
                sess.flush();
                sess.clear();
                i = 0;
            }
        }
        logger.debug("saving...");
        tx.commit();
        logger.debug("done...");

    } catch (RuntimeException e) {
        if (tx != null) tx.rollback();
        e.printStackTrace();

    } finally {
        sess.close();
    }
}

由于某种原因,关联表的数据是添加而不是删除,它在包含删除集合 org.sample.bookshelf.model.Shelf.shelfBooks的以下日志中可见:

16:08:13,857 DEBUG BookDaoImpl:58 - saving...
16:08:13,857 DEBUG AbstractTransactionImpl:175 - committing
16:08:13,857 DEBUG AbstractFlushingEventListener:149 - Processing flush-time cascades
16:08:13,857 DEBUG AbstractFlushingEventListener:189 - Dirty checking collections
16:08:13,859 DEBUG AbstractFlushingEventListener:123 - Flushed: 0 insertions, 1 updates, 0 deletions to 11 objects
16:08:13,859 DEBUG AbstractFlushingEventListener:130 - Flushed: 0 (re)creations, 0 updates, 1 removals to 0 collections
16:08:13,859 DEBUG EntityPrinter:114 - Listing entities:
16:08:13,860 DEBUG EntityPrinter:121 - org.sample.bookshelf.model.Book{id=2, title=The City of the Sun, block=org.sample.bookshelf.model.Shelf#1}
16:08:13,860 DEBUG EntityPrinter:121 - org.sample.bookshelf.model.Shelf{id=1, shelfBooks=null, name=dystopia}
16:08:13,860 DEBUG EntityPrinter:121 - org.sample.bookshelf.model.Book{id=1, title=1984, block=org.sample.bookshelf.model.Shelf#1}
16:08:13,860 DEBUG EntityPrinter:121 - org.sample.bookshelf.model.Book{id=6, title=Logan's Run, block=org.sample.bookshelf.model.Shelf#1}
16:08:13,860 DEBUG EntityPrinter:121 - org.sample.bookshelf.model.Book{id=5, title=Slaughterhouse Five, block=org.sample.bookshelf.model.Shelf#1}
16:08:13,860 DEBUG EntityPrinter:121 - org.sample.bookshelf.model.Book{id=4, title=Fahrenheit 451, block=org.sample.bookshelf.model.Shelf#1}
16:08:13,861 DEBUG EntityPrinter:121 - org.sample.bookshelf.model.Book{id=3, title=The Honeymoon Trip of Mr. Hamilton, block=org.sample.bookshelf.model.Shelf#1}
16:08:13,861 DEBUG EntityPrinter:121 - org.sample.bookshelf.model.Book{id=10, title=Brave New World, block=org.sample.bookshelf.model.Shelf#1}
16:08:13,861 DEBUG EntityPrinter:121 - org.sample.bookshelf.model.Book{id=9, title=Lord of the Flies, block=org.sample.bookshelf.model.Shelf#1}
16:08:13,861 DEBUG EntityPrinter:121 - org.sample.bookshelf.model.Book{id=8, title=Do Androids Dream of Electric Sheep?, block=org.sample.bookshelf.model.Shelf#1}
16:08:13,861 DEBUG EntityPrinter:121 - org.sample.bookshelf.model.Book{id=7, title=The Futurological Congress, block=org.sample.bookshelf.model.Shelf#1}
16:08:13,867 DEBUG SQL:109 - /* update org.sample.bookshelf.model.Shelf */ update shelves set name=? where id=?
16:08:13,869 DEBUG AbstractCollectionPersister:1174 - Deleting collection: [org.sample.bookshelf.model.Shelf.shelfBooks#1]
16:08:13,869 DEBUG SQL:109 - /* delete collection org.sample.bookshelf.model.Shelf.shelfBooks */ delete from shelf_books where shelf_id=?
16:08:13,870 DEBUG AbstractCollectionPersister:1232 - Done deleting collection
16:08:14,199 DEBUG JdbcTransaction:113 - committed JDBC Connection
16:08:14,199 DEBUG JdbcTransaction:126 - re-enabling autocommit
16:08:14,200 DEBUG BookDaoImpl:60 - done...

我猜出于某种原因,书架不知道添加的书籍,为了使其完整,这就是我添加数据的方式:

        String titles[] = {
                "1984",
                "The City of the Sun",
                "The Honeymoon Trip of Mr. Hamilton",
                "Fahrenheit 451",
                "Slaughterhouse Five",
                "Logan's Run",
                "The Futurological Congress",
                "Do Androids Dream of Electric Sheep?",
                "Lord of the Flies",
                "Brave New World",      
        };
        Vector<Book> books = new Vector<Book>(titles.length);
        for (int i=0; i<titles.length; ++i) {
            Book book = new Book(titles[i]);
            book.setShelf(shelf);
            books.add(book);
        }
        bookDao.saveMulti(books);

如您所见,我没有在任何地方调用shelf.setShelfBooks,如果我这样做,一切似乎都很好,但是hibernate的作用看起来很糟糕,请查看以下日志的片段:

16:20:15,015 DEBUG EntityPrinter:121 - org.sample.bookshelf.model.Book{id=8, title=Do Androids Dream of Electric Sheep?, block=org.sample.bookshelf.model.Shelf#1}
16:20:15,015 DEBUG EntityPrinter:121 - org.sample.bookshelf.model.Book{id=7, title=Fahrenheit 451, block=org.sample.bookshelf.model.Shelf#1}
16:20:15,021 DEBUG SQL:109 - /* update org.sample.bookshelf.model.Shelf */ update shelves set name=? where id=?
16:20:15,023 DEBUG AbstractCollectionPersister:1174 - Deleting collection: [org.sample.bookshelf.model.Shelf.shelfBooks#1]
16:20:15,023 DEBUG SQL:109 - /* delete collection org.sample.bookshelf.model.Shelf.shelfBooks */ delete from shelf_books where shelf_id=?
16:20:15,026 DEBUG AbstractCollectionPersister:1232 - Done deleting collection
16:20:15,027 DEBUG AbstractCollectionPersister:1256 - Inserting collection: [org.sample.bookshelf.model.Shelf.shelfBooks#1]
16:20:15,028 DEBUG SQL:109 - /* insert collection row org.sample.bookshelf.model.Shelf.shelfBooks */ insert into shelf_books (shelf_id, book_id) values (?, ?)
16:20:15,030 DEBUG SQL:109 - /* insert collection row org.sample.bookshelf.model.Shelf.shelfBooks */ insert into shelf_books (shelf_id, book_id) values (?, ?)
16:20:15,030 DEBUG SQL:109 - /* insert collection row org.sample.bookshelf.model.Shelf.shelfBooks */ insert into shelf_books (shelf_id, book_id) values (?, ?)

我有感觉,我做错了,谁能告诉我什么应该是正确的方法来做我想做的事?

4

1 回答 1

1

我没有比这两个实体更进一步,因为它们的映射是错误的,这可能是你的问题的原因。

第一个问题:

您将书籍声明为

@OneToMany(cascade=CascadeType.ALL)  
@JoinTable(name="shelf_books",   
    joinColumns = {@JoinColumn(name="shelf_id", referencedColumnName="id")},  
    inverseJoinColumns = {@JoinColumn(name="book_id", referencedColumnName="id")}  
)
private Set<Book> shelfBooks; 

这意味着存在 OneToMany 关联,由连接表映射。

然后你声明以下内容:

@OneToOne(cascade=CascadeType.ALL)
@JoinTable(name="shelf_books",
    joinColumns = {@JoinColumn(name="book_id", referencedColumnName="id")},  
    inverseJoinColumns = {@JoinColumn(name="shelf_id", referencedColumnName="id")}  
)
private Shelf block;

那没有意义。

您可能希望关联是双向的。由于一侧是 OneToMany,因此另一侧必须是 ManyToOne。并且在双向关联中,一侧必须是相反侧(使用 mappedBy 属性,并且不声明关联是如何映射的,因为它已经在另一侧定义),并且一侧必须是所有者侧。在 OneToMany 关联中,反面必须是一侧。所以账套必须声明为:

@OneToMany(cascade = CascadeType.ALL, mappedBy = "block") 
private Set<Book> shelfBooks; 

另请注意,在 ManyToOne 上使用 CascadeType.ALL 没有多大意义。您不希望书架在其中包含的一本书被删除后立即被删除。除非您真正了解其含义,否则我建议您删除所有级联。

于 2014-02-02T15:41:41.603 回答