SPRING-SOURCE.RU | |
|
|
Хранение данных в объектно-реляционных системах называется persistence (сохранение). Когда объект данных сохраняется в базу данных, значит объект считается сохраненным (persisted).
В JPA используется революционный подход для сохранения объекта, выбрасывая тяжелый Java EE контейнер за уравнение. Также JPA может хорошо работать с остальной частью Java EE 5 движка.
До прихода JPA, Spring фреймворк поддерживал различные persistence механизмы. Он поддерживал прямое использование JDBC, реализацию доступа к данным объекта (DAO), и различные ORM технологии.
Эта глава вводит вас во множество средств доступа к данным и поддержку persistence. Вы увидите как Spring использует DAO, шаблоны и другое. Самое главное, что вы узнаете о JPA и как Spring позволяет сделать persistence для любого POJO компонента с почти не специфичного для базы данных API программирования.
Практические упражнения в этой главе позволят сделать доступным persistence для доменной модели объектов PIX. Вы получите знания о том как хранить, получать, и изменять PIX POJO в и из реляционных баз данных.
В этой главе вы узнаете:
JDBC API - это низкоуровневый API, который взаимодействует с реляционными базами данных. Каждый поставщик РБД предоставляет драйвер совместимый с JDBC. Драйвер напрямую взаимодействует с базой данных, как показано на диаграмме.
Диаграмма иллюстрирует, как разработчики могут писать свой доступ к базе с использованием JDBC API. Эта API реализация построена на Java SE платформе и не требует установки другого вида. Доступ к базе от различных поставщиков, требует наличие драйвера. JDBC драйвер уже загружен в большинство RDBMS. Все новые РБД движки предоставляют интерфейсы к своей функциональности через SQL и JDBC операции основаны в первую очередь на отправке SQL запросов к РДБ и затем извлечения результата. В сущности, когда пишем JDBC код, вы должны создавать SQL запросы, выполнять их на сервере, и затем работать с табличным результатом, который вернул сервер.
Второй рисунок показывает, как JDBC код может сохранять данные объекта в РБД. Вы должны пройти дерево сохраняемых объектов и для каждого такого объекта вы должны сохранять каждое значение поля соответственно полям в таблице БД. Код должен создавать и отправлять SQL запрос в РБД для осуществления операции. Сопоставление между объектами и РБД делается вручную и все взаимосвязи должны жестко кодироваться в JDBC логике доступа.
JDBC API дает программисту прямой контроль над доступом к БД и управлению кэшем. Но есть некоторые характеристики, которые делают его довольно утомительным в использовании:
SQLException java.sql.BatchUpdateException: DB2-008: unique constraint (DB2_CS003) violated
Такое исключение следует интерпретировать на основе кода ошибки конкретного производителя БД.
Следующий код демонстрирует пример JDBC для сохранения одного класса домена PIX. Этот код повторяющийся и объемный. Это также иллюстрирует недостатки изложенные ранее.
package com.wrox.beginspring.pix.dao.examples; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import com.wrox.beginspring.pix.model.Album; /* * <pre> * The album database named pix is created. * The album managment tables along with sequence tables * ALBUM_SEQUENCE and PICTURE_SEQUENCE is created * <pre> */ public class AlbumDao { public void insertAlbum(Album album) { Connection con = null; PreparedStatement stmt = null; try { con = getConnection(); con.setAutoCommit(false); System.out.println("Persisting User = " + album.getUser().getUserName()); // Create User stmt = con .prepareStatement("INSERT INTO PIXUSER (USERNAME,FIRSTNAME,LASTNAME," + "EMAIL,PASSWORD)" + "values (?, ?,?,?,?)"); stmt.setString(1, album.getUser().getUserName()); stmt.setString(2, album.getUser().getFirstName()); stmt.setString(3, album.getUser().getLastName()); stmt.setString(4, album.getUser().getEmail()); stmt.setString(5, album.getUser().getPassword()); stmt.execute(); System.out.println("Persisting User"); System.out.println("User = " + album.getName()); // Get Album sequence. stmt = con .prepareStatement("insert into album_sequence values (null)"); stmt.execute(); stmt = con .prepareStatement("select max(identity()) from album_sequence"); ResultSet rs = stmt.executeQuery(); if (rs.next()) { // Retrieve the auto generated key i.e movie_id. album.setId(rs.getInt(1)); } stmt = con .prepareStatement("INSERT INTO ALBUM (ID,DTYPE,NAME, DESCRIPTION,USER_USERNAME)" + "values (?,?,?, ?,?)"); stmt.setInt(1, album.getId()); stmt.setString(2, "H"); stmt.setString(3, album.getName()); stmt.setString(4, album.getDescription()); stmt.setString(5, album.getUser().getUserName()); stmt.execute(); System.out.println("Persisting Album"); System.out.println("Album id generated = " + album.getId()); int count = album.getPictures().size(); // Insert Picture information and get the picture id auto generated // key. for (int i = 0; i < count; i++) { // Get Picture sequence. stmt = con .prepareStatement("INSERT INTO PICTURE_SEQUENCE VALUES(null)"); stmt.execute(); stmt = con .prepareStatement("select max(identity()) from picture_sequence"); rs = stmt.executeQuery(); if (rs.next()) { // Retrieve the auto generated key i.e movie_id. album.getPictures().get(i).setId(rs.getInt(1)); } stmt = con .prepareStatement("INSERT INTO PICTURE (ID,NAME,SIZE)" + "values (?,?, ?)"); // Set picture name and size. stmt.setInt(1, album.getPictures().get(i).getId()); stmt.setString(2, album.getPictures().get(i).getName()); stmt.setFloat(3, album.getPictures().get(i).getSize()); stmt.execute(); System.out.println("Picture id generated = " + album.getPictures().get(i).getId()); } // Associate album and picture. System.out.println("Linking album and picture"); for (int i = 0; i < count; i++) { stmt = con .prepareStatement("INSERT INTO ALBUM_PICTURE (ALBUM_ID,PICTURES_ID)" + "values (?, ?)"); // Set album id stmt.setInt(1, album.getId()); stmt.setInt(2, album.getPictures().get(i).getId()); stmt.execute(); } // Commit transaction con.commit(); System.out.println("Insert successful"); } catch (SQLException e) { e.printStackTrace(); try { con.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } // throw Exception } finally { try { if (stmt != null) { stmt.close(); } if (con != null) { con.close(); } } catch (SQLException e1) { // Log error. } } } private Connection getConnection() throws SQLException { // Take from connection pool or from DriverManager DriverManager.registerDriver(new org.hsqldb.jdbcDriver()); //If not using default setup; change the URL to point to pix database. return DriverManager.getConnection("jdbc:hsqldb:hsql://localhost/pix", "sa", ""); } }
Copyright © 2024 |