Das folgende Beispiel soll zeigen, wie man mit Spring arbeitet und Daten in einer relationalen Datenbank persistent macht. Um das Bespiel zum Laufen zu bringen müssen im Klassenpfad sein: hsqldb.jar, spring.jar, log4j-1.2.9.jar und common-logging.jar. Für die Log-Meldungen setzen wir in den Klassenpfad die Datei log4j.properties:
log4j.rootCategory=WARN, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%m%n
Beginnen wir mit unserem Geschäftsobjekt, einem Kunden:
package com.javatutor.domain;
public class Customer
{
private int id;
private String name;
public int getId()
{
return id;
}
public void setId( int id )
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName( String name )
{
this.name = name;
}
@Override
public String toString()
{
return String.format( "Customer[id=%d, name=%s]", id, name );
}
}
Für diesen Kunden definieren wir eine DAO-Schnittstelle, die uns später Exemplare der Geschäftsobjekte gibt und die Speicherung ermöglichen.
package com.javatutor.dao;
import java.util.Collection;
import com.javatutor.domain.Customer;
public interface CustomerDao
{
Collection<Customer> getCustomers();
Customer findCustomerById( int id );
void save( Customer customer );
}
Zum Testen der Applikation beginnen wir mit einer einfach DAO-Implementierung, die Kunden in einer HashMap speichert.
package com.javatutor.dao.map;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import com.javatutor.dao.CustomerDao;
import com.javatutor.domain.Customer;
public class CustomerDaoMapImpl implements CustomerDao
{
private Map<Integer, Customer> map = new HashMap<Integer, Customer>();
public Collection<Customer> getCustomers()
{
return map.values();
}
public Customer findCustomerById( int id )
{
return map.get( id );
}
public void save( Customer customer )
{
map.put( customer.getId(), customer );
}
}
Eine Applikation wird über die Spring-Konfigurationsdatei später mit einem konkreten CustomerDao gespritzt. Die Methode haveFun() legt einige Business-Objekte an und speichert sie über das DAO.
package com.javatutor;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import com.javatutor.dao.CustomerDao;
import com.javatutor.domain.Customer;
public class Application
{
private CustomerDao customerDao;
public void setCustomerDao( CustomerDao customerDao )
{
this.customerDao = customerDao;
}
private void haveFun()
{
System.out.println( customerDao.getCustomers() );
Customer c1 = new Customer();
c1.setId( 0 );
c1.setName( "Christian Ullenboom" );
customerDao.save( c1 );
System.out.println( customerDao.findCustomerById( 0 ) );
System.out.println( customerDao.getCustomers() );
Customer c2 = new Customer();
c2.setId( 1 );
c2.setName( "Tantiana Roujitcher" );
customerDao.save( c2 );
System.out.println( customerDao.getCustomers() );
}
//
public static void main( String[] args )
{
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "spring.xml" );
Application bean = (Application) context.getBean( "Application" );
bean.haveFun();
}
}
Jetzt fehlt nur noch die XML-Datei für Spring:
<?xml version="1.0"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="Application" class="com.javatutor.Application">
<property name="customerDao">
<ref local="CustomerDao" />
</property>
</bean>
<bean id="CustomerDao" class="com.javatutor.dao.map.CustomerDaoMapImpl" />
</beans>
Startet man das Programm, ist die Ausgabe
[]
Customer[id=0, name=Christian Ullenboom]
[Customer[id=0, name=Christian Ullenboom]]
[Customer[id=1, name=Tantiana Roujitcher], Customer[id=0, name=Christian Ullenboom]]
Prima. Es klappt. Jetzt kommt eine DAO-Implementierung für JDBC. Zunächst die Klasse.
package com.javatutor.dao.jdbc;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import com.javatutor.dao.CustomerDao;
import com.javatutor.domain.Customer;
public class CustomerDaoJdbcImpl extends JdbcTemplate implements CustomerDao
{
@SuppressWarnings("unchecked")
public Collection<Customer> getCustomers()
{
return query( "SELECT Id, Name FROM Customers", new CustomerRowMapper() );
}
public Customer findCustomerById( int id )
{
String sql = "SELECT Id, Name FROM Customers WHERE Id = ?";
try
{
return (Customer) queryForObject( sql,
new Object[] { id },
new CustomerRowMapper());
}
catch ( IncorrectResultSizeDataAccessException e ) { }
return null;
}
public void save( Customer customer )
{
if ( findCustomerById( customer.getId() ) == null )
{
Object[] args = { customer.getId(), customer.getName() };
update( "INSERT INTO Customers (Id, Name) VALUES (?,?)", args );
}
else
{
Object[] args = { customer.getName(), customer.getId() };
update( "UPDATE Customers SET Name = ? WHERE Id = ?", args );
}
}
}
class CustomerRowMapper implements RowMapper
{
public Object mapRow( ResultSet rs, int rowNum ) throws SQLException
{
Customer c = new Customer();
c.setId( rs.getInt( "Id" ) );
c.setName( rs.getString( "Name" ) );
return c;
}
}
Und in der XML-Datei ergänzen wir für den JDBC-DAO:
<bean id="CustomerDaoJdbc" class="com.javatutor.dao.jdbc.CustomerDaoJdbcImpl">
<property name="dataSource"><ref local="DataSource" /></property>
</bean>
<bean id="DataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>org.hsqldb.jdbcDriver</value>
</property>
<property name="url">
<value>jdbc:hsqldb:mem:customers</value>
</property>
<property name="username">
<value>sa</value>
</property>
<property name="password">
<value></value>
</property>
</bean>
Damit unsere Applikation mit dem neuen JDBC-DAO gespritzt wird setzt man.
<bean id="Application" class="com.javatutor.Application">
<property name="customerDao">
<ref local="CustomerDaoJdbc" />
</property>
<property name="dataSource">
<ref local="DataSource" />
</property>
</bean>
Gleichzeitig geben wir der Applikation eine DataSource, damit sie die Tabelle für die Datenbank anlegen kann.
public void setDataSource( DataSource dataSource )
{
new JdbcTemplate( dataSource ).execute( "CREATE TABLE Customers( Id INTEGER, Name VARCHAR(128) ) " );
}
Das gestartet Programm gibt nun die gleiche Ausgabe.