手动删除表后,Eclipselink无法在MySQL数据库中创建表

时间:2016-10-17 17:16:36

标签: mysql jpa eclipselink

我在项目中使用Eclipselink作为JPA实现。

我正在尝试使用此处所述的复合持久性单元http://wiki.eclipse.org/EclipseLink/Examples/JPA/Composite

我创建了两个实体ToDo和Diary,它们单独运行,具有自己的持久性单元,并且仍然使用复合持久性单元。

然后我在日记实体中添加了一个新字段,应用程序开始显示问题。所以我想我会放弃这张桌子,以便JPA自动添加新字段。

但是,当我删除创建的数据库表并尝试再次运行该示例时,它将不会按原样重新创建表。

这是我的复合持久性单元persistence.xml代码。

 <?xml version="1.0" encoding="UTF-8"?>
 <persistence version="2.1"
    xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="compositePU">
        <provider>
    org.eclipse.persistence.jpa.PersistenceProvider
    </provider>
        <jar-file>todo.jar</jar-file>
        <jar-file>diary.jar</jar-file>

        <properties>
            <property name="eclipselink.ddl-generation" value="create-or-extend-tables" />
            <property name="eclipselink.composite-unit" value="true" />
            <property name="javax.persistence.schema-generation.database.action"
                value="create" />
        </properties>
    </persistence-unit>
</persistence>

我在Apache Tomcat 7上使用它并使用Eclipselink 2.5。

这是我现在得到的错误:

HTTP Status 500 - Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5): org.eclipse.persistence.exceptions.DatabaseException

--------------------------------------------------------------------------------

type Exception report

message Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5): org.eclipse.persistence.exceptions.DatabaseException

description The server encountered an internal error that prevented it from fulfilling this request.

exception 

javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'testdb.todo' doesn't exist
Error Code: 1146
Call: INSERT INTO TODO (DESCRIPTION, NAME) VALUES (?, ?)
    bind => [2 parameters bound]
Query: InsertObjectQuery(todo.ToDo@3ba3441d)
    org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:157)
    com.lladmotors.test.AddToDo.doPost(AddToDo.java:64)
    com.lladmotors.test.AddToDo.doGet(AddToDo.java:41)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:624)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)


root cause 

Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'testdb.todo' doesn't exist
Error Code: 1146
Call: INSERT INTO TODO (DESCRIPTION, NAME) VALUES (?, ?)
    bind => [2 parameters bound]
Query: InsertObjectQuery(todo.ToDo@3ba3441d)
    org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:331)
    org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:900)
    org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:962)
    org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:631)
    org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:558)
    org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:1991)
    org.eclipse.persistence.sessions.server.ClientSession.executeCall(ClientSession.java:298)
    org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:242)
    org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228)
    org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.insertObject(DatasourceCallQueryMechanism.java:377)
    org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:165)
    org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:180)
    org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.insertObjectForWrite(DatabaseQueryMechanism.java:489)
    org.eclipse.persistence.queries.InsertObjectQuery.executeCommit(InsertObjectQuery.java:80)
    org.eclipse.persistence.queries.InsertObjectQuery.executeCommitWithChangeSet(InsertObjectQuery.java:90)
    org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:301)
    org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:58)
    org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:899)
    org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:798)
    org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:108)
    org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:85)
    org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2896)
    org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1793)
    org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1775)
    org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1726)
    org.eclipse.persistence.internal.sessions.CommitManager.commitNewObjectsForClassWithChangeSet(CommitManager.java:226)
    org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:125)
    org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:4196)
    org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1441)
    org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1531)
    org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:277)
    org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1169)
    org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:132)
    com.lladmotors.test.AddToDo.doPost(AddToDo.java:64)
    com.lladmotors.test.AddToDo.doGet(AddToDo.java:41)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:624)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)


root cause 

com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'testdb.todo' doesn't exist
    sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
    sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
    java.lang.reflect.Constructor.newInstance(Unknown Source)
    com.mysql.jdbc.Util.handleNewInstance(Util.java:409)
    com.mysql.jdbc.Util.getInstance(Util.java:384)
    com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1052)
    com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4232)
    com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4164)
    com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2615)
    com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2776)
    com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2838)
    com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2082)
    com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2334)
    com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2262)
    com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2246)
    org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:890)
    org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:962)
    org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:631)
    org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:558)
    org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:1991)
    org.eclipse.persistence.sessions.server.ClientSession.executeCall(ClientSession.java:298)
    org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:242)
    org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228)
    org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.insertObject(DatasourceCallQueryMechanism.java:377)
    org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:165)
    org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:180)
    org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.insertObjectForWrite(DatabaseQueryMechanism.java:489)
    org.eclipse.persistence.queries.InsertObjectQuery.executeCommit(InsertObjectQuery.java:80)
    org.eclipse.persistence.queries.InsertObjectQuery.executeCommitWithChangeSet(InsertObjectQuery.java:90)
    org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:301)
    org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:58)
    org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:899)
    org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:798)
    org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:108)
    org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:85)
    org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2896)
    org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1793)
    org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1775)
    org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1726)
    org.eclipse.persistence.internal.sessions.CommitManager.commitNewObjectsForClassWithChangeSet(CommitManager.java:226)
    org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:125)
    org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:4196)
    org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1441)
    org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1531)
    org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:277)
    org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1169)
    org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:132)
    com.lladmotors.test.AddToDo.doPost(AddToDo.java:64)
    com.lladmotors.test.AddToDo.doGet(AddToDo.java:41)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:624)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)


note The full stack trace of the root cause is available in the Apache Tomcat/7.0.72 logs.


--------------------------------------------------------------------------------

Apache Tomcat/7.0.72

这是我用来添加记录的代码

package com.lladmotors.test;

import java.io.IOException;
import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import todo.ToDo;

import com.lladmotors.diary.Diary;

public class AddToDo extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public AddToDo() {
        super();
        // TODO Auto-generated constructor stub
    }


    protected void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        // Call the doPost method
        doPost(request, response);
    }

    protected void doPost(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {

        // create a new To Do

        //EntityManagerFactory factory = Persistence
            //  .createEntityManagerFactory("todo");
        //EntityManager em = factory.createEntityManager();
        EntityManagerFactory factory = Persistence
                .createEntityManagerFactory("compositePU");
        EntityManager em = factory.createEntityManager();
        em.getTransaction().begin();
        ToDo toDo = new ToDo();
        toDo.setName(request.getParameter("name")+"via Servlet");
        toDo.setDescription(request.getParameter("description") + "via Servlet");
        em.persist(toDo);
        em.getTransaction().commit();

        // display a list of To Do.
        Query q = em.createQuery("select t from ToDo t");
        @SuppressWarnings("unchecked")
        List<ToDo> todoList = (List<ToDo>) q.getResultList();
        for (ToDo todo : todoList) {
            response.getWriter().println(
                    todo.getId() + todo.getName() + todo.getDescription() + "<br>");
        }

        //em.close();

        // create a new To Do

        //EntityManagerFactory factory2 = Persistence
            //  .createEntityManagerFactory("diary");
        //EntityManager em2 = factory2.createEntityManager();
        em.getTransaction().begin();
        Diary diary = new Diary();
        diary.setName(request.getParameter("name"));
        diary.setDetails(request.getParameter("description"));
        diary.setTodo(toDo);
        Date date = new Date();
        diary.setDate(date);
        em.persist(diary);
        em.getTransaction().commit();

        // display a list of To Do.
        Query q2 = em.createQuery("select d from Diary d");
        @SuppressWarnings("unchecked")
        List<Diary> diaryList = (List<Diary>) q2.getResultList();
        for (Diary entry : diaryList) {
            response.getWriter().println(
                    entry.getId() + entry.getName() + entry.getDetails()
                            + entry.getDate() + entry.getTodo().getDescription()
                            +"<br>");
        }

        em.close();
    }

}

2 个答案:

答案 0 :(得分:2)

我添加了以下persistence.xml文件属性,现在运行良好。如果要通过复合持久性单元对数据库进行更改,我认为您还必须在复合单元的persistence.xml中包含数据库访问详细信息。

我认为复合单元persistence.xml使用包含的JPA项目中persistence.xml文件中的数据在内存中创建一个persistence.xml(就像maven一样,带有'POM)

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
    xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="compositePU">

        <jar-file>todo.jar</jar-file>
        <jar-file>diary.jar</jar-file>
        <properties>
            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/testdb" />
            <property name="javax.persistence.jdbc.user" value="root" />
            <property name="javax.persistence.jdbc.password" value="root" />

            <property name="eclipselink.logging.level" value="ALL" />
            <property name="eclipselink.logging.level.jpa" value="ALL" />
            <property name="eclipselink.logging.level.ddl" value="ALL" />
            <property name="eclipselink.logging.level.connection" value="ALL" />
            <property name="eclipselink.logging.level.sql" value="ALL" />
            <property name="eclipselink.logging.level.transaction"
                value="ALL" />
            <property name="eclipselink.logging.level.sequencing" value="ALL" />
            <property name="eclipselink.logging.level.server" value="ALL" />
            <property name="eclipselink.logging.level.query" value="ALL" />
            <property name="eclipselink.logging.level.properties" value="ALL" />

            <property name="eclipselink.ddl-generation" value="create-or-extend-tables" />
            <property name="eclipselink.ddl-generation.output-mode"
                value="database" />
            <property name="javax.persistence.schema-generation.database.action"
                value="create" />
        </properties>
    </persistence-unit>
</persistence>

答案 1 :(得分:1)

您正在混合DDL生成的EclipseLink特定配置和JPA 2.1配置。

的EclipseLink

使用eclipselink.ddl-generation进行配置。 documentation个州,您只能在create-or-extend-tables时使用eclipselink.ddl-generation.output-mode = database。第一个例子中缺少这个。

JPA 2.1

specification概括了模式生成。使用javax.persistence.schema-generation.database.action。有效值为none, create, drop-and-create, drop。但是,EclipseLink对此属性接受create-or-extend-tables但不接受none

仅使用EclipseLink或JPA 2.1配置属性。