При реализации функционала приложения, работающего с реляционной базой данных, используются следующие программные элементы библиотеки avalanche-sql:
| Класс | Назначение |
|---|---|
| ru.funsys.avalanche.sql.Database | Основной объект выполнения SQL выражений |
| ru.funsys.avalanche.sql.MultiDatabase | Объект одновременной модификации двух копий БД |
| ru.funsys.avalanche.sql.Adapter | Адаптер (java интерфейс), используется для получения ссылки на объект Database |
| ru.funsys.avalanche.sql.annotation.Column | Аннотация, описывающая связь поля класса (типа данных) с колонкой таблицы |
| ru.funsys.avalanche.sql.Query | Класс запроса, содержащий SQL выражения и параметры запроса |
| ru.funsys.avalanche.sql.QueryType | Класс запроса, содержащий SQL выражения, возвращаемый тип и параметры запроса |
| ru.funsys.avalanche.sql.QueryProcedure | Класс запроса, содержащий SQL выражение вызова процедуры и описание входных и выходных параметров |
| ru.funsys.avalanche.sql.InOutParameter | Класс, описывающий входной и/или выходной параметр процедуры |
| ru.funsys.avalanche.sql.ExecuteSet | Класс, содержащий результат выполнения множества SQL выражений в одной транзакции |
Класс ru.funsys.avalanche.sql.Database представляет собой абстракцию над источником данных (javax.sql.DataSource) и явно в коде приложения не используется. Для доступа к классу ru.funsys.avalanche.sql.Database требуется адаптер ru.funsys.avalanche.sql.Adapter, поле которого должно присутствовать в коде класса, а в конфигурации приложения должно присутствовать секция адаптера.
Класс ru.funsys.avalanche.sql.MultiDatabase представляет собой абстракцию над классом ru.funsys.avalanche.sql.Database и явно в коде приложения не используется. Для доступа к классу ru.funsys.avalanche.sql.MultiDatabase требуется адаптер ru.funsys.avalanche.sql.Adapter, поле которого должно присутствовать в коде класса, а в конфигурации приложения должно присутствовать секция адаптера.
Класс ru.funsys.avalanche.sql.MultiDatabase через адаптеры ru.funsys.avalanche.sql.Adapter работает сразу с двумя БД.
Адаптер ru.funsys.avalanche.sql.Adapter используется для определения связи с экземпляром класса ru.funsys.avalanche.sql.Database, который может быть определен в конфигурации приложения или находиться на удаленной машине. Адаптер ru.funsys.avalanche.sql.Adapter упрощает программный код приложения, освобождая программиста от работы с соединениями БД, управления транзакциями, повышает модифицируемость приложения.
Адаптер ru.funsys.avalanche.sql.Adapter может быть определен в классе, наследуемом от класса ru.funsys.avalanche.Application.
Пример
public class MyApplication extends Application {
@CfgAtribute(description="Адаптер доступа к БД")
Adapter database;
...
}
Выполнить запрос SELECT c подставляемыми параметрами.
Пример без параметров
try {
ResultSet resultSet = database.select("SELECT * FROM ... ");
while (resultSet.next()) {
// обработка полученного результата
...
}
} catch (Exception e) {
// обработка возможного исключения
...
}
Пример c параметрами
try {
Timestamp timestamp = new Timestamp();
ResultSet resultSet = database.select("SELECT * FROM ... WHERE user_name = ? AND date_start < ?", "Петр", timestamp);
while (resultSet.next()) {
// обработка полученного результата
...
}
} catch (Exception e) {
// обработка возможного исключения
...
}
Выполнить запрос SELECT c подставляемыми параметрами и получить результат заданного типа.
Пример без параметров
try {
Task[] allTasks = database.select("SELECT * FROM ... ", Task.class);
// обработка полученного результата
...
} catch (Exception e) {
// обработка возможного исключения
...
}
Пример c параметрами
try {
Timestamp timestamp = new Timestamp();
Task[] tasks = database.select("SELECT * FROM ... WHERE user_name = ? AND date_start < ?", Task.class, "Петр", timestamp);
// обработка полученного результата
...
} catch (Exception e) {
// обработка возможного исключения
...
}
Выполнить запрос SELECT c подставляемыми из вектора параметрами.
Пример
try {
Vector<Object> vector = new Vector();
vector.add(Петр");
vector.add(new Timestamp());
ResultSet resultSet = database.select("SELECT * FROM ... WHERE user_name = ? AND date_start < ?", vector);
while (resultSet.next()) {
// обработка полученного результата
...
}
} catch (Exception e) {
// обработка возможного исключения
...
}
Выполнить запрос SELECT c подставляемыми из вектора параметрами.
Пример
try {
List<Object> list = new ArrayList<Object>();
list.add(Петр");
list.add(new Timestamp());
ResultSet resultSet = database.select("SELECT * FROM ... WHERE user_name = ? AND date_start < ?", list);
while (resultSet.next()) {
// обработка полученного результата
...
}
} catch (Exception e) {
// обработка возможного исключения
...
}
Выполнить запрос SELECT с использованием экземпляра класса Query.
Пример
try {
Query query = new Query("SELECT * FROM ... WHERE user_name = ? AND date_start < ?", "Петр", new Timestamp());
ResultSet resultSet = database.select(query);
while (resultSet.next()) {
// обработка полученного результата
...
}
} catch (Exception e) {
// обработка возможного исключения
...
}
Выполнить запрос SELECT с использованием экземпляра класса QueryType.
Пример
try {
QueryType queryType = new QueryType("SELECT * FROM ... WHERE user_name = ? AND date_start < ?", Task.class, "Петр", new Timestamp());
Task[] tasks = database.select(queryType);
// обработка полученного результата
...
} catch (Exception e) {
// обработка возможного исключения
...
}
Выполнить несколько запросов в параллельных потоках. Этот метод возвращает массив объектов. Каждый элемент этого массива содержит либо результат выполнения запроса, либо исключение, возникшее при выполнении запроса
try {
Query[] queries = new Query[3];
queries[0] = new Query("SELECT * FROM ... WHERE ...", параметр_1, параметр_2, ..., параметр_N);
queries[1] = new QueryType("SELECT * FROM ... WHERE user_name = ? AND date_start < ?", Task.class, "Петр", new Timestamp());
queries[2] = new Query("SELECT * FROM ... WHERE ... ORDER BY ...", , параметр_1, параметр_2, ..., параметр_Y);
Object[] result = database.select(queries);
// обработка полученного результата
...
} catch (Exception e) {
// обработка возможного исключения
...
}
Выполнить запрос модификации (INSERT, UPDATE, DELETE). Возвращается число вставленных, измененных или удаленных записей
Примеры
try {
database.execute("INSERT INTO ... (user_name, ...) VALUES (?, ...)", "Петр", ... );
} catch (Exception e) {
// обработка возможного исключения
...
}
try {
int count = database.execute("DELETE FROM ... WHERE user_name = ?", "Петр");
...
} catch (Exception e) {
// обработка возможного исключения
...
}
Выполнить запрос модификации (INSERT, UPDATE, DELETE). Вектор подставляемых в запрос параметров, размер вектора параметров должен быть равен числу знаков вопроса в sql запросе. Если нет параметров запроса, то может быть null.
Примеры
try {
Vector<Object> vector = new Vector<Object>();
vector.add("Петр");
vector.add(...);
...
database.execute("INSERT INTO ... (user_name, ...) VALUES (?, ...)", vector);
} catch (Exception e) {
// обработка возможного исключения
...
}
try {
Vector<Object> vector = new Vector<Object>();
vector.add("Петр");
int count = database.execute("DELETE FROM ... WHERE user_name = ?", vector);
...
} catch (Exception e) {
// обработка возможного исключения
...
}
Выполнить запрос модификации (INSERT, UPDATE, DELETE). Список подставляемых в запрос параметров, размер вектора параметров должен быть равен числу знаков вопроса в sql запросе. Если нет параметров запроса, то может быть null.
Примеры
try {
List<Object> list = new ArrayList<Object>();
list.add("Петр");
list.add(...);
...
database.execute("INSERT INTO ... (user_name, ...) VALUES (?, ...)", list);
} catch (Exception e) {
// обработка возможного исключения
...
}
try {
List<Object> list = new ArrayList<Object>();
list.add("Петр");
int count = database.execute("DELETE FROM ... WHERE user_name = ?", list);
...
} catch (Exception e) {
// обработка возможного исключения
...
}
Выполнить запрос модификации (INSERT, UPDATE, DELETE) с использованием экземпляра класса Query..
Примеры
try {
List<Object> list = new ArrayList<Object>();
list.add("Петр");
list.add(...);
Query query = new Query("INSERT INTO ... (user_name, ...) VALUES (?, ...)", list);
database.execute(query);
} catch (Exception e) {
// обработка возможного исключения
...
}
try {
List<Object> list = new ArrayList<Object>();
list.add("Петр");
Query query = new Query("DELETE FROM ... WHERE user_name = ?", list);
int count = database.execute(query);
...
} catch (Exception e) {
// обработка возможного исключения
...
}
Выполнить множество запросов модификации (INSERT, UPDATE, DELETE) в одной транзакции. Уровень изоляции определяется либо в СУБД (действующий по умолчанию), либо в конфигурации объекта приложения ru.funsys.avalanche.sql.Database. Ошибка выполнения любого запроса откатывает всю транзакцию. Возвращает массив объектов, содержащих число модифицированных записей и время выполнения каждого запроса
Пример
try {
Query query1 = new Query("INSERT INTO ... VALUES (?, ?, ...)", param11, param12, ...);
Query query2 = new Query("UPDATE ... ?, ? ...", param21, param22, ...);
Query query3 = new Query("DELETE FROM ... WHERE ... = ? AND ... = ? ...", param31, param32, ...);
ExecuteSet[] executeSet = database.execute(query1, query2, query3);
// При необходимости контроль результата
} catch (Exception e) {
// обработка возможного исключения
...
}
Выполнить множество запросов модификации (INSERT, UPDATE, DELETE) в одной транзакции. Уровень изоляции определяется либо в СУБД (действующий по умолчанию), либо конфигурации объекта приложения ru.funsys.avalanche.sql.Database. Ошибка выполнения любого запроса откатывает всю транзакцию. Возвращает массив объектов, содержащих число модифицированных записей и время выполнения каждого запроса
Пример
try {
List<Query> transaction = new ArrayList<Query>();
list.add(new Query("INSERT INTO ... VALUES (?, ?, ...)", param11, param12, ...));
list.add(new Query("UPDATE ... ?, ? ...", param21, param22, ...);
list.add(new Query("DELETE FROM ... WHERE ... = ? AND ... = ? ...", param31, param32, ...));
ExecuteSet[] executeSet = database.execute(list);
// При необходимости контроль результата
} catch (Exception e) {
// обработка возможного исключения
...
}
Выполнить множество запросов модификации (INSERT, UPDATE, DELETE) в одной транзакции. Уровень изоляции определяется либо в СУБД (действующий по умолчанию), либо в конфигурации объекта приложения ru.funsys.avalanche.sql.Database. При установленном параметре ignore в значении true ошибки выполнения любого запроса игнорируются. Возвращает массив объектов, содержащих число модифицированных записей и время выполнения каждого запроса
Пример
try {
Query query1 = new Query("INSERT INTO ... VALUES (?, ?, ...)", param11, param12, ...);
Query query2 = new Query("UPDATE ... ?, ? ...", param21, param22, ...);
Query query3 = new Query("DELETE FROM ... WHERE ... = ? AND ... = ? ...", param31, param32, ...);
ExecuteSet[] executeSet = database.execute(true, query1, query2, query3);
// При необходимости контроль результата
} catch (Exception e) {
// обработка возможного исключения
...
}
Метод получения метаданных базы. Передаваемые параметры могут быть чувствительны к регистру в используемой СУБД. Для настройки регистра используется конфигурационный параметр ru.funsys.avalanche.sql.Database.
Пример получения структуры таблицы
try {
String schema = ...;
String table = ...;
ResultSet resultSet = database.metadata("getColumns", null, schema, table, (String) null);
while (resultSet.next()) {
// Обработка результата
...
}
} catch (Exception e) {
// обработка возможного исключения
...
}
Вызов хранимой процедуры
Пример
try {
database.call("call ...", new InOutParameter(Types.INTEGER, idAuthor), new InOutParameter(Types.INTEGER, idProgramm), new InOutParameter(Types.VARCHAR, message));
} catch (Exception e) {
logger.error("Ошибка вызова хранимой процедуры", e);
}
Вызов хранимой процедуры
Пример
try {
QueryProcedure queryProcedure = new QueryProcedure("call ...", new InOutParameter(Types.INTEGER, idAuthor), new InOutParameter(Types.INTEGER, idProgramm), new InOutParameter(Types.VARCHAR, message))
database.call(queryProcedure);
} catch (Exception e) {
logger.error("Ошибка вызова хранимой процедуры", e);
}
Аннотация, описывающая связь поля класса (типа данных) с колонкой таблицы или результата
При выполнении SQL запросов, которые возвращают типизированные данные, происходит автоматическое связывание поля класса с колонкой таблицы/результата по имени (имя поля класса совпадает с именем колонки таблицы или результата и SQL тип может быть преобразован в тип поля класса). В тех случаях, когда по каким либо причинам поле класса не совпадает с именем поля таблицы/результата, используют аннотацию @Column для задания связи.
Пример использования. Требуется выполнить SQL запрос, в результате которого возвращается колонка user_name. Значения колонки user_name требуется установить в поле name экземпляров класса User.
SELECT user_name, ... FROM ...
У поля name класса User требуется объявить аннотацию @Column, в которой указывается имя колонки полученного результата
public class User {
@Column(name="user_name")
public String name;
...
}
Получение результата
...
User[] users = database.select("SELECT user_name, ... FROM ...", User.class, ....)
...
или
...
QueryType queryType = new QueryType("SELECT user_name, ... FROM ...", User.class, ....);
User[] users = database.select(queryType);
...
Класс-оболочка определения параметров SQL запроса. Имеет несколько вариантов конструктора.
/** * Создать объект запроса * * @param statement SQL выражение * * @param parameters параметры запроса */ public Query(String statement, Object... parameters) /** * Создать объект запроса * * @param statement statement SQL выражение * @param parameters параметры запроса */ public Query(String statement, Vector<Object> parameters) /** * Создать объект запроса * * @param statement statement SQL выражение * @param parameters параметры запроса */ public Query(String statement, List<Object> parameters)
Класс-оболочка определения параметров SQL запроса получения типизированного результата. Имеет несколько вариантов конструктора.
/** * @param statement SQL выражение * @param type тип возвращаемых записей * @param parameters параметры запроса */ public QueryType(String statement, Class<?> type, Object... parameters) /** * @param statement SQL выражение * @param type тип возвращаемых записей * @param parameters параметры запроса */ public QueryType(String statement, ArrayList<Object> parameters, Class<?> type)
Класс-оболочка определения параметров вызова хранимой процедуры. Имеет несколько вариантов конструктора.
/** * Создать объект запроса * * @param statement SQL выражение * * @param parameters параметры запроса */ public QueryProcedure(String statement, InOutParameter... parameters) /** * Создать объект запроса * * @param statement statement SQL выражение * @param parameters параметры запроса */ public QueryProcedure(String statement, Vector<InOutParameter> parameters) /** * Создать объект запроса * * @param statement statement SQL выражение * @param parameters параметры запроса */ public QueryProcedure(String statement, ArrayList<InOutParameter> parameters)
Класс-оболочка определения параметров хранимой процедуры. Имеет несколько вариантов конструктора. При задании типа параметра используется значения: 0 - IN, 1 - INOUT, 2 - OUT.
/** * Создает выходной параметр * * @param sqlType SQL тип параметра */ public InOutParameter(int sqlType) /** * Создает входной параметр * * @param sqlType SQL тип параметра * @param value значение входного параметра */ public InOutParameter(int sqlType, Object value) /** * Создает входной/выходной параметр * * @param type тип параметра (0 - IN, 1 - INOUT, 2 - OUT) * @param sqlType SQL тип параметра * @param value значение входного параметра */ public InOutParameter(int type, int sqlType, Object value)
Класс-оболочка возвращаемого результата. Этот класс позволяет получить доступ к результатам выполнения запросов в транзакции.
public class ExecuteSet {
/**
* Время выполнения запроса
*/
private long timer;
/**
* Количество модифицированных записей
*/
private int records;
/**
* Результат генерации ключей при вставке записей
*/
private ResultSet keys;
/**
* Полученный типизированный результат запроса
*/
private Object[] rows;
/**
* Полученный результат запроса
*/
private ResultSet resultSet;
/**
* Исключение, возникшее при выполнении выражения
*/
private java.sql.SQLException exception = null;
public long getTimer() {
return timer;
}
public int getRecords() {
return records;
}
public ResultSet getKeys() {
return keys;
}
public void setKeys(ResultSet keys) {
this.keys = keys;
}
public Object[] getRows() {
return rows;
}
public void setRows(Object[] rows) {
this.rows = rows;
}
public ResultSet getResultSet() {
return resultSet;
}
public void setResultSet(ResultSet resultSet) {
this.resultSet = resultSet;
}
public boolean isError() {
return exception != null;
}
public java.sql.SQLException getError() {
return exception;
}
}