Sqladria 2009 SRC

20
SQLJ for Developers Andrea Parrilli Oracle SQL Expert, Developer Mvn: thanks to Damjan Kumar

description

SQLAdria 2009 presentation's slides about our experience with Maven and SQLJ. It delves in some details about SQLJ and performance comparion between SQLJ and JDBC with prepared statements. It also shows surprising results for what concerns performances of (DB2) SQL PL procedures

Transcript of Sqladria 2009 SRC

Page 1: Sqladria 2009 SRC

SQLJ for DevelopersAndrea ParrilliOracle SQL Expert, Developer

Mvn: thanks to Damjan Kumar

Page 2: Sqladria 2009 SRC

22

Topics

• What is SQLJ;• Short SQLJ syntax introduction;• Equivalence between SQLJ and JDBC;• SQLJ on DB2 using Data Studio Developer, setup, binding, automatic building with maven;

• Performance comparison between SQLJ, unoptimized JDBC, JDBC with PreparedStatements;

• Performance comparison: SQL PL vs. Java

Page 3: Sqladria 2009 SRC

33

What is SQLJ

• SQLJ is an extension of Java language meant to used with a preprocessor to naturally embed SQL statements in Java code.

• It is specified by ISO/IEC in module SQL/OLB to support portability.

• The SQLJ preprocessor produces JDBC code with precompiled prepared statements.

Page 4: Sqladria 2009 SRC

44

What is a Preprocessor?

SQLJ#sql [ctx] {INSERT INTO MAPING.maplogVALUES (NEXTVAL FORMAPING.maplog_log_id_seq,CURRENT TIMESTAMP,0,:msg)};

Java

A preprocessor is just a kind of compiler (or rather a macro processor) devoted to translating the hosted languange, in an hybrid syntax code unit, into the host language.

Page 5: Sqladria 2009 SRC

55

The Generated Code

sqlj.runtime.ConnectionContext __sJT_connCtx = ctx; if (__sJT_connCtx == null) sqlj.runtime.error.RuntimeRefErrors.raise_NULL_CONN_CTX(); sqlj.runtime.ExecutionContext __sJT_execCtx = __sJT_connCtx.getExecutionContext(); if (__sJT_execCtx == null) sqlj.runtime.error.RuntimeRefErrors.raise_NULL_EXEC_CTX(); synchronized (__sJT_execCtx) { sqlj.runtime.profile.RTStatement __sJT_stmt = __sJT_execCtx.registerStatement(__sJT_connCtx,

MAPLOG_SJProfileKeys.getKey(0), 2); try { __sJT_stmt.setString(1, msg); __sJT_execCtx.executeUpdate(); } finally { __sJT_execCtx.releaseStatement(); } }

Page 6: Sqladria 2009 SRC

66

SQLJ Syntax• ITERATORS: an iterator represents a result set or a cursor, it supports

positional update/delete, inter-transaction persistence, scrollability and sensitivity attributes.

• DQL, DML & DDL: supports the full syntax of the underlying database manager.

• In the IBM implementation of SQLJ standard the statements are exclusively processed at compile time (the bind process), this means that the host language variables can appear only where a bind parameter in a prepared statement (JDBC or standard SQL’s procedural language extensions EXECUTE … USING) can, thus allowing only static SQL in SQLJ statements. On the contrary Oracle’s implementation allows for dynamic SQL in a very intuitive way but at the same time offers less features for what concerns iterators (this is mainly due to the differences between the two transaction models and the cursors implentations).

Page 7: Sqladria 2009 SRC

77

SQLJ Syntax Single row statements

#sql [context] :(hostVar) = {SELECT single_valueFROM somewhere…};#sql [context] {SELECT f1, f2, …INTO :(hostVar1), :(hostVar2), …FROM … };#sql [context] {DML/DDL with binds as allowed in EXECUTE … USING};

Page 8: Sqladria 2009 SRC

88

SQLJ Syntax Iterators

#sql [context] iterator <it_name> implements sqlj.runtime.ForUpdate,

sqlj.runtime.Scrollablewith(holdability=…

sensitivity=… updateColumns=“…”)

{<JavaDataType> <field_name>,…}

The standard defines datatypes mappings between Java and SQL:ex. INTEGER is mapped to BigDecimal, not to BigInteger!

Page 9: Sqladria 2009 SRC

99

Why Maven?

• Manages library dependencies;• Manages library download and installation;• Manages the build process:

• SQLJ translation of .sqlj files into .java;• Binding .ser files to the database;• Generation of artifacts (.jar, .war, …);

• Execution from command line (calling the main method with the right classpath);

• Maven is Open Source!

Once configured allows for a greater productivity shortening deploy and setup times and it fully integrates with the versioning system in use.

Page 10: Sqladria 2009 SRC

1010

How do we manage library dependencies

<dependency><groupId>com.ibm.db2</groupId><artifactId>db2jcc</artifactId><version>1.0</version>

</dependency><dependency><groupId>jdom</groupId><artifactId>jdom</artifactId><version>1.1</version>

</dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>2.5.6</version>

</dependency>

