【发布时间】:2014-02-02 15:28:32
【问题描述】:
首先让我说,我不是 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 中,我想拥有具有 all-or-nothing 行为的方法, 这可以让我保存多本书,如下所示:
@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();
}
}
由于某种原因,关联表的数据被添加而不是被删除,它在以下包含 delete collection 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...
我猜出于某种原因 Shelf 不知道添加的书籍,为了使其完整,这就是我添加数据的方式:
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 (?, ?)
我有感觉,我做错了,谁能告诉我应该以正确的方式来做我想做的事?
【问题讨论】:
标签: spring hibernate one-to-many jointable batch-insert