Session.get抛出异常而不是null

时间:2015-07-02 14:30:20

标签: java hibernate

我在程序下面运行,并期望hibernate会调用ObjectNotFoundException来调用loadnull来调用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)

1 个答案:

答案 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 );
                }
            };
        }