mvn install:install-file-Dfile=lib/db2jcc.jar-DgroupId=com.ibm.db2-DartifactId=db2jcc-Dversion=1.0-Dpackaging=jar-Dgeneratepom=true

Pom.xml Manual install

Not everything is in the standard repositories!

Page 11: Sqladria 2009 SRC

1111

Maven: SQLJ translation of .sqlj into .java

We use a custom maven plugin (sqlj-maven-plugin) for translation and binding of SQLJ files.

<build> <plugins> <plugin> <groupId>si.srcsi</groupId> <artifactId>sqlj-maven-plugin</artifactId> <version>1.2</version> <executions> <execution> <goals> <goal>sqljex</goal> <goal>sqljcustomize</goal> </goals> <configuration> <sqljDirs> <sqljDir>src/main/java</sqljDir> </sqljDirs> <generatedSourcesDirectory>src/main/java</generatedSourcesDirectory> <generatedResourcesDirectory>src/main/java</generatedResourcesDirectory> <classpath>lib/framework.jar</classpath> <dbUrl>${dbUrl}</dbUrl> <dbUser>${dbUser}</dbUser> <dbPassword>${dbPassword}</dbPassword> <dbCollection>${dbCollection}</dbCollection> </configuration> </execution> </executions> </plugin> </plugins></build>

Page 12: Sqladria 2009 SRC

1212

Maven: SQLJ translation the implementation

public class SqljExMojo extends AbstractSqljMojo{ private File[] sqljFiles; private File[] sqljDirs; public void execute() { ... Set sqljFiles = getSqljFiles(); for ( Iterator i=sqljFiles.iterator(); i.hasNext(); ){ File file = (File) i.next(); generate( file ); } Resource resource = new Resource(); resource.setDirectory( getGeneratedResourcesDirectory().getAbsolutePath() );

mavenProject.addResource( resource ); mavenProject.addCompileSourceRoot( getGeneratedSourcesDirectory().getAbsolutePath() );

}

Page 13: Sqladria 2009 SRC

1313

Maven:artifact generation

<modelVersion>4.0.0</modelVersion><groupId>si.srcsi</groupId><artifactId>diners-mapping-batch</

artifactId><packaging>jar</packaging><version>1.0-SNAPSHOT</version><name>diners-mapping-batch</name>

Page 14: Sqladria 2009 SRC

1414

Maven: execution

#!/bin/bashmvn exec:java-Dexec.mainClass= “si.src.diners.mapping.batch.IcusBatch" -Dexec.args="2 $1 $2 $3 $2"

Mvn takes care of classpath and environment variables

maven_screencast.avi

Page 15: Sqladria 2009 SRC

1515

Data Studio Developer

• IDE_SQLJsupport.avi• IDE_sqljassist.avi• IDE_SQLJ_errors.avi• IDE_debug.avi

Screencasts

Deleted from Presentation: too heavy

Page 16: Sqladria 2009 SRC

1616

Performance Test SQLJ – JDBC - PreparedStatement

•SQLJ: 16 ms / 102 ms ± 10 ms;•JDBC: 31 ms / 78 ms ± 10 ms;•JDBC with PreparedStatement:

•16 ms / 58 ms ± 15 ms;

Note: smaller is faster. First figures are on a small single valued query the latter are for a 1000 elements iterator

This is coherent with the implementation!

Page 17: Sqladria 2009 SRC

1717

The measureint iterations = 100;long sqljTime = 0;long jdbcTime = 0;long jdbcPreparedTime = 0;long start = 0;String str; //SQLJ#sql [ctx] { select str into :str from sirius.x_testsqlj where id = 3}; start = (new Date()).getTime();for(int i = 0; i < iterations; i++) {#sql [ctx] { select str into :str from sirius.x_testsqlj where id = :(i%6)};}sqljTime = (new Date()).getTime() - start;

start = (new Date()).getTime();Statement stmt = con.createStatement();for(int i = 0; i < iterations; i++) { ResultSet rs = stmt.executeQuery("select str from sirius.x_testsqlj where id = " + (i%6));

rs.next();tr = rs.getString(1);}

jdbcTime = (new Date()).getTime() - start; start = (new Date()).getTime();PreparedStatement ps = con.prepareStatement("select str from sirius.x_testsqlj where id = ?");

for(int i = 0; i < iterations; i++) { ps.setInt(1, i%6); ResultSet rs = ps.executeQuery(); rs.next(); str = rs.getString(1);}ps.close();jdbcPreparedTime = (new Date()).getTime() - start;

Page 18: Sqladria 2009 SRC

1818

Performance comparison: SQL PL vs. Java

for each row in the source: set savepoint; for each destination entity: check destination's business constraints; insert into destination table; if anything is wrong write to message

buffer; if there are warnings in the buffer then flush it to messages table and rollback to savepoint; else commit;

Page 19: Sqladria 2009 SRC

1919

Performance comparison: SQL PL vs. Java Surprise!

Over 10 executions of both implementations, run over a set of test data:

•Java + SQLJ: 8s ± 1s;•SQL PL: 15s ± 1.5s;•SQL PL without error logging: 10s ± 1s;

Page 20: Sqladria 2009 SRC

2020

Q&A