Руководство программиста

При реализации функционала приложения, работающего с реляционной базой данных, используются следующие программные элементы библиотеки avalanche-sql:

КлассНазначение
ru.funsys.avalanche.sql.DatabaseОсновной объект выполнения SQL выражений
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

Класс ru.funsys.avalanche.sql.Database представляет собой абстракцию над источником данных (javax.sql.DataSource) и явно в коде приложения не используется. Для доступа к классу ru.funsys.avalanche.sql.Database требуется адаптер ru.funsys.avalanche.sql.Adapter, поле которого должно присутствовать в коде класса, а в конфигурации приложения должно присутствовать секция адаптера.

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;

	...
} 

Метод - ResultSet select(String statement, Object... parameters)

Выполнить запрос 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) {
	// обработка возможного исключения
	...
}

Метод - <T< T[] select(String statement, Class<? extends T> type, Object... parameters)

Выполнить запрос 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) {
	// обработка возможного исключения
	...
}

Метод - ResultSet select(String statement, Vector<Object> parameters)

Выполнить запрос 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) {
	// обработка возможного исключения
	...
}

Метод - ResultSet select(String statement, List<Object> parameters)

Выполнить запрос 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) {
	// обработка возможного исключения
	...
}

Метод - ResultSet select(Query query)

Выполнить запрос 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) {
	// обработка возможного исключения
	...
}

Метод - <T< T[] select(QueryType query)

Выполнить запрос 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) {
	// обработка возможного исключения
	...
}

Метод - Object[] select(Query[] queries)

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

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) {
	// обработка возможного исключения
	...
}

Метод - int execute(String sql, Object... parameters)

Выполнить запрос модификации (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) {
	// обработка возможного исключения
	...
}

Метод - int execute(String sql, Vector<Object> parameters)

Выполнить запрос модификации (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) {
	// обработка возможного исключения
	...
}

Метод - int execute(String sql, List<Object> parameters)

Выполнить запрос модификации (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) {
	// обработка возможного исключения
	...
}

Метод - int execute(Query query)

Выполнить запрос модификации (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) {
	// обработка возможного исключения
	...
}

Метод - ExecuteSet[] execute(Query... queries)

Выполнить множество запросов модификации (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) {
	// обработка возможного исключения
	...
}

Метод - ExecuteSet[] execute(List<Query> list)

Выполнить множество запросов модификации (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) {
	// обработка возможного исключения
	...
}

Метод - ExecuteSet[] execute(boolean ignore, Query... queries)

Выполнить множество запросов модификации (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) {
	// обработка возможного исключения
	...
}

Метод - ResultSet metadata(String method, String catalog, String schema, String table, Object... args)

Метод получения метаданных базы. Передаваемые параметры могут быть чувствительны к регистру в используемой СУБД. Для настройки регистра используется конфигурационный параметр 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) {
	// обработка возможного исключения
	...
}

Метод - ResultSet[] call(String sql, InOutParameter... parameters)

Вызов хранимой процедуры

Пример

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);
}

Метод - ResultSet[] call(QueryProcedure query)

Вызов хранимой процедуры

Пример

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);
}

ru.funsys.avalanche.sql.Column

Аннотация, описывающая связь поля класса (типа данных) с колонкой таблицы или результата

При выполнении 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);
	...

ru.funsys.avalanche.sql.Query

Класс-оболочка определения параметров 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)

ru.funsys.avalanche.sql.QueryType

Класс-оболочка определения параметров 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)
	

ru.funsys.avalanche.sql.QueryProcedure

Класс-оболочка определения параметров вызова хранимой процедуры. Имеет несколько вариантов конструктора.

	/**
	 * Создать объект запроса
	 * 
	 * @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)

ru.funsys.avalanche.sql.InOutParameter

Класс-оболочка определения параметров хранимой процедуры. Имеет несколько вариантов конструктора. При задании типа параметра используется значения: 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)

ru.funsys.avalanche.sql.ExecuteSet

Класс-оболочка возвращаемого результата. Этот класс позволяет получить доступ к результатам выполнения запросов в транзакции.

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;
	}
	
}