2016-07-13 98 views
1

我正在使用SpringFramework構建一個Web應用程序。在數據訪問層中,我使用Hibernate來查詢MySQL中的數據,該數據工作正常。我SessionFactory是這種方法建立:使用休眠和JPA構建EntityManagerFactory

public SessionFactory sessionFactory() throws HibernateException { 
    return new org.hibernate.cfg.Configuration() 
      .configure() 
      .buildSessionFactory(); 
} 

今天我要與JPA,這需要一個EntityManagerFactory我的數據訪問整合,IMO我只需要改變上面的代碼爲以下:

@Bean 
public EntityManagerFactory entityManagerFactory() throws HibernateException { 
    return new org.hibernate.cfg.Configuration() 
      .configure()     
      .buildSessionFactory(); 
} 

僅僅是因爲SessionFactory延伸了EntityManagerFactory。但是我有一個例外

java.lang.ClassCastException: org.hibernate.internal.SessionFactoryImpl不能轉換到 javax.persistence.EntityManagerFactory

這是很奇怪的,因爲SessionFactoryImpl實現SessionFactorySessionFactory延伸EntityManagerFactory。我不知道演員爲什麼失敗。

我的問題是:1.爲什麼演員無效? 2.使用Hibernate構建EntityManagerFactory的正確方法是什麼?

編輯調試說

factory instanceof SessionFactory   //true 
factory instanceof EntityManagerFactory //false 

SessionFactory

public interface SessionFactory extends EntityManagerFactory, HibernateEntityManagerFactory, Referenceable, Serializable, Closeable 

我敢肯定,所有上述EntityManagerFactoryjavax.persistence.EntityManagerFactory源。

+0

爲什麼你會用這麼複雜的方式做到這一點?爲什麼不使用@PersistenceContext註釋將entityManager注入到bean中? – wallenborn

+0

@wallenborn我是新來的Java(以及春季框架),所以我不知道什麼是最佳做法。由於我的「舊代碼」提供了一個'SessionFactory',我的第一個想法是重新使用它。 –

回答

0

嗯,除非你使用Hibernate 5.2 Hibernate的org.hibernate.SessionFactory不擴展javax.persistence.EntityManagerFactory,hibernate-entitymanager最近才被合併到hibernate-core中。在我看來,您正在瀏覽的源代碼版本比您在項目中使用的版本更新。

在這兩種情況下,要查看使用Hibernate和JPA的正確方法,請參閱this link

+0

我正在使用'org.hibernate:hibernate-core:5.2.1.Final',所以我確定'SessionFactory'擴展了'javax.persistence.EntityManagerFactory'。而且我的項目只有'hibernate-core'依賴項,沒有'hibernate-entitymanager'。 –

+0

在這種情況下,我唯一的猜測就是Hibernate正在返回一個由CGLib創建的類。您可以嘗試打印返回的實例並嘗試從那裏進行調試。無論哪種情況,要查看使用Hibernate和JPA的正確方法,請參閱[此鏈接](https://docs.jboss.org/hibernate/orm/5.2/quickstart/html_single/#tutorial_jpa) –

0

您可以按照步驟here在Spring中設置SessionFactory bean來重用Session工廠。

但是由於您已經使用EntityManagerFactory進行了編碼,因此您應該遵循this tutorial中描述的更簡單的路線。不幸的是,這是德文,但代碼應該說明問題。您聲明Hibernate作爲JPA的供應商,然後與供應商和數據源EntityManagerFactory的,它可以明確地定義,或者是一個JNDI數據源,在容器中定義和要求是這樣的:

<jee:jndi-lookup id="dataSource" jndi-name="myDataSource"/> 

然後它是非常好的聲明一個Spring transactionManager來允許@Transactional註解,所以你不必處理明確的事務管理。

然後你就可以讓你的UserDAO這個樣子:

public class UserDAO { 
    @PersistenceContext 
    private EntityManager em; 

    @Transactional 
    public List<User> findUserByName(String name) { 
     return em.createNamedQuery("User.findByName") 
      .setParameter("name", name) 
      .getResultList(); 
    } 
} 

其中User是一樣的東西

@Entity 
@NamedQueries({ @NamedQuery(name="User.findByName", query="select u from User where u.name = :name") }) 
public class User { 
    @Id 
    private Long id; 

    @Column 
    private String name; 
... 
} 

有很多方法可以做到這一點,雖然。