SPRING-SOURCE.RU | |
|
|
Существует много статей о том, как делать инъекцию зависимости в Spring, но очень мало толковой информации о подключениях к базам данных. В Spring это можно делать либо напрямую при помощи JDBC либо использовать ORM технологии, например, Hibernate.
В серии уроков мы поэтапно рассмотрим основные моменты подключения и выполнения запросов к базе данных. Начнем с JDBC и закончим, наверное, Hibernate-ом в связке со Spring-ом. Это будет выглядеть, как изучение от сложного к простому, так как Spring все очень упрощает (пишем меньше кода).
Начнем наш урок с создания класса:
public class Student { protected String name; //Getters and setters
Это обычный JAVA класс, так называемый POJO. Здесь одно поле и два метода (напишите их сами) setter и getter, которые устанавливают и возвращают что либо.
Теперь перейдем к базе данных. Мы будем использовать базу данных Hypersonic (hsqldb.jar). Прежде всего скачайте из интернета этот файл. Находясь в той же директории, где и hsqldb.jar напишите в командной строке такую команду:
java -cp hsqldb.jar org.hsqldb.Server -database.0 file:data/test -dbname.0 asiavant
После выполнения команды у вас должен стартовать сервер. Что в этой команде мы указали? Аргумент file:data/test это путь, где будут созданы файлы, то есть в папке data и имя файлов test. А –dbname.0 asiavant указывает псевдоним базы данных. Псевдоним, который используется для доступа к JDBC при помощи HSQLDB. Цифры нуль указывают индекс базы данных. Индексы могут быть от 0 – 9.
Теперь можно запускать менеджер, который поможет нам создать таблицу в нашей базе:
java -cp hsqldb.jar org.hsqldb.util.DatabaseManager
После выполнения этой команды вы увидите окно как на картинке. Добавьте в строку URL слово asiavant – наш алиас. Проверьте остальные параметры и нажимайте кнопку ОК.
CREATE TABLE STUDENT ( NAME VARCHAR )
Когда вы успешно выполните программу, то снова запускайте этот менеджер и наберите команду SELECT * FROM имя таблицы и вы сможете увидеть результаты вашей работы.
Все, таблица создана и менеджер нам пока больше не нужен. Выполняем команду SHUTDOWN COMPACT.
Student student = new Student(); student.setName("Amitabh"); try{ Class.forName("org.hsqldb.jdbcDriver"); }catch(ClassNotFoundException cfe){ System.out.println("Driver not found"); System.exit(0); } Connection conn = null; PreparedStatement stmt = null; try{ conn = DriverManager.getConnection ("jdbc:hsqldb:hsql://localhost","sa",""); stmt = conn.prepareStatement ("insert into STUDENT (name) values (?) "); stmt.setString(1, student.getName()); stmt.execute(); }catch(SQLException se){ System.out.println("Problem with data insert"); } finally{ try{ if(stmt != null) {stmt.close();} if(conn != null) {conn.close();} } catch(SQLException se) {}
Что здесь происходит:
Обратите внимание, что кроме тех мест, где мы работаем с запросами, мы можем видеть, что код повторяется. Прежде чем двигаться дальше давайте взглянем в сторону Spring DAO. Этот подход основан на реализации интерфейсов. Давайте определим наш интерфейс:
public interface StudentDao { public void saveStudent(Student student); }
Если мы используем JDBC, то реализация класса будет выглядеть следующим образом:
public class StudentJdbcDao implements StudentDao{ public void saveStudent(Student student) { } }
Зачем нужны шаблоны? Роль шаблона – убрать весь повторяющийся код, чтобы разработчик мог сосредоточиться на бизнес логике. Spring обрабатывает доступ к данным, используя шаблоны и callback. Код, такой как открытие и закрытие соединения, выполняется шаблоном, а переменная часть кода, обработка результата, например, обрабатывается callback.
Spring поддерживает несколько шаблонов доступа к данным для различных механизмов сохранения:
На данный момент мы ищем способ взаимодействия с базой через JDBC. Давайте сначала попробуем JdbcTemplate. Этот шаблон автоматически обрабатывает управление ресурсами, обработку исключений и управление транзакциями. Теперь наша реализация класса для JdbcDAO выглядит так:
public class StudentJdbcDao implements StudentDao{ private JdbcTemplate jdbcTemplate; public void setJdbcTemplate(JdbcTemplate jdbcTemplate){ this.jdbcTemplate = jdbcTemplate; } public void saveStudent(Student student) { jdbcTemplate.update ("insert into STUDENT (name) values (?)",new Object[] {student.getName()} ); } }
Вопрос теперь в том, как получить jdbcTemplate. Сделаем это при помощи Spring.
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource" /> </bean> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" destroy-method="close"> <property name="driverClassName" value="org.hsqldb.jdbcDriver" /> <property name="url" value="jdbc:hsqldb:hsql://localhost" /> <property name="username" value="sa" /> <property name="password" value="" /> </bean>
DataSource – это бин, который предоставляет все свойства для соединения к базе данных. Затем мы делаем инъекцию dataSource в jdbcTemplate и затем делаем инъекцию jdbcTemplate в StudentJdbcDao.
<bean id="studentDao" class="StudentJdbcDao"> <property name="jdbcTemplate" ref="jdbcTemplate" /> </bean>
Теперь мы можем получить доступ к dao вызвав следующий код:
Student student = new Student(); student.setName("AmitabhDao"); StudentDao studentDao = (StudentDao)appContext.getBean("studentDao"); studentDao.saveStudent(student);
Для всех приложений JDBC поддерживает DAO классы и мы должны быть уверены что добавили JdbcTemplate свойство и установили setter метод. Также мы должны быть уверены, что связали JdbcTemplate бин с JdbcTemplate свойством нашего DAO. Это не столь большая трудность для одного DAO, но что делать если у нас их много? Код начнет повторяться, а этого нам не нужно.
Решением может быть создание класса для всех ваших DAO объектов, где JdbcTemplate свойство уже установлено. Затем все наши DAO классы расширяют этот класс и используют JdbcTemplate свойство родительского класса для доступа к данным.
При помощи dao есть возможность сократить код там, где мы делаем инъекцию jdbcTemplate. Если мы воспользуемся этими возможностями, то получим следующий код:
public class StudentJdbcDao extends JdbcDaoSupport implements StudentDao { public void saveStudent(Student student) { this.getJdbcTemplate().update ("insert into STUDENT (name) values (?)", new Object[] {student.getName()} ); } }
JdbcDaoSupport предоставляет удобный доступ к JdbcTemplate через getJdbcTemplate метод. Когда конфигурируем наш DAO класс в Spring, вы можете напрямую связывать JdbcTemplate бин в jdbcTemplate свойство. После расширения JdbcDaoSupport класса нам больше нет необходимости связывать JdbcTemplate бин с нашим DAO классом. Теперь мы пишем так:
<bean id="studentDao" class="com.dataccesstest.StudentJdbcDao"> <property name="dataSource" ref="dataSource" /> </bean>
Когда StudentJdbcDao имеет свой сконфигурированное dataSource свойство, тогда он внутри себя создаст JdbcTemplate. Это устраняет неоьходимость явно объявлять JdbcTemplate бин в Spring.
Spring предоставляет несколько способов конфигурирования data source:
Ранее мы видели, как работать с соединениями используя свойства соединения, когда мы работали с JDBC напрямую. Spring предоставляет два основных драйвера:
Spring предоставляет три типа класса шаблонов для работы с JDBC:
Каждый класс шаблона поддерживает DaoSupport класс для простого связывания шаблонов. Мы уже видели использование JdbcTemplate. Давайте взглянем как работает NamedParameterJdbcTemplate. В этом случае DAO класс будет выглядеть так:
public class StudentJdbcDao implements StudentDao { protected NamedParameterJdbcTemplate namedJdbcTemplate; //Method to inject NamedParameterJdbcTemplate public void setNamedJdbcTemplate (NamedParameterJdbcTemplate namedJdbcTemplate) { this.namedJdbcTemplate = namedJdbcTemplate; } public void saveStudent(Student student) { Map parameters = new HashMap(); parameters.put("name",student.getName()); namedJdbcTemplate.update ("insert into STUDENT (name) values (:name)", parameters); } ... }
Xml будет выглядеть так:
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate"> <constructor-arg ref="dataSource" /> </bean>
Обратите внимание, что источник данных вводиться через конструктор и SimpleJdbcTemplate будет выглядеть следующим образом:
protected SimpleJdbcTemplate simpleJdbcTemplate; //Setter method for SimpleJdbcTemplate ... public void saveStudent(Student student) { //Note how the arguments are passed. It uses varargs feature. simpleJdbcTemplate.update ("insert into STUDENT (name,percentage) values (?,?)", student.getName(),student.getPercentage());
XML конфигурация:
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate"> <constructor-arg ref="dataSource" /> </bean>
Давайте посмотрим как нам извлекать коллекции из базы данных. Мы будем использовать SimpleJdbcTemplate:
public List<Student> getAllStudents() { return simpleJdbcTemplate.query ("Select name as Name from Student", new ParameterizedRowMapper<Student>(){ public Student mapRow(ResultSet rs,int rowNum) throws SQLException { Student student = new Student(); student.setName(rs.getString("Name")); return student; } } ); }
Copyright © 2024 |