JDBC 4.0 and Oracle JDeveloper for J2EE Development
上QQ阅读APP看书,第一时间看更新

SQL: 2003 XML Data Type Support

The SQL: 2003 standard supports a new data type, XML, for storing XML documents. With the XML data type, an XML document can be stored in a database table column similar to the other data types. JDBC 4.0 supports the SQL: 2003 standard. The java.sql.SQLXML object is the Java mapping for the database type, XML. Prior to the SQLXML Java data type, an XML type column value could be retrieved only as a String or CLOB, which did not include the functionality to access different nodes in an XML document.

An XML type database column can be mapped to a Java data type with the help of SQLXML data type. In JDBC 4.0 specification, a java.sql.Connection object has the provision to create an SQLXML object that initially does not have any data. The data can be added with the setString() method or the setBinaryStream(), setCharacterStream(),and setResult() methods. An SQLXML object can be retrieved from a ResultSet or a CallableStatement by using the overloaded getSQLXML() method. The data in an SQLXML object can be retrieved by using the getString() method or the getBinaryStream(), getCharacterStream(), and getSource() methods. An SQLXML object can be stored in a database table column of type XML, which is similar to any other data type using the setSQLXML() method of the PreparedStatement interface.

SQL Server 2005 EXPRESS supports the XML data type whereas, SQL Server 2000 does not. IBM's DB2 UDB V 9 also supports the XML data type. To find out if a database supports the XML data type, obtain the database metadata from the Connection object:

DatabaseMetaData metadata= connection.getMetaData();

The data types are supported with the getTypeInfo() method, as shown below:

ResultSet rs=metadata.getTypeInfo();

Iterate over the data type result set and output the TYPE_NAME column, as shown below:

System.out.println("TYPE_NAME:"+rs.getString("TYPE_NAME"));

For SQL Server 2005 and IBM's DB2 UDB v9, the XML TYPE_NAME is output:

TYPE_NAME: XML 

In the following subsections, the procedures to create an XML document, store it in a database that supports the XML data type, and retrieve it from the database will be discussed.

Generating an XML Document

We will discuss the procedure to create and initialize an SQLXML object. Import the java.sql package, and the javax.xml.stream package:

import java.sql.*;
import javax.xml.stream.*;

The Java representation of an XML document in a database table is the SQLXML object. Create an SQLXML object from the Connection object with the createSQLXML() method, as shown below:

SQLXML sqlXML=connection.createSQLXML();

An SQLXML object can be initialized using one of the setString(), setBinaryStream(), setCharacterStream(), or setResult() methods. An SQLXML object can be initiated using the setResult() method and the StAXResult class. Create an XMLStreamWriter object from a StAXResult object, as shown below:

StAXResult staxResult = sqlXML.setResult(StAXResult.class);
XMLStreamWriter xmlStreamWriter = staxResult.getXMLStreamWriter();

The SQLXML object becomes non-writable after the setResult()method is invoked. Add the start of an XML document with the writeStartDocument(String,String) method, as shown below:

xmlStreamWriter.writeStartDocument("UTF-8","1.0");

The encoding and version of the XML document is specified in the writeStartDocument method. Add the start of an element with the writeStartElement(String localName) method, as shown below:

xmlStreamWriter.writeStartElement("catalog");

Add the element attributes by using the writeAttribute(String localName, String value) method. Add an element of text by using the writeCharacters(String text) method. Each start element would have a corresponding end element tag. Add an end element by using the writeEndElement() method. The writeEndElement() method does not specify the element name as the writeStartElement(String) method:

xmlStreamWriter.writeEndElement();

Add end of the document by using the writeEndDocument() method:

xmlStreamWriter.writeEndDocument();

A SQLXML object can also be initiated using the SAXResult class. Create a SAXResult object using the setResult() method of the SQLXML interface. Subsequently, obtain the ContentHandler result using the getHandler() method:

SAXResult saxResult = sqlXML.setResult(SAXResult.class);
ContentHandler contentHandler= saxResult.getHandler();

Specify the start of an XML document using the startDocument() method:

contentHandler.startDocument();

Specify the start of an element using the startElement(String uri,String localName,String qName,Attributes atts) method in which the parameter uri specifies the element namespace, parameter localName specifies the element local name, parameter qName specifies the element qualified name and parameter atts of type Attributes specifies the element attributes. An Attributes object can be created using the org.xml.sax.helpers.AttributesImpl class, which implements the Attributes interface. An attribute can be added to the AttributesImpl object using the addAttribute(String uri, String localName, String qName, String type, String value) method:

AttributesImpl.AttributesImpl() attrs=new AttributesImpl();
attrs.addAttribute("","","journal","StringType","OracleMagazine");
contentHandler.startElement("","","catalog",attrs);

