2011-05-18 45 views
2

我在Netbeans 7.0上使用EclipseLink(JPA 2.0)和MySQL數據庫 - 我根據this screencast配置了該數據庫。但有時當我堅持一個對象/實體時,在該對象持久存在之前,我的表被清除,並且我得到一個僅包含此對象的表(例如它已被清除)。我只是簡單地在(填充)數據庫中添加新條目。如何防止EclipseLink(JPA 2.0)清除我的數據庫/表?

我該如何預防?

這裏是我的代碼:

Movie movie = new Movie(
    jsondata.path("Title").getTextValue(), 
    jsondata.path("Year").getValueAsInt(), 
    jsondata.path("Genre").getTextValue(), 
    jsondata.path("Plot").getTextValue(), 
    jsondata.path("Poster").getTextValue()); 
persist(movie); 

我的堅持()函數:

public static void persist(Object object) { 
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("AllmoviesPU"); 
    EntityManager em = emf.createEntityManager(); 
    em.getTransaction().begin(); 
    try { 
     em.persist(object); 
     em.getTransaction().commit(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
     em.getTransaction().rollback(); 
    } 
    em.close(); 
} 

我的電影對象/實體:

@Entity 
public class Movie implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id; 
    private String title; 
    @Column(name="MOVIEYEAR") 
    private int year; 
    private String genre; 
    private String synopsis; 
    private String image; 

    public Movie(String title, int year, String genre, String synopsis, String image) { 
     this.title = title; 
     this.year = year; 
     this.genre = genre; 
     this.synopsis = synopsis; 
     this.image = image; 
    } 

    public Movie() { 
    } 

    /* ... Getters and Setters stuff ... */ 

} 

我的persistence.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> 
    <persistence-unit name="AllmoviesPU" transaction-type="RESOURCE_LOCAL"> 
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> 
    <class>allmovies.data.Movie</class> 
    <properties> 
     <property name="javax.persistence.jdbc.url" value="jdbc:mysql://123.123.123.123:3306/psanta_allmovies"/> 
     <property name="javax.persistence.jdbc.password" value="XXXXXX"/> 
     <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/> 
     <property name="javax.persistence.jdbc.user" value="psanta_allmovies"/> 
    </properties> 
    </persistence-unit> 
</persistence> 
+1

你在別的地方發佈過這個問題嗎?完成(工作!!)數據庫登錄設置*公共*?難道這不就是一些不時縮短桌面的小丑嗎?嘗試更改您的密碼,不要在萬維網中發佈數據庫連接詳細信息... – BalusC 2011-05-19 02:59:49

回答

2

儘管我不能保證它們與您的問題相關,但您的代碼中仍有許多需要解決的問題。

第一件事情是,每次你僅僅想要堅持一個實體時,創建你的實體管理器工廠和實體管理器就太昂貴了。另外,你並沒有關閉你的實體經理工廠。

正確的做法是,創建一個實體管理器工廠並在應用程序的整個生命週期中保持它可用。每次與用戶開始對話(即事務)時,都會向它請求一個實體管理器,用它來堅持你想要堅持的一切,然後關閉實體管理器。

當您的應用程序完成時,關閉實體管理器工廠。

您可能想要考慮的第二個方面是某些異常已經意味着回滾,例如在提交執行期間拋出的任何異議。因此,如果你嘗試第二次回滾,那麼你會得到第二個異常,你沒有處理。

我無法保證任何這些更改都能解決您的問題,但它們肯定是一個好的開始。

這就是說,從你的代碼中,我不明顯看出你堅持多個實體。我想,更多的上下文是必需的。

我有些建議是這樣的:

public class DataAccessLayer { 

    private EntityManagerFactory emf; 

    public DataAccessLayer(){ 
    } 

    public synchronized void start(){ 
     if(isStarted()) 
     throw new IllegalStateException("Already started"); 
     this.emf = Persistence.createEntityManagerFactory("AllmoviesPU"); 
    } 

    public synchronized void stop(){ 
     if(!isStarted()) 
     throw new IllegalStateException("Not started"); 
     this.emf.close(); 
     this.emf = null; 
    } 

    public synchronized boolean isStarted(){ 
    return this.emf != null; 
    } 

    public void doPersistenceStuff(InputData o){ 
      if(!isStarted()) 
       throw new IllegalStateException("Not started"); 
     EntityManager em = emf.getEntityManager(); 
     EntityTransaction t = entityManager.getTransaction(); 
     try { 
      t.begin(); 
      //do persistence stuff here 
      t.commit(); 
     } 
     catch (RollbackException e) { 
      //transaction already rolledback 
      throw new MyPersistenceException(e); 
     } 
     catch (Exception e) { 
      t.rollback(); //manual rollback 
      throw new MyPersistenceException(e); 
     } 
     em.close() 
    } 
} 

而且可以確保當您的應用程序結束(當用戶點擊退出按鈕,或者當你的服務器停止或關閉,如電動勢關閉)通過在數據訪問層實例中調用stop()方法來實現。

+0

請考慮在我想保留另一個實體/對象時運行相同的代碼。好的,感謝Factory提示。我會嘗試的。 – pedrosanta 2011-05-18 16:59:53

+0

我現在在退出時關閉工廠時運行代碼,行爲相同:有時會清除表。 – pedrosanta 2011-05-18 17:05:19

+0

請澄清一下,您是否正在創建全球實體經理工廠,或者您每次持續創建實體經理工廠?您爲您的應用程序創建單個實體管理器工廠並且每次要保留時重用它,而不是非常重要,因此非常重要。 – 2011-05-18 17:13:53

3

嘗試開啓日誌記錄至FINEST或FINE查看發生了什麼。 ( 「eclipselink.logging.level」= 「最好」)。 EclipseLink確實有一個在啓動時重新創建表的選項(「eclipselink.ddl-generation」=「drop-and-create-tables」),確保你沒有使用它。 NetBeans或Glassfish可能會默認設置此項,我認爲他們可能會在開發模式下執行此操作。