|
Comments
Did you read today's front page stories & breaking news?
SYS-CON.TV
|
General Java SQL Embedded in Java: Part 1 Starting Out
SQL Embedded in Java: Part 1 Starting Out
May. 1, 2000 12:00 AM
If you know SQL and Java, and you want to learn SQLJ, this series of articles is for you! I'm going to introduce SQLJ, the standard for embedding database SQL statements in Java programs. You may be familiar with JDBC, an API for talking SQL with the database. SQLJ takes many ideas from JDBC further by providing a language interface for SQL statements in Java. This allows programmers to concentrate on what to say, not how to say it. Take the following SQLJ statement (here aName is a Java variable of type String, and emp is a database table with a numeric column sal and a character column ename): #sql { UPDATE emp SET sal = sal * 1.1 WHERE ename = :aName }; If you're using JDBC, you'd have to write something along the following lines:
PreparedStatement st = Brevity isn't the only benefit of SQLJ. An equally important feature is that you can check SQL statements against the database at translate time rather than at runtime, when a particular SQL statement may or may not get executed. Last but not least, since the SQL text of SQLJ programs is known ahead of time, it permits database vendors to use all of their compile-time performance tricks - such as compilation into the database. You're probably thinking, however, that with all of these goodies there must be limitations. Actually, there's only one: SQLJ supports only static SQL statements. The names, shapes and types of SQL tables, views and procedures must be known and fixed ahead of time. The actual data sent to or received from the database is, of course, not fixed. In the example above the bind variable aName can take on any string value. Note that you couldn't use this variable to specify a table name, as in the following: #sql { UPDATE :aName SET sal = sal * 1.1 }; // BAD! Not a static SQL statement. So how can you write dynamic SQL programs if you have to? That's easy: just use JDBC. SQLJ actually provides nice interoperability features with JDBC. Now that I've lured you into reading about SQLJ, here are the topics I'll discuss in the remainder of the article:
Skeleton of an SQLJ Program import java.sql.SQLException; If something goes wrong while you're running your SQLJ program, your SQLJ statements and any methods in the SQLJ runtime API throw a SQLException. Either declare that your program throws an SQLException, or put try { ... } catch (SQLException exn) { ... } blocks in your program. What good is an SQL program without a database connection? (See the second sidebar for a summary of SQLJ syntax and usage.) Another important import line is the following: import sqlj.runtime.ref.DefaultContext; Before executing an SQLJ statement you had better connect to the database.
new oracle.jdbc.driver.OracleDriver(); The first line creates an instance of your JDBC driver and - as a desired side effect - registers that driver with the JDBC DriverManager. Of course, if you don't use an Oracle JDBC driver, you'd use a different class name here. The second statement sets the SQLJ default connection. Your username - equivalent to the database schema you're connecting to - is "scott" and your password "tiger." The first argument to the DefaultContext() constructor is the JDBC URL. If you want to connect to a different database and/or through a different JDBC driver, you need to adjust the URL accordingly. Refer to your JDBC driver documentation for specifics. The last argument is the auto-commit flag. For serious database work you want to turn auto-commit off. Only at the end of the day will you decide whether to commit or roll back your work. How do you do that? With #sql {COMMIT}; or #sql {ROLLBACK}; of course! It's also good style to close your connection context (by now it's rather obvious that's what we call connections in SQLJ) rather than leave the cleanup to your JVM's finalization. You can accomplish this with: DefaultContext.getDefaultContext().close(); Are you still with me? Now pull all the pieces together into a file HiScotty.sqlj (see Listing 1). Tip: Every SQLJ statement must be terminated with a semicolon ";" Excercises
Now you've got a file with a bunch of text in it - nothing to write home about. How do you bring this to life? One small step for you, one big leap for the translator: sqlj HiScotty.sqlj Yes, this translates your SQLJ source to a Java source and compiles it in the same fell swoop. This should - if everything goes okay - create some *.class files (and a *.ser file), and you can then issue: java HiScotty Even though you're familiar with .class files - the result of Java compilation - you'll be curious about these .ser files that the SQLJ translator produces. We also call them (serialized) profiles. They're serialized Java objects that contain all the information about the static SQL statements in your .sqlj source files, such as the SQL source text, the types and names of the host variables that occur in the SQL statement and what kind of SQL statement this is (a commit/rollback, a query, a DML statement and so on). Without a database the SQLJ translator can perform only offline checking of your SQL code. If you want to get your database involved, that is, if you want SQLJ to perform online checking, then you must tell the translator how to connect to it (see Figure 1). Specifically, you must supply a username (corresponding to the database schema you want to connect to) and a password: sqlj -user=scott/tiger HiScotty.sqlj Of course, you also want to be able to say which database you'd like to talk to and how - that is, using which driver and protocol. Because SQLJ uses JDBC underneath, this is accomplished by - yes, you guessed it! - a JDBC URL. Depending on the version of your SQLJ translator, this may already be set up (Oracle SQLJ, for example, uses "jdbc:oracle:oci8:@"), or you can provide it on the SQLJ command line with the -url= option. For example, you can use Oracle's thin (Type IV) JDBC driver as follows:
sqlj -user=scott/tiger
-url=jdbc:oracle:thin:@my_host:1521:my_oracle_sid HiScotty.sqlj
The -user and -url flags are two of the 46 or so option flags that SQLJ accepts. Issue sqlj -help to get an introduction to the most important ones. Tip: The translator will try to check your SQLJ programs against the database if, and only if, you specify the -user option. Excercises
Cooler Than Host Variables: Host Expressions
String aName = "SCOTT";
#sql { UPDATE emp SET sal = sal * :raise WHERE ename = :aName }; But SQLJ is more flexible than that - you can use Java expressions instead of host variables. Just make sure that the host expression is enclosed between ":(" and ")" (see Listing 2). Tip: All host expressions are evaluated once, and only once, from left to right (including side effects) before any values are sent to the database.
Look, Ma! Result Sets Are Typed...and Are Called "Iterators" SQLJ does not have the "amorphous" result sets of JDBC. SQLJ query results are always strongly typed - each column in the result has a particular Java type. To differentiate these "typed result sets" from the JDBC notion of ResultSet and from the SQL notion of cursor, we call them iterators. First, you declare an iterator type by specifying both the column types in Java and the column names. The names also serve as names of accessor functions, with which the column value is retrieved. How do you get your iterator with all of these names and types? You declare it, of course! #sql iterator Iter (String ename, Double sal); This line creates a Java class declaration for the Iter class - right where you wrote it. This class has next() and close() methods - just like the java.sql.ResultSet. Instead of the getXxxx(column_name) accessors, however, your Iter class sports two fully customized, tailor-made, individualized accessor methods known as String ename() and Double sal(). A minor detail: you'll have the most success with this declaration if you put it where Java class declarations are permitted. Let's declare ourselves an Iter. Iter n; And - better yet - populate it with the result from a query: #sql n = { SELECT ename, sal FROM emp }; How do you use this iterator? Whaddayaknow, I told you all about these methods you find in Iter.
while (n.next()) { Questions, questions! You should now have a gazillion questions about iterators, such as:
Tip: If you want to declare an iterator locally (as an inner class), I recommend that you declare it as follows. #sql public static iterator IteratorName( ... ); You must always close() your iterators once you are done using them, or you will run out of cursors with which to connect to the database. Exercises
SQLJ Resources
Reader Feedback: Page 1 of 1
Your Feedback Latest Cloud Developer Stories
Subscribe to the World's Most Powerful Newsletters
Subscribe to Our Rss Feeds & Get Your SYS-CON News Live!
|
SYS-CON Featured Whitepapers
Most Read This Week
Breaking Cloud Computing News
|
||||||||||||||||||||||||||||||||||||||||||||||||||||