The end of an element is specified with the endElement(String uri,String localName,String qName) method. Also specify the end of the document with the endDocument() method:

contentHandler.endElement("","","catalog");
contentHandler.endDocument();

An SQLXML object can also be initiated using the setCharacterStream() method. Create a Writer object from the SQLXML object using the setCharacterStream() method. Create a BufferedReader object from an input XML file. Read from the BufferedReader, and output to the Writer object:

Writer writer= sqlXML.setCharacterStream();
BufferedReader bufferedReader = new BufferedReader(new FileReader(new File("C:/catalog.xml")));
String line= null;
while((line = bufferedReader.readLine() != null) {
writer.write(line);
}

The SQLXML object becomes non-writable after the setCharacterStream() method is invoked. An XML document can also be added to an SQLXML object with the setString() method, as shown below:

sqlXML.setString("xmlString");

The SQLXML object becomes non-writable after invoking the setString() method. If the setString(), setBinaryStream(), setCharacterStream(), or setResult() method is invoked on an SQLXML object that has been previously initiated, a SQLException is generated. If any of the setBinaryStream(), setCharacterStream(), or setResult() methods are invoked more than once, a SQLException is generated, and the previously returned InputStream, Writer, or Result object is not effected.

Storing an XML Document

The SQLXML Java data type is stored in an XML document, just like any other Java data type. Create a database table with an XML type column. Run the SQL statement to create a database table, and obtain a Statement object from the Connection object, as shown below:

Statement stmt=connection.createStatement();

Create a database table, Catalog with an XML type column, as shown below:

stmt.executeUpdate("CREATE Table Catalog(CatalogId int, Catalog XML)");

Create a PreparedStatement object to add values to a database table, as shown in the following listing:

PreparedStatement statement=connection.prepareStatement("INSERT INTO CATALOG(catalogId, catalog) VALUES(?,?)");

Set the int value with the setInt() method and the SQLXML value with the setSQLXML() method, as shown below:

stmt.setInt(1, 1);
stmt.setSQLXML(2, sqlXML);

Update the database with the executeUpdate() method:

stmt.executeUpdate();

Retrieving an XML Document

An XML database data type row is retrieved as an SQLXML Java data type. Create a PreparedStatement for a SELECT query, as shown below:

PreparedStatement stmt=connection.prepareStatement("SELECT * FROM CATALOG WHERE catalogId=?");

Specify the catalogId value for which an XML document is to be retrieved:

stmt.setInt(1, 1);

Obtain a result set with the executeQuery() method:

ResultSet rs=stmt.executeQuery();

Obtain the SQLXML object for the catalog column of type XML, as shown below:

SQLXML sqlXML=rs.getSQLXML("Catalog");

Output the XML document in the SQLXML object by using the getString() method:

System.out.println(sqlXML.getString());

Accessing an XML Document Data

The XMLStreamReader interface can be used to read an XML document with an event iterator. An XMLStreamReader object is obtained from a SQLXML object, as shown below:

InputStream binaryStream = sqlXML.getBinaryStream();
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader xmlStreamReader = factory.createXMLStreamReader(binaryStream);

The SQLXML object becomes non-readable after calling the getBinaryStream() method. The next event is obtained by using the next() method, as shown below:

while(xmlStreamReader.hasNext())
{
int parseEvent=xmlStreamReader.next();
}

The next() method returns an int value that corresponds to an XMLStreamConstants constant, which represents an event type. Some of the return values of the next() method are listed in following table:

If the return value is ELEMENT, then the local name, prefix, and namespace can be obtained by using the getLocalName(), getPrefix(), and getNamespaceURI() methods, as shown below:

System.out.println("Element Local Name: "+xmlStreamReader.getLocalName());
System.out.println("Element Prefix: "+xmlStreamReader.getPrefix());
System.out.println("Element Namespace:"+xmlStreamReader.getNamespaceURI());

The attribute count in an element is obtained by using the getAttributeCount() method. Iterate over the attributes and obtain the attribute local name by using the getAttributeLocalName() method, the attribute value with the getAttributeValue() method, the attribute prefix with the getAttributePrefix() method, and the attribute namespace with the getAttributeNamespace() method:

for(int i=0; i<xmlStreamReader.getAttributeCount();i++){
System.out.println("Attribute Prefix:"+xmlStreamReader.getAttributePrefix(i));
System.out.println("Attribute Namespace:"+xmlStreamReader.getAttributeNamespace(i));
System.out.println("Attribute Local Name:"+xmlStreamReader.getAttributeLocalName(i));
System.out.println("Attribute Value:"+xmlStreamReader.getAttributeValue(i));
}