Как ВЫБРАТЬ данные из таблицы базы данных Derby в памяти?

#java #select #derby #javadb #in-memory-database

#java #выберите #derby #javadb #база данных в памяти

Вопрос:

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

Я создаю таблицу с:

 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() равно false).

Что я делаю не так при использовании 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 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: не печатается, поэтому он по-прежнему не работает.

Ответ №1:

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

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

Ответ №2:

Здесь используются две концепции: одна — Derby с опцией хранения в памяти, а другая — временная таблица. Если вам нужна база данных в памяти, вы все равно можете использовать обычные определенные таблицы («СОЗДАТЬ ТАБЛИЦУ …»). Это упростит задачу, поскольку вам не придется иметь дело с семантикой сеанса этих временных таблиц.

Ответ №3:

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

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

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

Комментарии:

1. Спящий режим — это не то, что я ищу, и я не понимаю, как это решает мою проблему.

2. Использование гибернации поможет вам не увязнуть в особенностях языка базы данных. Хотя он добавляет пару своих собственных.

3. Пожалуйста, объясните, как вместо этого Hibernate решит мою проблему, и опубликуйте некоторый код. Как мне написать запрос select из базы данных derby в памяти, которая работает в режиме гибернации?

4. Я подозреваю, что это даже невозможно сделать с помощью Hibernate Derby.