我在Netbeans 7.0上使用带有MySQL数据库的EclipseLink(JPA 2.0) - 我根据this screencast配置了它。但有时当我坚持一个Object / Entity时,我的表会在该对象持续存在之前被清除,并且我得到一个只有这个对象的表(就像它已被清除)。我只是在(填充)数据库中添加新条目。
我该如何防止这种情况?
这是我的代码:
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);
我的persist()函数:
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>
答案 0 :(得分:3)
尝试将日志记录设置为FINEST或FINE以查看正在发生的情况。 ( “eclipselink.logging.level”= “最好”)。
EclipseLink确实有一个选项可以在启动时重新创建表(“eclipselink.ddl-generation”=“drop-and-create-tables”),确保您没有使用它。 NetBeans或Glassfish可能默认设置此项,我认为它们可能在开发模式下执行此操作。
答案 1 :(得分: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()方法,您可以确保在应用程序完成时关闭emf(例如,当用户单击退出按钮时,或者当服务器停止或关闭时)。