И так, чтобы начать получать данные из базы или сохранять/изменять их в ней, нам нужно создать выражение, и выполнить его, результатом выполнения выражения является ResultSet.
ResultSet бывают нескольких типов, которые определяют методы работы с ним:
TYPE_FORWARD_ONLY – курсор такого резалтсета может двигаться только вперед, при этом данные в этом резалтсете храняться на момент выполнения выражения, не отображая изменения в базе на поточный момент работы в ним через курсор.
TYPE_SCROLL_INSENSITIVE – такой резалтсет позволяет курсору двигаться в любом направлении и в абсолютные позиции, но при этом в нем хранятся данные на момент выполнения выражения.
TYPE_SCROLL_SENSITIVE – курсор такого сета тоже подвижен в любом направлении, но при этом изменения в базе тут же отображаются в резалтсете.
Еще одна характеристика резалтсета это конкурентность(ResultSet Concurrency). Она определяет можно ли изменять содержимое базы данных через резалтсет. Есть два типа:
CONCUR_READ_ONLY – не можно.
CONCUR_UPDATABLE – можно изменять изменять содержимое базы.
public void modifyPrices(float percentage) throws SQLException {
Statement stmt = null;
try {
stmt =
con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet uprs = stmt.executeQuery("SELECT * FROM COFFEES");
while (uprs.next()) {
float f = uprs.getFloat("PRICE");
uprs.updateFloat("PRICE", f * percentage);
uprs.updateRow();
}
} catch (SQLException e) {
JDBCTutorialUtilities.printSQLException(e);
} finally {
if (stmt != null) { stmt.close(); }
}
}
И так, как уже стало понятно, чтобы база начала выполнять какие-то операции мы должна работать с выражением, а вернее выполнять через него некие запросы.
Делать мы это можем через следующие методы:
boolean execute(String sql) – выполнить скуель указанный в строке; возращается тру, если мы можем получить резалтсет через .getResultSet() в случае если у нас запрос типа выборка, или же мы можем получить количество обработанных/вставленных строк запросом int getUpdateCount(), если же у нас запросом сформирован резалтсет(была выборка), то этот методв вернет -1, -1 он вернет также если не обработано ни одной строки.
ResultSet executeQuery(String sql) – этот метод у нас для того, чтобы выполнять только запросы выборки.
int executeUpdate(String sql) – а этот метод для того, чтобы выполнять запросы INSERT, UPDATE, или DELETE, или SQL DDL, которые не возвращают никаких результатов.
int[] executeBatch() – этот метод выполняет пакет запросов, которые мы до этого вставили в наше выражение, возвращает он массив с количеством результатов, которые возвратил каждый запрос пакета.
Впринципе мы можем работать только с екзекьютом, при этом не сразу обрабатывать резалтсеты в служае выборок, мы можем потом подключить использование методов, которые получают результаты пердыдущих запросов:
boolean getMoreResults() – тру если мы можем получить следующий результат методом .getResultSet(), у нас не может быть вызовов .getResultSet() больше чем выло выполнено екзекьютов на этом выражении, если мы вызываем .getResultSet() большее количество раз чем было екзекьютов( если getMoreResults() == фолс), то у нас будет ексепшин.
boolean getMoreResults(int current) – подвинет курсор резалтсетов на указанную позицию, если вернется тру, то мы можем .getResultSet() получить результат выполненного по счету current запроса.
Курсоры резалтсета:
Они содрежат следующие методы:
next:
previous:
first:
last:
beforeFirst:
afterLast:
relative(int rows):
absolute(int row):
Пакетные запросы.
public void batchUpdate() throws SQLException {
Statement stmt = null;
try {
this.con.setAutoCommit(false);
stmt = this.con.createStatement();
stmt.addBatch(
"INSERT INTO COFFEES " +
"VALUES('Amaretto', 49, 9.99, 0, 0)");
stmt.addBatch(
"INSERT INTO COFFEES " +
"VALUES('Hazelnut', 49, 9.99, 0, 0)");
stmt.addBatch(
"INSERT INTO COFFEES " +
"VALUES('Amaretto_decaf', 49, " +
"10.99, 0, 0)");
stmt.addBatch(
"INSERT INTO COFFEES " +
"VALUES('Hazelnut_decaf', 49, " +
"10.99, 0, 0)");
int [] updateCounts = stmt.executeBatch();
this.con.commit();
} catch(BatchUpdateException b) {
JDBCTutorialUtilities.printBatchUpdateException(b);
} catch(SQLException ex) {
JDBCTutorialUtilities.printSQLException(ex);
} finally {
if (stmt != null) { stmt.close(); }
this.con.setAutoCommit(true);
}
}
Также в пакете можно работать с подготовленными выражениями:
con.setAutoCommit(false);
PreparedStatement pstmt = con.prepareStatement(
"INSERT INTO COFFEES VALUES( " +
"?, ?, ?, ?, ?)");
pstmt.setString(1, "Amaretto");
pstmt.setInt(2, 49);
pstmt.setFloat(3, 9.99);
pstmt.setInt(4, 0);
pstmt.setInt(5, 0);
pstmt.addBatch();
pstmt.setString(1, "Hazelnut");
pstmt.setInt(2, 49);
pstmt.setFloat(3, 9.99);
pstmt.setInt(4, 0);
pstmt.setInt(5, 0);
pstmt.addBatch();
// ... and so on for each new
// type of coffee
int [] updateCounts = pstmt.executeBatch();
con.commit();
con.setAutoCommit(true);
Вставка строк через резалтсет
Как известно инсерты делаются execute, executeUpdate. Но некоторые реляционные базы позволяют делать вставки также через резалтсет:
public void insertRow(String coffeeName, int supplierID,
float price, int sales, int total)
throws SQLException {
Statement stmt = null;
try {
stmt = con.createStatement(
ResultSet.TYPE_SCROLL_SENSITIVE
ResultSet.CONCUR_UPDATABLE);
ResultSet uprs = stmt.executeQuery(
"SELECT * FROM " + dbName +
".COFFEES");
uprs.moveToInsertRow();
uprs.updateString("COF_NAME", coffeeName);
uprs.updateInt("SUP_ID", supplierID);
uprs.updateFloat("PRICE", price);
uprs.updateInt("SALES", sales);
uprs.updateInt("TOTAL", total);
uprs.insertRow();
uprs.beforeFirst();
} catch (SQLException e ) {
JDBCTutorialUtilities.printSQLException(e);
} finally {
if (stmt != null) { stmt.close(); }
}
}
Подготовленные выражения
public void updateCoffeeSales(HashMap salesForWeek)
throws SQLException {
PreparedStatement updateSales = null;
PreparedStatement updateTotal = null;
String updateString =
"update " + dbName + ".COFFEES " +
"set SALES = ? where COF_NAME = ?";
String updateStatement =
"update " + dbName + ".COFFEES " +
"set TOTAL = TOTAL + ? " +
"where COF_NAME = ?";
try {
con.setAutoCommit(false);
updateSales = con.prepareStatement(updateString);
updateTotal = con.prepareStatement(updateStatement);
for (Map.Entry e : salesForWeek.entrySet()) {
updateSales.setInt(1, e.getValue().intValue());
updateSales.setString(2, e.getKey());
updateSales.executeUpdate();
updateTotal.setInt(1, e.getValue().intValue());
updateTotal.setString(2, e.getKey());
updateTotal.executeUpdate();
con.commit();
}
} catch (SQLException e ) {
JDBCTutorialUtilities.printSQLException(e);
if (con != null) {
try {
System.err.print("Transaction is being rolled back");
con.rollback();
} catch(SQLException excep) {
JDBCTutorialUtilities.printSQLException(excep);
}
}
} finally {
if (updateSales != null) {
updateSales.close();
}
if (updateTotal != null) {
updateTotal.close();
}
con.setAutoCommit(true);
}
}
Recent Comments