Simon Wirtz
Seminarvortrag WS 13/14
Oktober 2013
© 2012 TravelTainment
Datenbankzugriffe in Java-Applikationen
mit Hilfe des Spring Frameworks
Inhaltsübersicht
1. Motivation und Einleitung
2. Java Database Connectivity
2.1 Anwendung
2.2 Problematik der Technologie
3. Objektrelationale Abbildungen
3.1 Hibernate
3.1.1 Anwendung
3.1.2 Vergleich zu JDBC
© 2012 TravelTainment
Inhaltsübersicht
4. Spring
4.1 Kerntechnologien
4.2 Spring Data Access/Integration
4.2.1 Spring JDBC
4.2.1.1 Das JdbcTemplate
4.2.1.2 Vorteile der Technologie
4.2.2 Spring ORM
4.2.2.1 Nutzung von Hibernate mit Spring
4.2.2.2 Vorteile von Spring ORM für Hibernate
5. Fazit
© 2012 TravelTainment
1. Motivation und Einleitung
Viele Computeranwendungen arbeiten mit Datenbanken
Datenbankzugriff in Applikationen über verschiedene
Tools und Technologien
In Java:
ORM
Spring
• primäre DB-Schnittstelle
• Fortgeschritten und objektorientiert
• Weitere Erleichterungen
© 2012 TravelTainment
JDBC
© 2012 TravelTainment
Kapitel 2
JDBC
2. Java Database Connectivity
Datenbankschnittstelle der Java-Plattform
Am 19. Februar 1997 erstmals veröffentlicht
Neueste Version: JDBC 4.1
Hauptfunktionalität:
SQLAbfragen
senden
Mit den
Ergebnissen
arbeiten
© 2012 TravelTainment
Verbindung
zu DB
aufbauen
2.1 Anwendung
private String url = "...", dbName = "...",
userName = "..", password = "...";
private Connection connection = null;
private Statement statement = null;
private ResultSet resultSet = null;
//load driver and connect to db
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {...}
try {
connection = DriverManager.getConnection(url + dbName,
userName, password);
} catch (SQLException ex) {...}
Verbindungsaufbau
try {
statement = connection.createStatement();
resultSet = statement.executeQuery("SELECT * FROM car;");
printResult();
} catch (SQLException ex) {...}
Abfrage senden
while (resultSet.next()) {
Car car = new Car();
car.setHorsePower(resultSet.getInt("horsepower"));
car.setId(resultSet.getInt("id"));
//set more attributes
System.out.println(car);
}
} catch (SQLException ex) {...}
Verarbeiten
© 2012 TravelTainment
try {
2.2 Problematik der Technologie
JDBC arbeitet SQLbasiert!
Geschäftslogik <
Verwaltung
Aufwändiges
Ressourcenmanagement
•Sich wiederholender
Prozess
Exceptionhandling
bei allen APIAufrufen
© 2012 TravelTainment
Manuelles
Überführen von
Datenbankeintrag in
Objekt und
umgekehrt
© 2012 TravelTainment
Kapitel 3
ORM
3. Objektrelationale Abbildung
Erlaubt das Ablegen von Objekten in einer Datenbank
Schicht zwischen Anwendung und Datenbank
Behandelt Unverträglichkeit zwischen Objekten und
relationalen Datenbanken
ORM
1
NAME
Simon
Beispiel Java: Java Persistence API
DESCRIPTION
Test
AGE
21
© 2012 TravelTainment
ID
3.1 Hibernate
Implementierung der Java Persistence API
Neuste Version im März 2013 veröffentlicht: 4.2.0
Mapping der POJOs über XML oder Annotationen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Parameterloser Konstruktor ist Pflicht
import javax.persistence.*;
@Entity
public class Person {
@Id
@GeneratedValue (strategy=GenarationType.AUTO)
private int id;
@Column(name="firstName", nullable=false, unique = true)
private String name;
private String description;
private Integer age;
public Person(){}
/* getter and setter */
}
Importieren des
Packages
Annotieren des
POJOs mit @Entity
und einer @Id
@Column zur
Spezifizierung der
Spaltendefinition
© 2012 TravelTainment
Konfigurationsdatei
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
hibernate.cfg.xml
Beinhaltet Daten für SessionFactory
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd" >
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">
com.mysql.jdbc.Driver
</property>
<property name="connection.url">
jdbc:mysql://localhost/hibernate
</property>
<property name="connection.username">user</property>
<property name="connection.password">password</property>
Datenbankspezifikation
<!-- JDBC connection pool -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">update</property>
<mapping class="model.Person"/>
</session-factory>
</hibernate-configuration>
Weitere
Spezifikationen wie
„Dialect“
Annotierte Klassen
© 2012 TravelTainment
3.1.1 Anwendung
private SessionFactory factory = null;
private Configuration configuration = null;
private ServiceRegistry serviceRegistry = null;
configuration = new Configuration().configure();
serviceRegistry = new ServiceRegistryBuilder().
applySettings(configuration.getProperties()).
buildServiceRegistry();
factory = configuration.buildSessionFactory(serviceRegistry);
Erzeugen der
SessionFactory
Session wird aus SessionFactory bezogen
Ausführen einer Query über Session
Methode ist in Transaktion gehüllt
© 2012 TravelTainment
Session session = factory.withOptions().openSession();
session.beginTransaction();
Query query = session.createQuery("from Person");
List<Person> persons = (List<Person>)query.list();
session.getTransaction().commit();
3.1.2 Vergleich zu JDBC
Beispiel: Abfragen eines Objekts aus der Datenbank
private ResultSet doQuery(String query){
ResultSet result = null;
try{
connectToDb();
stmt = conn.createStatement();
result = stmt.executeQuery(query);
} catch (Exception e){...}
return result;
public Person getById(Integer id){
}
Session session = factory.withOptions().openSession();
session.beginTransaction();
String select = "from Person p where p.id = " + id;
Query query = session.createQuery(select);
Person p = (Person) query.uniqueResult();
session.getTransaction().commit();
return p;
}
© 2012 TravelTainment
public Person getById(Integer id){
String query = "SELECT * from person where id= "+id;
ResultSet result = doQuery(query):
Person person = null;
try{
while(result.next()){
String name = result.getString("name");
String desc = result.getString("description");
Integer age = result.getInt("age");
Integer idValue = result.getInt("id");
person = new Person(name, desc, age, idValue);
}
closeConnAndStmt();
} catch(SQLException sqlE){...}
return person;
}
3.1.2 Vergleich zu JDBC
Geschäftslogik steht
mehr im Vordergrund
(Sinn der
Technologie)
OO-Konzept wird
verfolgt
© 2012 TravelTainment
Weniger
Verwaltungsaufwand
Überführung der DBEinträge in Objekte
nicht nötig
© 2012 TravelTainment
Kapitel 4
Spring
4 Spring
Modular aufgebautes Framework (ca. 20 Module)
Aktuelle Version: 3.2 vom 13.12.2012
Ziel:
Entwicklung mit Java/JEE vereinfachen
gute Programmierpraktiken fördern
© 2012 TravelTainment
Dependeny Injection bzw. Inversion of Control
IoC-Container beinhaltet alle wichtigen ApplikationsKomponenten (Beans) inklusive Abhängigkeiten
Beans können aus ApplicationContext bezogen
werden
© 2012 TravelTainment
4.1 Kerntechnologien
Bean-Definition
1. XML
<bean id="exampleBean" class="examples.ExampleBean">
<!-- setter injection using the 'ref' attribute -->
<property name="beanOne" ref="anotherExampleBean"/>
<property name="integerProperty" value="1"/>
</bean>
<bean id="anotherExampleBean" class="examples.AnotherBean"/>
2. Annotationen
@Component
public class ExampleBean {
// other attributes and methods
}
© 2012 TravelTainment
@Autowired
private AnotherBean beanOne;
private int integerProperty;
4.2 Spring Data Access / Integration
© 2012 TravelTainment
Wie gestaltet Spring das
Arbeiten mit JDBC und Hibernate
angenehmer und einfacher?
© 2012 TravelTainment
Spring JDBC
4.2.1.1 Das JdbcTemplate
Einschränkungen in JDBC
Springs Lösungsansatz: JdbcTemplate
Threadsafe, kann in allen DAOs genutzt werden
Benötigt DataSource, das Verbindungsparameter definiert:
© 2012 TravelTainment
<bean id="mySqlDataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/db"/>
<property name="username" value="user_xy" />
<property name="password" value="pw_xy" />
</bean>
Nutzung des JdbcTemplates
Injizieren der DataSource-Bean in DAO:
@Repository
public class ExampleDao implements IExampleDao {
private JdbcTemplate jdbcTemplate;
@Autowired
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
// JDBC-backed implementations of the methods on the ExampleDao
}
JdbcTemplate stellt ca. 100 Methoden bereit
execute(sql: String)
update()-Methoden
public void insertCar(Car car) {
String query = "INSERT INTO car (id, make, horsepower)"+
"VALUES(?,?,?);";
jdbcTemplate.update(query, "DEFAULT", car.getMake(),
car.getHorsePower());
}
© 2012 TravelTainment
Vereinfachtes Mapping
RowMapper-Interface
private static final class CarMapper implements RowMapper<Car> {
@Override
public Car mapRow(ResultSet resultSet, int i) throws SQLException {
Car result = new Car();
result.setMake(resultSet.getString("make"));
result.setHorsePower(resultSet.getInt("horsepower"));
result.setId(resultSet.getInt("id"));
result.setSeats(resultSet.getInt("seats"));
result.setType(resultSet.getString("type"));
return result;
}
Implementierung
public Car getCarById(int id) {
String query = "SELECT * FROM car WHERE id=?";
Car car = jdbcTemplate.queryForObject(query, new CarMapper(), id);
return car;
}
Nutzung
© 2012 TravelTainment
}
4.2.1.2 Vorteile der Technologie
Kein
Behandeln
von SQLExceptions
Kein
Ressourcenmanagement
Kapselung
JDBCCode in
Template
Anwendungslogik steht im Vordergrund
© 2012 TravelTainment
Kein
Iterieren
durch
ResultSet
© 2012 TravelTainment
Spring ORM
4.2.2 Spring ORM
Folgendes Kapitel konzentriert sich auf Hibernate
Spring bietet First-Level Support für Hibernate
Früher: Template-Klassen wie bei JDBC gesehen
Ziele
Einfaches
Testen und
Warten
Lose
Kopplung
© 2012 TravelTainment
Schichtentrennung
4.2.2.1 Nutzung von Hibernate mit Spring
Hibernate ohne Spring:
SessionFactory erzeugen mithilfe der Konfigurationsdatei
Hibernate mit Spring:
SessionFactory als Bean definieren
DataSource injizieren
SessionFactory in alle relevanten Klassen injizieren
<bean id="mySqlDataSource" class="...BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/table"/>
<property name="username" value="user_xy" />
<property name="password" value="pw_xy" />
</bean>
<bean id="sessionFactory" class="...LocalSessionFactoryBean">
<property name="dataSource" ref="mySqlDataSource" />
<property name="hibernateProperties">
<value>hibernate.dialect=...MySQLDialect</value>
<!--more hibernate properties-->
</property>
<!-- more sessionFactory properties -->
</bean>
© 2012 TravelTainment
SessionFactory in DAO nutzen
konsistente RuntimeExceptions
(DataAccessException).
Wie gewohnt, Hibernate
in DAOs benutzen
© 2012 TravelTainment
Injizieren der
SessionFactory-Bean
Annotieren mit
@Repository
4.2.2.1 Nutzung von Hibernate mit Spring
Weitere Erleichterung durch Spring-TransactionManagement:
Ohne Spring
• Manuelles Starten
und Beenden von
Transaktionen
Mit Spring
• @Transactional
• Spring handhabt
Transaktionen
eigenständig:
• Öffnen, Schließen,
Fehlerbehandlung
© 2012 TravelTainment
4.2.2.2 Vorteile
Einfache Möglichkeit, SessionFactorys bzw.
DataSources auszutauschen
Exceptions werden in einheitliche Hierarchie überführt
Transaktionsmanagement wird vereinfacht
Allgemein:
Dependency Injection
Losere Kopplung zwischen
Applikationskomponenten
© 2012 TravelTainment
Geschäftslogik wird von
Datenzugriffs- und
Transaktionsstrategien getrennt
© 2012 TravelTainment
Kapitel 5
Fazit
5. Fazit
Spring JDBC:
JdbcTemplate kapselt „boilerplate code“
Kein manuelles Verbindungs-, Transaktions- oder
Ressourcenmanagement notwendig
Spring vereinfacht Mapping zwischen Objekt und
relationalem Datensatz (RowMapper)
Weiterhin SQL-basiert
© 2012 TravelTainment
5. Fazit
Spring ORM/Hibernate:
Kein Template, sondern Arbeiten mit Standard-API
Kein manuelles Aufsuchen der Konfigurationsdatei oder
Erstellen der SessionFactory
Definition der SessionFactory in Spring-Context führt zu
loserer Kopplung
Transaktions- und Exceptionhandling wird verbessert
Spring ist eine Bereicherung für Hibernate-Anwendung!
© 2012 TravelTainment
Quellen
M. Konda, Just Spring Data Access, 2012
R. Johnson, J. Hoeller u.a., Spring Framework
Reference Documentation 3.2.3, 2013
S. Slavic, „community.jboss.org“, 2010
M. Inden, Der Weg zum Java-Profi, 2011
M. Fowler, „martinfowler.com“, 2004
Wikipedia, August 2013: „Java Database
Connectivity“, „Objektrelationale Abbildung“, „Java
Persistence API“, „Spring“, „Hibernate“
Für detaillierte Angaben vgl. Literaturverzeichnis im
Skript.
© 2012 TravelTainment
© 2012 TravelTainment
Fragen
© 2012 TravelTainment
Vielen Dank für die Aufmerksamkeit