Um mit value % 2 == 1 zu testen, ob value eine ungereade Zahl ist, muss value positiv sein, denn -3 % 2 wertete Java zu -1 aus. Der Test auf ungereade Zahlen wird erst wieder korrekt mit value % 2 != 0.
Insel: Innere Klasse und Serializable
Werden Exemplare einer nicht statischen inneren Klasse serialisiert, die äußere Klasse implementiert aber nicht Serializable, gibt es einen Fehler, denn intern hält ein Objekt der inneren Klasse einen Verweis auf das Exemplar der äußeren Klasse. Statische innere Klassen machen das nicht, was das Problem mit der Serialisierung lösen kann. Das Datenvolumen kann natürlich groß werden, wenn schlanke nicht-statische innere Serializable-Klassen in einer äußeren Serializable-Klassen liegen, die sehr viele Eigenschaften besitzt.
JAX-WS 2.1 with Spring under Java 6
First you need some jars in your classpath of an web application
- commons-logging.jar
- jaxw-api.jar
- jaxws-rt.jar
- jaxws-spring-1.1.jar
- saaj-api.jar
- saaj-impl.jar
- spring.jar
- stax-ex.jar
- streambuffer.jar
- xbean-spring-2.8.jar
The Jars are from Spring itself, http://geronimo.apache.org/xbean/, https://jax-ws.dev.java.net/ (jax-ws 2.1, JAXWS2.1_nightly.zip) and https://jax-ws-commons.dev.java.net/spring/ (jaxws-spring-1.1.jar). It is although important to place
- jaxb-api.jar
- jaxb-impl.jar
under C:\Programme\Apache Software Foundation\Tomcat 5.5\common\endorsed.
This was the necessary and boring preparation.
Next the Web Service itself
package com.tutego.service;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;@WebService
@SOAPBinding(style = SOAPBinding.Style.RPC)
public class GreeterService
{
@WebMethod
public String greet( String name )
{
return "Hello " + name + "!"
}
}
And web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>SpringWeb</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>jaxws-servlet</servlet-name>
<servlet-class>
com.sun.xml.ws.transport.http.servlet.WSSpringServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>jaxws-servlet</servlet-name>
<url-pattern>/greet</url-pattern>
</servlet-mapping>
</web-app>
The applicationContext.xml follows the suggestions with the namespace.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ws="http://jax-ws.dev.java.net/spring/core"
xmlns:wss="http://jax-ws.dev.java.net/spring/servlet"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://jax-ws.dev.java.net/spring/core http://jax-ws.dev.java.net/spring/core.xsd
http://jax-ws.dev.java.net/spring/servlet http://jax-ws.dev.java.net/spring/servlet.xsd">
<ws:service id="greeterService"
impl="com.tutego.service.GreeterService" />
<wss:bindings id="jax-ws.http">
<wss:bindings>
<wss:binding url="/greet" service="#greeterService" />
</wss:bindings>
</wss:bindings>
</beans>
Now you can consume your WS. If your Web-Context is SpringWeb use http://localhost:8080/SpringWeb/greet?wsdl. Enjoy it!
Spring in einer Web-Applikationen nutzen – so einfach ist das
Mit dem WTP ist es eine Sache von Minuten.
Lege ein Dynamic-Web-Projekt an. Nenne es etwa spring.
Aus dem Spring-all-in-one-glücklich.zip kopiere spring.jar und common-loggings.jar in das WEB-INF/lib.
Lege in WEB-INF eine Datei applicationContext.xml.
Setze in die Datei:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans><bean id="date" class="java.util.Date" />
</beans>
Setzte in WEB-INF/web.xml die Zeilen:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
</param-value>
</context-param><listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
Schreibe eine index.jsp
<%@page import="org.springframework.web.context.support.WebApplicationContextUtils"%>
<%@page import="org.springframework.context.ApplicationContext"%>
<%
ApplicationContext appContext = WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext());
%><%= appContext.getBean("date") %>
Das war’s. Unter http://localhost:8080/spring/ gibt’s dann das Datum.
Swing Application Framework und Swing Databinding — eine Aufzeichnung
Aktuelle Closure-Varianten (BGGA, CICE, FCM) im Vergleich
Zwar wird Java 7 höchst wahrscheinlich Closures bekommen, aber nicht jeder wird wissen, dass im Moment ganz unterschiedliche Varianten diskutiert werden:
– Gilad Bracha, Neal Gafter, James Gosling, Peter von der Ahé (BGGA)
– Bob Lee, Doug Lea, and Josh Bloch (CICE)
– Stefan Schulz (FCM)
Der Blog-Eintragt http://www.jroller.com/page/scolebourne?entry=java_7_comparing_closure_proposals vergleicht Szenarien mit den drei bisherigen Vorschlägen.
Find all hyperlinks in a text file
FileChannel fc = new FileInputStream( "c:/a.html" ).getChannel();
ByteBuffer byteBuf = fc.map( FileChannel.MapMode.READ_ONLY, 0, fc.size() );
CharBuffer charBuf = Charset.defaultCharset().newDecoder().decode( byteBuf );
Pattern pattern = Pattern.compile( "<a.*?href=[\"']([^\"]*?)[\"'].*?>", Pattern.CASE_INSENSITIVE );
Matcher m = pattern.matcher( charBuf );
while ( m.find() )
System.out.println( m.group( 1 ) );
fc.close();
Axis2/XFire Zoff. Der Gewinner: JAXWS 2.1?
Im Moment tobt der Kampf zwischen Axis2 und XFire um die Performance-Krone. Einige Benchmarks zeigen Axis2 vorne, doch das wohl nur, weil eigentlich XML-Bindings-Frameworks (JAXB bei XFire, ADB (Axis2 Data Binding) bei Asix2), also vergleichen werden, und nicht der Serialisierer selbst. Andere wiederum erfreuen sich über die Rechtschreibfehler in der Axis2-Doku bis zur Frustration:
- isOneHanlder
boolean isOneHanlder
this is want if the phaseFirst and phaseLst same hanlder that is for this phase there is only one phase - This send the SOAP Message to other SOAP nodes and this alone write the SOAP Message to the wire. Out flow must be end with one of this kind.
- cloneOMElement
public OMElement cloneOMElement()
Clones this element. Since both elements are build compleletely, you will lose the differed building capability.
Returns:
Returns OMElement.
Im Moment sieht gar nicht so schlecht für die Referenzimplementierung aus, insbesondere seit der neuen Version JAXWS 2.1 FCS. Die Performance-Ergebnisse sind ausgezeichnet und Spring-Support gibt’s auch. Was will man mehr?
Einiges mehr zur Debatte:
SOAP-Encodings — Eine kleine Übersicht
RPC-Style oder Document-Style
RPC-Syle (Remote Procedure Style)
Web-Services werden im Sinne von entfernten Methodenaufrufen genutzt.
Eine Web-Service-Methode kann Übergabeparameter und Rückgaben besitzen.
Die Übergabewerte müssen umkodiert werden. XML selbst zum Beispiel wird als umkodierter String übertragen.
Document-Style
Eine Web-Service-Methode hat nur ein Argument.
Das Argument geht als echtes XML-kodiertes Objekt auf den Weg und wird nicht umkodiert.
Da sich jedes beliebige XML-Dokument schicken lässt, ist das flexibler bei Anpassungen, denn Änderungen am WSDL für die Argumente sind nicht nötig.
SOAP-Encoding/Literal-Encoding
SOAP nutzt XML um Daten zu übertragen.
Im Fall von Methoden müssen Argumente und Rückgabewerte wie Zahlen, Strings aber auch Arrays der Datentypen in XML kodiert werden.
Zwei Kodierungen gibt es:
- Literal-Encoding. Literal Encoding nutzt ein XML Schema zum Validieren der SOAP-Daten.
- SOAP-Encoding, auch Section 5 Encoding genannt. Das 5. Kapitel der W3C-Spezifiaktion für SOAP schreibt vor, wie Argumente verpackt werden.
Mit den Varianten RPC- oder Document-Style zu versenden und Daten über SOAP-Encoding oder Literal zu kodieren gibt es theoretisch vier Möglichkeiten.
- RPC/SOAP-Encoding wird nach WS-I Basic Profile nicht empfohlen. (Kann XFire etwa auch nicht.)
- Document/SOAP ergibt keinen Sinn.
Document/Wrapped
Die Variante über Document/Literal, auch Document/Bare genannt, ist in der Praxis üblich. Sie bietet auch die beste Performance http://www-128.ibm.com/developerworks/webservices/library/ws-soapenc/.
Zwar nimmt Document/Literal nur exakt ein Argument, es lässt sich aber tricksen, in dem mehrere Argumente zu einem neuen komplexen Typ werden. Das nennt man Document/Wrapped. Damit ist auch addPerson(int id, String name) möglich.
Die Paramter id und name werden in einen eigenen Complex-Type gepackt.
LevelGZIPOutputStream — GZIPOutputStream mit Kompressionslevel
Der normale GZIPOutputStream nutzt einen Standardkompressionswert. Um diesen zu ändern, ruft man beim Deflator, der eigentlich hinter der Kompresssion steckt, setLevel() auf, um den Kompressionslevel setzen. Die folgende Unterklasse regelt das für uns:
import java.io.IOException;
import java.io.OutputStream;
import java.util.zip.GZIPOutputStream;
public class LevelGZIPOutputStream extends GZIPOutputStream
{
/**
* Creates a new output stream with a default buffer size and
* sets the current compression level to the specified value.
*
* @param out the output stream.
* @param level the new compression level (0-9).
* @exception IOException If an I/O error has occurred.
* @exception IllegalArgumentException if the compression level is invalid.
*/
public LevelGZIPOutputStream( OutputStream out, int compressionLevel )
throws IOException
{
super( out );
def.setLevel( compressionLevel );
}
}
XFire + JSR 181 Annotations + Jetty = Simple Web-Service
package xfire;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService( serviceName = "GreeterService" )
public class GreeterService
{
@WebMethod
public String greet( Person p )
{
return "Hello " + p.getName() + "!";
}
}
package xfire;
public class Person
{
private String name;
public Person()
{
}
public Person( String name )
{
this.name = name;
}
public String getName()
{
return name;
}
public void setName( String name )
{
this.name = name;
}
}
package xfire;
import org.codehaus.xfire.XFire;
import org.codehaus.xfire.XFireFactory;
import org.codehaus.xfire.annotations.AnnotationServiceFactory;
import org.codehaus.xfire.annotations.jsr181.Jsr181WebAnnotations;
import org.codehaus.xfire.server.http.XFireHttpServer;
import org.codehaus.xfire.service.Service;
public class ServiceServer
{
public static void main( String[] args ) throws Exception
{
XFire xfire = XFireFactory.newInstance().getXFire();
AnnotationServiceFactory factory = new AnnotationServiceFactory(
new Jsr181WebAnnotations(),
xfire.getTransportManager() );
Service service = factory.create( GreeterService.class );
xfire.getServiceRegistry().register( service );
new XFireHttpServer().start();
// http://localhost:8081/GreeterService?wsdl
}
}
package xfire;
import java.net.MalformedURLException;
import org.codehaus.xfire.client.XFireProxyFactory;
import org.codehaus.xfire.service.Service;
import org.codehaus.xfire.service.binding.ObjectServiceFactory;
public class ServiceClient
{
public static void main( String[] args ) throws MalformedURLException
{
ObjectServiceFactory serviceFactory = new ObjectServiceFactory();
Service serviceModel = serviceFactory.create( GreeterService.class );
GreeterService service = (GreeterService)
new XFireProxyFactory().create( serviceModel,
"http://localhost:8081/GreeterService" );
String s = service.greet( new Person( "Ulli" ) );
System.out.println( s );
}
}
Absonderliche Schreibweise bei einer Feld-Rückgabe
Da blättere ich gerade durch das „Just Java“ Buch und glaube, schon einen Fehler gefunden zu haben, da sagt mir der Compiler, dass alles in Ordnung ist:
public class T
{
public static int foo()[]
{
return new int[] { 1, 2, 3 };
}
public static void main( String[] args )
{
System.out.println( foo().length );
}
}
Diese sonderbare Rückgabe habe ich noch nie gesehen und ist mir in der Grammatik der Sprache Java auch noch nie aufgefallen.
Gerade noch in der Java EE, jetzt schon in der Java SE
Was früher noch Teil der J2EE war, ist heute Teil der Java Standard Edition.
- http://java.sun.com/j2ee/sdk_1.3/techdocs/api/ zeigt noch DOM und SAX, sowie das „JDBC 2.0 Optional Package“ was dann Teil der J2SE 1.4 wurde.
- http://java.sun.com/j2ee/1.4/docs/api/index.html zeigt javax.management „Java Management Extensions“ (JMX), und javax.xml.parsers, javax.xml.transform was fester Bestandteil von Java SE 5 wurde.
- http://java.sun.com/javaee/5/docs/api/ zeigt die JPA (Java Persistence API), was vermutlich Teil von Java 6 wird.
Viele Teile der Java Enterprise Edition werden so geläufig, dass sie in die Java Standard Edition wandern.
- Dennoch wurde es unter der Enterprise-Edition mehr: 78 Pakete in Java EE 5, 54 Pakete in J2EE 1.4, 32 in J2EE 1.3
@Service-EJBs bei JBoss — EJB 3.1 ruft
Bei JBoss ist eine Service-Bean eine besondere EJB, wovon es serverseitig nur ein Exemplar gibt.
Unterschiedliche Clients werden immer mit dem gleichen Exemplar arbeiten.
Es ist ein Singleton, ein nicht gepooltes Objekt.
Eine Service-Bean wird mit @org.jboss.annotation.ejb.Service annotiert.
@Service
public class VitalityCheckBean implements…
Über @Remote und/oder @Local wäre sich auch ganz normal von außen zugänglich.
Interessant sind Service-Bean, weil sie an einem MBean-Server angemeldet werden können und so über JMX zugänglich sind.
Dazu muss die EJB
mit @Service annotiert werden,
ein Management-Interface für die JMX-Operationen implementieren und
mit der Annotation @org.jboss.annotation.ejb.Management das Management-Interface benennen.
Das Management-Interface ist eine ganz normale Java-Schnittstelle und muss keiner Namenskonvention folgen.
Alle dort genannten Methoden sind über eine JMX-Konsole sichtbar.
interface MyManagementInterface
{
void doIt();
String getValue();
void setValue( String string );
}
import org.jboss.annotation.ejb.*;
@Service
@Management( MyManagementInterface.class )
public class SimpleServiceBean implements MyManagementInterface
{
private String string = „(default)“
public void doIt() {
System.out.println( „Ausgabe“ );
}
public void setValue( String string ) {
this.string = string;
}
public String getValue() {
return string;
}
}
In der JMX-Konsole unter http://localhost:8080/jmx-console/ suchen nach SimpleServiceBean mit ManagementInterface.
Der JMX-ObjectName lässt sich über das Attribut objectName der Annotation @Service ändern:
@Service(objectName=“javatutor:service=SimpleServiceBean“)
@Management(MyManagementInterface.class)
public class SimpleServiceBean implements …
Weiteres, auch zum Lebenszkylus unter
JBoss, JMX und JConsole
Mit JBoss und den proprietären Annotationen ist es einfach eine JMX zu schreiben. JBoss bringt ein Beispiel gleich mit:
package trail.jmx;
public interface Rechner {
// Attribute
public void setGrowthrate (double g);
public double getGrowthrate ();
// The management method
public double calculate (int start, int end, double saving);
// Life cycle method
public void create () throws Exception;
public void destroy () throws Exception;
}
package trail.jmx;
import java.lang.management.ManagementFactory;
import javax.annotation.PostConstruct;
import org.jboss.annotation.ejb.Management;
import org.jboss.annotation.ejb.Service;
@Service (objectName=“trail:service=calculator“)
@Management(Rechner.class)
public class RechnerMBean implements Rechner {
double growthrate;
public void setGrowthrate (double growthrate) {
this.growthrate = growthrate;
}
public double getGrowthrate () {
return growthrate;
}
public double calculate (int start, int end, double saving) {
double tmp = Math.pow(1. + growthrate / 12., 12. * (end – start) + 1);
return saving * 12. * (tmp – 1) / growthrate;
}
// Lifecycle methods
public void create() throws Exception {
growthrate = 0.08;
System.out.println(„Calculator – Creating“);
}
public void destroy() {
System.out.println(„Calculator – Destroying“);
}
}
In der JMX-Console taucht die Klasse dann auf.
Wenn man das ganze nun mit der JConsole hinbekommen möchte, hat man ein Problem, denn JBoss meldet die Beans nicht am Standard-Container für JMX Beans an, sondern an einem eigenen. Daher benötigt JBoss einen Hinweis, in den Sun-Container zu schreiben. Dazu ist ein Schalter beim Starten (run.bat oder in Eclipse bei der Startkonfiguration) mit anzugeben:
-Djboss.platform.mbeanserver -Djavax.management.builder.initial=org.jboss.system.server.jmx.MBeanServerBuilderImpl
Unter Java 5 muss natürlich noch -Dcom.sun.management.jmxremote dazu.
Jetzt ist der „Rechner“ auch in der JConsole.
Einige Gründe, warum man keinen Second Level Cache (etwa bei Hibernate) verwenden soll
- Greift Hibernate nicht allein auf die Datenquelle zu, sind die Daten im Cache unter Umständen nicht mehr aktuell.
- Wenn Daten einmal in den Cache gesetzt werden, danach aber nie wieder benötigt werden, war die Arbeit umsonst.
- Bei sehr vielen Daten quillt der Cache über und muss Dinge entfernen – nach Murphys Law sind die dabei, die wir als nächstes wieder lesen.
- Es sollen/müssen alle Anfragen an die Datenbank gehen, weil etwa jede Anfrage Logging-Informationen mitgespeichert. (Durch ein SELECT ist ein Trigger verbunden.)
- Wenn es nur eine Sitzung gibt, ist ein Second Level Cache unnötig. Er dient nur dazu, Daten zwischen mehreren Sitzungen „lebendig“ zu halten.
Java 2D unter 3D JOGL
Das Programm mit
zu starten ist ein MUSS!
Mehr zur Vorgehensweise, wie Java 2D mit JOGL auf Open GL kommt, gibt es unter http://weblogs.java.net/blog/campbell/archive/2007/01/java_2d_and_jog.html.
Jettison – JSON-Dokumente nach dem StAX-Modell schreiben
Viele JSON-Implementierungen nehmen ein direktes Mapping der Java-Objekte nach JSON vor. http://jettison.codehaus.org/ geht da einen anderen Weg. Mit den aus StAX bekannten Methoden zum Schreiben/Lesen von Elementen wird nicht in ein XML-Format „gemarshalled“, sondern in das JSON-Format. Ein Testfall für MappedXMLStreamWriterTest macht deutlich, was hier vor sich geht:
StringWriter strWriter = new StringWriter();
MappedNamespaceConvention con = new MappedNamespaceConvention();
AbstractXMLStreamWriter w = new MappedXMLStreamWriter(con, strWriter);
w.writeStartDocument();w.writeStartElement("root");
w.writeStartElement("child1");w.writeStartElement("subchild1");w.writeCharacters("test");w.writeEndElement();
w.writeStartElement("subchild2");w.writeCharacters("test");w.writeEndElement();
w.writeEndElement();
w.writeStartElement("child2");w.writeStartElement("subchild");w.writeCharacters("test");w.writeEndElement();w.writeEndElement();
w.writeEndElement();w.writeEndDocument();
w.close();strWriter.close();
System.out.println(strWriter.toString());
assertEquals("{\"root\":{" +"\"child1\":{\"subchild1\":\"test\",\"subchild2\":\"test\"}," +"\"child2\":{\"subchild\":\"test\"}}}",
strWriter.toString());
Ein Servlet/JSP würde statt in den StringWriter in den response Strom schreiben.
TaskExecutor und java.util.concurrent.Executor in Spring 2
Seit Java 5 gibt es mit dem Executor (JSR 166) eine Schnittstelle für „Ausführer“ von Runnable-Objekten.
Spring bietet mit dem TaskExecutor die gleiche Schnittstelle.
– So steht die Funktionalität auch für Java 1.4 und Java 1.3 und auch für Java EE Umgebungen zur Verfügung.
org.springframework.core.task.TaskExecutor:
void execute( Runnable task )
Die TaskExecutor im Überblick
SimpleThreadPoolTaskExecutor
– Thread-Pool durch Quartz’s SimpleThreadPool.
SimpleAsyncTaskExecutor
– Erzeugt pro Anfrage einen neuer Thread. Es gibt eine optionale maximale Größe.
SyncTaskExecutor
– Führt Runnable im aktuellen Thread aus. Erzeugt also keinen neuen Thread zur Nebenläufigkeit.
ConcurrentTaskExecutor
– Ein Wrapper zum java.util.concurrent.Executor von Java 5.
ThreadPoolTaskExecutor
– Geht direkt auf den java.util.concurrent.ThreadPoolExecutor von Java 5. Ermögicht Anpassung der Properties „corePoolSize“, „maxPoolSize“, „keepAliveSeconds“, „queueCapacity“.
TimerTaskExecutor
– Nutzt einen java.util.Timer zur Ausführung. Der Runnable wird als TimerTask hintereinander durch den Timer-Thread ausgeführt.
WorkManagerTaskExecutor
– Nutzt CommonJ WorkManager als Implementierung. Ermöglicht Ausführung auf Applikationsservern von BEA und IBM.
Beispiel für TaskExecutor
public class DoItExecutor
{
private TaskExecutor executor;
public DoItExecutor( TaskExecutor executor )
{
this.executor = executor;
}
public void doIt()
{
Runnable run = new Runnable() {
public void run() {
System.out.println( Thread.currentThread() );
}
};
executor.execute( run );
executor.execute( run );
}
}
Injizierung vom TaskExecutor
<bean id=“taskExecutor“ class=“org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor“>
<property name=“corePoolSize“ value=“5″ />
<property name=“maxPoolSize“ value=“10″ />
<property name=“queueCapacity“ value=“25″ />
</bean>
<bean id=“doItExecutor“ class=“DoItExecutor“>
<constructor-arg ref=“taskExecutor“ />
</bean>
„Fehlende“ Typen aus Java 5
Spring bietet unterschiedliche Implementierungen für den TaskExecutor, aber Java 5 bietet außer execute() im Executor noch mehr.
Der java.util.concurrent.ThreadPoolExecutor implementiert mehr als nur Executor, nämlich ExecutorService. Das bietet
– awaitTermination(), invokeAll(), invokeAny(), isShutdown(), isTerminated(), shutdown(), shutdownNow(), submit()
– mit weiteren Typen wie Future, Callable.
Spring bietet dafür bisher keine Abstraktion!
SimpleJdbcTemplate aus Spring 2.0
Das org.springframework.jdbc.core.JdbcTemplate compiliert unter Java 1.4 und nutzt keine Eigenschaften von Java 5 wie Generics, Autoboxing und Varags.
Seit Spring 2.0 gibt es mit org.springframework.jdbc.core.simple.SimpleJdbcTemplate eine neue Klasse mit eine überschaubaren Anzahl Methoden für Java 5.
– Es ist eine Java 5-Fassade vor dem JdbcTemplate.
Der Konstruktor von SimpleJdbcTemplate nimmt wie JdbcTemplate eine DataSource an.
Methoden vom SimpleJdbcTemplate
int queryForInt(String sql, Object… args)
long queryForLong(String sql, Object… args)
Erfragt ein int/long über einen SQL-String und Argumenten.
List<Map<String,Object>> queryForList(String sql, Object… args)
Map<String,Object> queryForMap(String sql, Object… args)
Führt die SQL-Anfrage mit optionalen Argumenten aus.
<T> T queryForObject(String sql, ParameterizedRowMapper<T> rm, Object… args)
Die SQL-Anfrage liefert ein Ergebnis, das der Mapper auf ein Objekt überträgt.
<T> T queryForObject(String sql, Class<T> requiredType, Object… args)
Führt eine SQL-Anfrage aus und überträgt die Eigenschaften auf ein Objekt.
<T> List<T> query(String sql, ParameterizedRowMapper<T> rm, Object… args)
Der ParameterizedRowMapper überträgt Ergebnisse auf Objekte.
int update(String sql, Object… args)
Führt ein SQL-Update mit optionalen Argumenten durch.
SimpleJdbcDaoSupport
Die DAO-Klassen von Spring erlauben Zugriff auf die Template-Objekte.
Während JdbcDaoSupport ein JdbcTemplate liefert, gibt SimpleJdbcDaoSupport ein SimpleJdbcTemplate.
SimpleJdbcDaoSupport ist eine Unterklasse von JdbcDaoSupport:
org.springframework.jdbc.core.support.JdbcDaoSupport
extended by org.springframework.jdbc.core.simple.SimpleJdbcDaoSupport