Как ВЫБРАТЬ данные из таблицы базы данных Derby в памяти? - PullRequest
3 голосов
/ 11 ноября 2011

Я создал таблицу базы данных в памяти, используя JavaDB / Derby. Я могу INSERT данные в таблицу. Но это не работает, когда я пытаюсь SELECT данные из таблицы.

I создать таблицу с:

DECLARE GLOBAL TEMPORARY TABLE SESSION.memtable (id int, name varchar(10))
NOT LOGGED

вставить данные с:

INSERT INTO SESSION.memtable (id, name) VALUES (?,?)

и возвращает 1 для rows affected. Я выбираю данные с помощью:

SELECT name FROM SESSION.memtable WHERE id = ?

но возвращается пусто ResultSet (rs.next() ложно).

Что я делаю не так при использовании SELECT?

Я использую derby.jar, включенный в JDK7.

Вот мой код:

public class DBTest {
    public static void main(String[] args) {
        final int userId = 4;
        final String sql = "DECLARE GLOBAL TEMPORARY TABLE SESSION.memtable "+
                            "(id int, name varchar(10)) NOT LOGGED";
        final String inSQL = "INSERT INTO SESSION.memtable (id, name) "+
                             "VALUES (?,?)";
        final String selSQL = "SELECT name FROM SESSION.memtable WHERE id = ?"
        final String connURL = "jdbc:derby:memory:memdatabase;create=true";
        try(Connection conn = DriverManager.getConnection(connURL);) {
            try (PreparedStatement ps = conn.prepareStatement(sql);) {
                ps.execute();
            }
            try (PreparedStatement ps = conn.prepareStatement(inSQL);) {
                ps.setInt(1, userId);
                ps.setString(2, "Jonas");
                int rows = ps.executeUpdate();
                System.out.println(rows + " rows inserted.");
            }
            try (PreparedStatement ps = conn.prepareStatement(selSQL);) {
                ps.setInt(1, userId);
                try (ResultSet rs = ps.executeQuery();) {
                    String name;
                    if(rs.next()) {
                        name = rs.getString("name");
                    } else {
                        name = null;
                    }
                    System.out.println("Name: " + name);
                }
            }
        } catch (SQLException e) {e.printStackTrace();}}}

ОБНОВЛЕНИЕ

Если я изменю SELECT-запрос на:

SELECT t1.name AS name FROM SESSION.memtable t1 WHERE id = ?

Я получаю это сообщение об ошибке:

java.sql.SQLException: Operation 'DROP TABLE' cannot be performed on object 'MEMTABLE(ID, NAME)' because there is an open ResultSet dependent on that object.
    at org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(Unknown Source)
    at org.apache.derby.impl.jdbc.Util.generateCsSQLException(Unknown Source)
    at org.apache.derby.impl.jdbc.TransactionResourceImpl.wrapInSQLException(Unknown Source)
    at org.apache.derby.impl.jdbc.TransactionResourceImpl.handleException(Unknown Source)
    at org.apache.derby.impl.jdbc.EmbedConnection.handleException(Unknown Source)
    at org.apache.derby.impl.jdbc.EmbedConnection.commitIfAutoCommit(Unknown Source)
    at org.apache.derby.impl.jdbc.ConnectionChild.commitIfAutoCommit(Unknown Source)
    at org.apache.derby.impl.jdbc.EmbedStatement.resultSetClosing(Unknown Source)
    at org.apache.derby.impl.jdbc.EmbedResultSet.movePosition(Unknown Source)
    at org.apache.derby.impl.jdbc.EmbedResultSet.next(Unknown Source)
    at DBTest.main(DBTest.java:29)
Caused by: java.sql.SQLException: Operation 'DROP TABLE' cannot be performed on object 'MEMTABLE(ID, NAME)' because there is an open ResultSet dependent on that object.
    at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source)
    at org.apache.derby.impl.jdbc.SQLExceptionFactory40.wrapArgsForTransportAcrossDRDA(Unknown Source)
    ... 11 more
Caused by: ERROR X0X95: Operation 'DROP TABLE' cannot be performed on object 'MEMTABLE(ID, NAME)' because there is an open ResultSet dependent on that object.
    at org.apache.derby.iapi.error.StandardException.newException(Unknown Source)
    at org.apache.derby.impl.sql.conn.GenericLanguageConnectionContext.verifyNoOpenResultSets(Unknown Source)
    at org.apache.derby.impl.sql.GenericPreparedStatement.prepareToInvalidate(Unknown Source)
    at org.apache.derby.impl.sql.depend.BasicDependencyManager.coreInvalidateFor(Unknown Source)
    at org.apache.derby.impl.sql.depend.BasicDependencyManager.invalidateFor(Unknown Source)
    at org.apache.derby.impl.sql.conn.GenericLanguageConnectionContext.tempTablesAndCommit(Unknown Source)
    at org.apache.derby.impl.sql.conn.GenericLanguageConnectionContext.doCommit(Unknown Source)
    at org.apache.derby.impl.sql.conn.GenericLanguageConnectionContext.userCommit(Unknown Source)
    at org.apache.derby.impl.jdbc.TransactionResourceImpl.commit(Unknown Source)
    ... 6 more

Но Name: не печатается, поэтому все равно не работает.

Ответы [ 3 ]

1 голос
/ 11 ноября 2011

Вопрос обсуждался в списке рассылки derby-user , где было отмечено дополнительное требование включить on commit preserve rows.

При включенной автоматической фиксации временная таблица по умолчанию очищается при фиксации, поэтому дополнительное условие гарантирует, что строки остаются доступными после фиксации транзакции.

0 голосов
/ 11 августа 2014

Здесь вы используете два понятия: одно - Derby с опцией хранения In-Memors, а другое - временная таблица.Если вам нужна база данных In-Memors, вы все равно можете использовать обычные определенные таблицы («CREATE TABLE ...»).Это облегчит задачу, поскольку вам не нужно иметь дело с семантической сессией этих временных таблиц.

0 голосов
/ 11 ноября 2011

Вы должны действительно заглянуть в Hibernate. Он не только отображает ваши классы, но и управляет неприятными вещами JDBC для вас, чтобы вы могли сосредоточиться на том, что вы хотите сделать. Он далек от совершенства, но в дополнение к этому он обеспечивает переносимость базы данных.

Я использую hibernate через Spring, поэтому мой код будет выглядеть примерно так:

TempStorage temp = new TempStorage();
temp.setName("Bob");
getHibernateTemplate.insert(temp);
temp = getHibernateTemplate.find("SELECT name FROM TempStorage");
...