/****************************************************************************** * Copyright © 2013-2016 The Nxt Core Developers. * * * * See the AUTHORS.txt, DEVELOPER-AGREEMENT.txt and LICENSE.txt files at * * the top-level directory of this distribution for the individual copyright * * holder information and the developer policies on copyright and licensing. * * * * Unless otherwise agreed in a custom licensing agreement, no part of the * * Nxt software, including this file, may be copied, modified, propagated, * * or distributed except according to the terms contained in the LICENSE.txt * * file. * * * * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ package nxt.db; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public abstract class ValuesDbTable<T,V> extends DerivedDbTable { private final boolean multiversion; protected final DbKey.Factory<T> dbKeyFactory; protected ValuesDbTable(String table, DbKey.Factory<T> dbKeyFactory) { this(table, dbKeyFactory, false); } ValuesDbTable(String table, DbKey.Factory<T> dbKeyFactory, boolean multiversion) { super(table); this.dbKeyFactory = dbKeyFactory; this.multiversion = multiversion; } protected abstract V load(Connection con, ResultSet rs) throws SQLException; protected abstract void save(Connection con, T t, V v) throws SQLException; protected void clearCache() { db.clearCache(table); } public final List<V> get(DbKey dbKey) { List<V> values; if (db.isInTransaction()) { values = (List<V>) db.getCache(table).get(dbKey); if (values != null) { return values; } } try (Connection con = db.getConnection(); PreparedStatement pstmt = con.prepareStatement("SELECT * FROM " + table + dbKeyFactory.getPKClause() + (multiversion ? " AND latest = TRUE" : "") + " ORDER BY db_id")) { dbKey.setPK(pstmt); values = get(con, pstmt); if (db.isInTransaction()) { db.getCache(table).put(dbKey, values); } return values; } catch (SQLException e) { throw new RuntimeException(e.toString(), e); } } private List<V> get(Connection con, PreparedStatement pstmt) { try { List<V> result = new ArrayList<>(); try (ResultSet rs = pstmt.executeQuery()) { while (rs.next()) { result.add(load(con, rs)); } } return result; } catch (SQLException e) { throw new RuntimeException(e.toString(), e); } } public final void insert(T t, List<V> values) { if (!db.isInTransaction()) { throw new IllegalStateException("Not in transaction"); } DbKey dbKey = dbKeyFactory.newKey(t); db.getCache(table).put(dbKey, values); try (Connection con = db.getConnection()) { if (multiversion) { try (PreparedStatement pstmt = con.prepareStatement("UPDATE " + table + " SET latest = FALSE " + dbKeyFactory.getPKClause() + " AND latest = TRUE")) { dbKey.setPK(pstmt); pstmt.executeUpdate(); } } for (V v : values) { save(con, t, v); } } catch (SQLException e) { throw new RuntimeException(e.toString(), e); } } @Override public final void rollback(int height) { if (multiversion) { VersionedEntityDbTable.rollback(db, table, height, dbKeyFactory); } else { super.rollback(height); } } @Override public final void trim(int height) { if (multiversion) { VersionedEntityDbTable.trim(db, table, height, dbKeyFactory); } else { super.trim(height); } } }