我在程序下面运行,并期望hibernate会调用ObjectNotFoundException
来调用load
和null
来调用get
。但我在输出中看不到book : null
。
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class LoadAndGetTest {
public static void main(String[] args) {
Configuration configuration = new Configuration().configure();
SessionFactory factory = configuration.buildSessionFactory();
Session session = factory.openSession();
try {
Book book = (Book) session.load(Book.class, "DOES_NOT_EXIST");
} catch(Exception exception) {
exception.printStackTrace();
}
Book book = (Book) session.get(Book.class, "DOES_NOT_EXIST");
System.out.println("book : "+ book);
}
}
Book.java
import java.util.Date;
import java.util.List;
public class Book {
private String isbn;
private String name;
private Publisher publisher;
private Date publishDate;
private int price;
private List chapters;
// Getters and Setters
public Book() {
}
public Book(String isbn, String name, Publisher publisher,
Date publishDate, int price, List chapters) {
super();
this.isbn = isbn;
this.name = name;
this.publisher = publisher;
this.publishDate = publishDate;
this.price = price;
this.chapters = chapters;
}
public String getIsbn() {
return isbn;
}
public String getName() {
return name;
}
public Publisher getPublisher() {
return publisher;
}
public Date getPublishDate() {
return publishDate;
}
public int getPrice() {
return price;
}
public List getChapters() {
return chapters;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
public void setName(String name) {
this.name = name;
}
public void setPublisher(Publisher publisher) {
this.publisher = publisher;
}
public void setPublishDate(Date publishDate) {
this.publishDate = publishDate;
}
public void setPrice(int price) {
this.price = price;
}
public void setChapters(List chapters) {
this.chapters = chapters;
}
}
和book.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">
<hibernate-mapping package="com.chatar.hibernate.receipes.example.domain">
<class name="Book" table="BOOK">
<id name="isbn" type="string" column="ISBN" />
<property name="name" type="string" column="BOOK_NAME" />
<property name="publishDate" type="date" column="PUBLISH_DATE" />
<property name="price" type="int" column="PRICE" />
</class>
</hibernate-mapping>
并且
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">
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">
org.apache.derby.jdbc.EmbeddedDriver
</property>
<property name="connection.url">jdbc:derby://localhost:1527/BookShopDB</property>
<property name="connection.username">book</property>
<property name="connection.password">book</property>
<property name="dialect">org.hibernate.dialect.DerbyDialect</property>
<mapping resource="com/chatar/hibernate/receipes/example/domain/book.hbm.xml" />
</session-factory>
</hibernate-configuration>
这是例外
950 [main] INFO org.hibernate.event.def.DefaultLoadEventListener - Error performing load command
org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.chatar.hibernate.receipes.example.domain.Book#DOES_NOT_EXIST]
at org.hibernate.impl.SessionFactoryImpl$2.handleEntityNotFound(SessionFactoryImpl.java:449)
at org.hibernate.event.def.DefaultLoadEventListener.returnNarrowedProxy(DefaultLoadEventListener.java:320)
at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:277)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:152)
at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:1080)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:997)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:990)
at com.chatar.hibernate.receipes.example.LoadAndGetTest.main(LoadAndGetTest.java:21)
Exception in thread "main" org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.chatar.hibernate.receipes.example.domain.Book#DOES_NOT_EXIST]
at org.hibernate.impl.SessionFactoryImpl$2.handleEntityNotFound(SessionFactoryImpl.java:449)
at org.hibernate.event.def.DefaultLoadEventListener.returnNarrowedProxy(DefaultLoadEventListener.java:320)
at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:277)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:152)
at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:1080)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:997)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:990)
at com.chatar.hibernate.receipes.example.LoadAndGetTest.main(LoadAndGetTest.java:21)
但是如果我删除了对load的调用,那么我可以在输出中看到book : null
。
LoadAndGetTest.java
没有致电load
public class LoadAndGetTest {
public static void main(String[] args) {
Configuration configuration = new Configuration().configure();
SessionFactory factory = configuration.buildSessionFactory();
Session session = factory.openSession();
Book book = (Book) session.get(Book.class, "DOES_NOT_EXIST");
System.out.println("book : "+ book);
}
}
输出
book:null
同样,当我在get
之前和之后两次致电load
时,我可以在打印之前看到它,而不是在打印之后。
此处再次LoadAndGetTest
public class LoadAndGetTest {
public static void main(String[] args) {
Configuration configuration = new Configuration().configure();
SessionFactory factory = configuration.buildSessionFactory();
Session session = factory.openSession();
Book book1 = (Book) session.get(Book.class, "DOES_NOT_EXIST");
System.out.println("book : "+ book1);
try {
Book book = (Book) session.load(Book.class, "DOES_NOT_EXIST");
} catch(Exception exception) {
exception.printStackTrace();
}
Book book = (Book) session.get(Book.class, "DOES_NOT_EXIST");
System.out.println("book : "+ book);
}
}
输出
book : null
1292 [main] INFO org.hibernate.event.def.DefaultLoadEventListener - Error performing load command
org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.chatar.hibernate.receipes.example.domain.Book#DOES_NOT_EXIST]
at org.hibernate.impl.SessionFactoryImpl$2.handleEntityNotFound(SessionFactoryImpl.java:449)
at org.hibernate.event.def.DefaultLoadEventListener.returnNarrowedProxy(DefaultLoadEventListener.java:320)
at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:277)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:152)
at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:1080)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:997)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:990)
at com.chatar.hibernate.receipes.example.LoadAndGetTest.main(LoadAndGetTest.java:24)
Exception in thread "main" org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.chatar.hibernate.receipes.example.domain.Book#DOES_NOT_EXIST]
at org.hibernate.impl.SessionFactoryImpl$2.handleEntityNotFound(SessionFactoryImpl.java:449)
at org.hibernate.event.def.DefaultLoadEventListener.returnNarrowedProxy(DefaultLoadEventListener.java:320)
at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:277)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:152)
at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:1080)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:997)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:990)
at com.chatar.hibernate.receipes.example.LoadAndGetTest.main(LoadAndGetTest.java:24)
答案 0 :(得分:0)
确定。检查完源代码并跟踪堆栈跟踪后,我能够弄清楚:
看来如果你在调用加载后调用get,Hibernate会使用代理对象。这是调用的顺序,
1. Book book = (Book) session.get(Book.class, "DOES_NOT_EXIST");
2. SessionImpl.get
public Object get(Class entityClass, Serializable id) throws HibernateException {
return get( entityClass.getName(), id );
}
3. fireLoad(event, LoadEventListener.GET);
4. DefaultLoadEventListener.onLoad
//return a proxy if appropriate
if ( event.getLockMode() == LockMode.NONE ) {
event.setResult( proxyOrLoad(event, persister, keyToLoad, loadType) );
}
5. DefaultLoadEventListener.proxyOrLoad
if ( proxy != null ) {
return returnNarrowedProxy( event, persister, keyToLoad, options, persistenceContext, proxy );
}
6. DefaultLoadEventListener.returnNarrowedProxy
if ( !options.isAllowProxyCreation() ) {
impl = load( event, persister, keyToLoad, options );
if ( impl == null ) {
event.getSession().getFactory().getEntityNotFoundDelegate().handleEntityNotFound( persister.getEntityName(), keyToLoad.getIdentifier());
}
}
7. SessionFactoryImpl.handleEntityNotFound
// EntityNotFoundDelegate
EntityNotFoundDelegate entityNotFoundDelegate = cfg.getEntityNotFoundDelegate();
if ( entityNotFoundDelegate == null ) {
entityNotFoundDelegate = new EntityNotFoundDelegate() {
public void handleEntityNotFound(String entityName, Serializable id) {
throw new ObjectNotFoundException( id, entityName );
}
public boolean isEntityNotFoundException(RuntimeException exception) {
return ObjectNotFoundException.class.isInstance( exception );
}
};
}