UCanAccess/Jackcess exception when calling execute

2019-06-23 09:13发布

问题:

I am using UCanAccess for manipulating an Access database. When calling executeUpdate I get the exception:

net.ucanaccess.jdbc.UcanaccessSQLException: UCAExc:::3.0.2 Unexpected page type 1 (Db=db.accdb;Table=MyTable;Index=PrimaryKey)

It only occurs when trying to update one specific row - I already know how to fix this in the Access DB.

The problem is with the Logger, after this exception is thrown and I catch it, I log an info message and it is not shown, all of the next log messages are not shown either.

The reason why I want to fix it without fixing the DB is because when it occurs once, the user should close the application in order to log the next actions, if he doesn't then I will not be able to know what he did.

This is my code:

public static void main(String args[]) {
    Logger logger = Logger.getLogger("myLogger");
    PreparedStatement pst = null;
    try {
        FileHandler fileHandler = new FileHandler("myLog.log", 0, 1, true);

        // Set formatter to put the time, the message, and the exception if exists
        fileHandler.setFormatter(new Formatter() {
            @Override
            public String format(LogRecord record) {
                Throwable t = record.getThrown();
                String stackTrace = "";
                if (t != null) {
                    StringWriter sw = new StringWriter();
                    t.printStackTrace(new PrintWriter(sw));
                    stackTrace = sw.toString();
                }

                return  Calendar.getInstance().getTime() + "--" +
                        formatMessage(record) + stackTrace + "\n";
            }
        });

        // Set the logger handler
        logger.addHandler(fileHandler); 
        logger.log(Level.INFO, "1");

        // Throw on purpose
        String query = "UPDATE myTable SET name = 'a' WHERE id = 289";

        conn = DriverManager.getConnection(DB_URL);
        pst = conn.prepareStatement(query);
        pst.executeUpdate();

        logger.log(Level.INFO, "2");
    } catch (UcanaccessSQLException e) {
        logger.log(Level.INFO, "3");
        System.out.println("INSIDE Exception");
    } catch (SQLException e) {
        logger.log(Level.INFO, "4");
    } catch (Exception e) {
        logger.log(Level.INFO, "5");
    }
}

The console output is:

net.ucanaccess.jdbc.UcanaccessSQLException: UCAExc:::3.0.2 Unexpected page type 1 (Db=db.accdb;Table=myTable;Index=PrimaryKey) at net.ucanaccess.commands.CompositeCommand.persist(CompositeCommand.java:95) at net.ucanaccess.jdbc.UcanaccessConnection.flushIO(UcanaccessConnection.java:315) at net.ucanaccess.jdbc.UcanaccessConnection.commit(UcanaccessConnection.java:205) at net.ucanaccess.jdbc.AbstractExecute.executeBase(AbstractExecute.java:161) at net.ucanaccess.jdbc.ExecuteUpdate.execute(ExecuteUpdate.java:50) at net.ucanaccess.jdbc.UcanaccessPreparedStatement.executeUpdate(UcanaccessPreparedStatement.java:253) at rashi.NewClass.main(NewClass.java:61) Caused by: java.io.IOException: Unexpected page type 1 (Db=db.accdb;Table=myTable;Index=PrimaryKey) at com.healthmarketscience.jackcess.impl.IndexData.isLeafPage(IndexData.java:1185) at com.healthmarketscience.jackcess.impl.IndexData.readDataPage(IndexData.java:1067) at com.healthmarketscience.jackcess.impl.IndexPageCache.readDataPage(IndexPageCache.java:267) at com.healthmarketscience.jackcess.impl.IndexPageCache.getDataPage(IndexPageCache.java:224) at com.healthmarketscience.jackcess.impl.IndexPageCache.getCacheDataPage(IndexPageCache.java:211) ..............

INSIDE Exception

And my log file contains only this row:

Sun Dec 20 15:35:40 IST 2015--1

which means my logger is no longer active. I guess there are some logger changes before the exception in UCanAccess.

回答1:

It looks like an HSQLDB side-effect that happens while UCanAccess is doing a physical rollback and shutting down the mirror db.

Setting the system property hsqldb.reconfig_logging to false may solve the issue, e.g.,

-Dhsqldb.reconfig_logging=false

or

System.setProperty("hsqldb.reconfig_logging", "false");