简体   繁体   中英

Eclipselink fails to create tables in MySQL database after manually dropping the tables

I am using Eclipselink as a JPA implementation in my project.

I was trying to use composite persistence units as described here http://wiki.eclipse.org/EclipseLink/Examples/JPA/Composite .

I created two entities ToDo and Diary and they work well individually, with their own persistence units and still worked with the composite persistence unit as well.

Then I added a new field to the diary Entity and the app started showing problems. So I thought I will drop the table so the JPA will add the new field automatically.

However when I dropped the database tables created and try to run the sample again it won't re-create the tables as they are supposed to do.

This is my composite persistence unit persistence.xml code.

 <?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>

I am using this on Apache Tomcat 7 and uses Eclipselink 2.5.

This is the error I am getting now:

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

This is the code I am using to add records

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();
    }

}

I added the following persistence.xml file properties, things are now working well. If you want to make changes to the database via composite persistence units, I figured you have to include the database access details in the composite units' persistence.xml as well.

I thought the composite units persistence.xml uses the data from the persistence.xml files in the contained JPA project to create a single persistence.xml in memory (like maven does, with its' 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>

You are mixing EclipseLink specific configuration of DDL generation and JPA 2.1 configuration.

EclipseLink

Configure using eclipselink.ddl-generation . The documentation states, that you can use create-or-extend-tables only when eclipselink.ddl-generation.output-mode = database . This is missing in your first example.

JPA 2.1

The specification generalized the schema generation. Use javax.persistence.schema-generation.database.action . Valid values are none, create, drop-and-create, drop . However, EclipseLink accepts create-or-extend-tables but not none for this property.

Use only either EclipseLink or JPA 2.1 configuration property.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM