Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 66 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
66
Dung lượng
1,87 MB
Nội dung
CHAPTER 17 ■ ACCESSING POSTGRESQL FROM JAVA 505 Table 17-1 lists the mapping of Java types to PostgreSQL data types and JDBC data types. The different JDBC types are defined in the class java.sql.Types. Working with Updatable Result Sets We can create updatable result sets from statements that specified the result set concurrency as CONCUR_UPDATEABLE. We can modify the data in updatable result sets, as well as add and remove rows. In this section, we will look at the methods available for modifying the state of result sets. Deleting Data The interface defines the following methods for deleting the current row and verifying the deletion: • public void deleteRow() throws SQLException: This method deletes the current row from the result set and from the database. This method cannot be called when the cursor is on INSERT row (a special row in a result set for adding data to the underlying database). • public boolean rowDeleted() throws SQLException: The rowDeleted method checks whether the current row has been deleted and returns True if it has been. Table 17-1. Data Type Cross Reference Java Type JDBC Type PostgreSQL Type java.lang.Boolean tinyint int2 java.lang.Byte tinyint int2 java.lang.Short smallint int2 java.lang.Integer integer int4 java.lang.Long bigint int8 java.lang.Float float float(7) java.lang.Double double float(8) java.lang.Character char char(1) java.lang.String varchar text java.sql.Date date date java.sql.Time time time java.sql.Timestamp timestamp timestamp java.lang.Object JAVA_OBJECT oid MatthewStones_4789C17.fm Page 505 Friday, March 4, 2005 6:45 PM 506 CHAPTER 17 ■ ACCESSING POSTGRESQL FROM JAVA Updating Data The result set interface defines a set of updateXXX methods for updating the data in the current row of the result set. However, these methods don’t in themselves update the underlying data in the database; the updateRow method must be called to actually change the data in the data- base. The following lists a few of the more commonly used updateXXX methods (for a complete listing, see the Java documentation), and then the methods for processing updates: • public void updateBoolean(int i, boolean x): Sets the data in the specified column to the specified boolean value. • public void updateBoolean(String col, boolean x): Sets the data in the specified column to the specified boolean value. • public void updateInt(int i, int x): Sets the data in the specified column to the specified int value. • public void updateInt(String col, int x): Sets the data in the specified column to the specified int value. • public void updateString(int i, String x): Sets the data in the specified column to the specified string value. • public void updateString(String col, String x): Sets the data in the specified column to the specified string value. • public void updateRow() throws SQLException: After updating the data in the result set, if you wish to write your change to the database, you must call the updateRow method. This method updates the underlying database with the data changed using the updateXXX methods. • public void refreshRow() throws SQLException: The refreshRow method refreshes the current row the most recent data from the database. • public void cancelRowUpdates() throws SQLException: This method cancels the updates made to the current row. • public boolean rowUpdated() throws SQLException: The rowUpdated method checks whether the current row held in the working data set (not the one stored in the database) has been updated and returns True if it has been. Inserting Data Result sets have a special row called the INSERT row for adding data to the underlying database. To move the cursor to the INSERT row, use the following method: public boolean moveToInsertRow() throws SQLException The cursor can then be returned to the previous row using this method: public boolean moveToCurrentRow() throws SQLException To actually insert the INSERT row into the database, use the following method: public boolean insertRow() throws SQLException MatthewStones_4789C17.fm Page 506 Friday, March 4, 2005 6:45 PM CHAPTER 17 ■ ACCESSING POSTGRESQL FROM JAVA 507 An instance of SQLException is thrown if the cursor is not on INSERT row (or if a database-access error occurs). Using Other Relevant Methods Two other relevant methods are available with the java.sql.ResultSet interface. This close method releases the database and JDBC resources: public void close() throws SQLException The getMetaData method gets the result set meta data as an instance of a class that imple- ments the java.sql.ResultSetMetaData interface: public ResultSetMetaData getMetaData() throws SQLException This interface defines a host of methods for accessing the result set meta data, including the following: • Catalog name • Column class name •Column count • Column display size •Column label •Column type • Column type name Refer to the Java documentation for a complete listing. Creating JDBC Statements The JDBC API defines three types of statements for sending SQL statements to the database: • Statements: Statements are generally used for sending SQL statements that don’t take any arguments. The methods required for Statement objects are defined by the java.sql.Statement interface. The JDBC driver provider supplies the implementation class for this interface. • Prepared Statements: Prepared statements are generally used for sending precompiled SQL statements that take IN arguments. The methods required for PreparedStatement objects are defined in the java.sql.PreparedStatement interface. This interface extends the java.sql.Statement interface. • Callable Statements: Callable statements are generally used for making calls to database stored procedures and can take both IN and OUT arguments. The methods required for CallableStatement objects are defined in the java.sql.CallableStatement interface. This interface extends the java.sql.PreparedStatement interface. MatthewStones_4789C17.fm Page 507 Friday, March 4, 2005 6:45 PM 508 CHAPTER 17 ■ ACCESSING POSTGRESQL FROM JAVA ■Note Callable statements are supported in versions of the PostgreSQL JDBC driver from 7.4 onwards. Using Statements The java.sql.Statement interface is normally used for sending SQL statements to the database that don’t have IN or OUT parameters. The JDBC driver vendor provides the implementation class for this interface. The common methods required by the different JDBC statements are defined in this interface. The methods defined by java.sql.Statement allow you to perform the following tasks: • Execute SQL statements • Query results and result sets • Handle SQL batches • Get and set query time out • Close the statement to release resources • Get and set escape processing • Get and clear SQL warnings • Get and set cursor names Here, we will cover the main tasks of executing statements, querying result sets, and handling SQL batches. See the Java documentation for information about the additional methods. Executing SQL Statements The java.sql.Statement interface defines methods for executing SQL statements such as SELECT, UPDATE, INSERT, DELETE, and CREATE. Use the executeQuery method to send a SELECT statement to the database and get back the result: public ResultSet executeQuery(String sql) throws SQLException Here is an example that simply returns a result set containing everything from the mytable table: try { Connection con = DriverManager.getConnection(url, prop); Statement stmt = con.createStatement(); ResultSet res = stmt.executeQuery("SELECT * FROM mytable"); } catch(SQLException e) { // Handle exception } MatthewStones_4789C17.fm Page 508 Friday, March 4, 2005 6:45 PM CHAPTER 17 ■ ACCESSING POSTGRESQL FROM JAVA 509 You can use the execute method to send a SQL statement to the database that may fetch multiple result sets (like a stored procedure): public boolean execute(String sql) throws SQLException This returns True if the next result is a ResultSet object. For SQL statements that don’t return result sets—like INSERT, UPDATE, and DELETE statements, as well as data definition language statements—use executeUpdate: public int executeUpdate(String sql) throws SQLException This returns the number of rows affected by the SQL statement. Querying Results and Result Sets The Statement interface defines various methods for retrieving information about the result of executing a SQL statement. Although executing a SQL statement can create several result sets, a Statement object can have only one result set open at a time. The getResultSet method returns the current result set associated with the Statement object: public ResultSet getResultSet() throws S.Exception This method returns NULL if there is no more of the result set available or the next result is an update count generated by executing an UPDATE, INSERT, or DELETE statement. The getUpdateCount method returns the update count for the last executed UPDATE, INSERT, or DELETE statement: public int getUpdateCount() throws SQLException This method returns -1 if there is no more update count available or the next result is a result set generated by executing a SELECT statement. The getMoreResults method gets the Statement object’s next result set: public boolean getMoreResults() throws SQLException This method returns False if there is no more of the result set available or the next result is an update count. Methods are also provided for performing the following get or set tasks: • The result set concurrency with which the statement was created • The result set fetch direction • The fetch size Handling SQL Batches The Statement interface also provides methods for sending a batch of SQL statements to the database: MatthewStones_4789C17.fm Page 509 Friday, March 4, 2005 6:45 PM 510 CHAPTER 17 ■ ACCESSING POSTGRESQL FROM JAVA • public void addBatch(String sql) throws SQLException: The addBatch method adds the specified SQL to the current batch. Generally, the SQL statements are INSERT, UPDATE, or DELETE. • public void clearBatch() throws SQLException: The clearBatch method clears the current batch. • public int[] executeBatch() throws SQLException: The executeBatch method executes the current batch. This method returns an array of updated counts. Writing a JDBC Client Using Statements It’s time to try out the key elements we have learned so far. To demonstrate the use of JDBC, we will write a JDBC client, called StatementClient.java, that will perform the following tasks: • Get a connection to the database. • Create a Statement object. • Insert two records into the customer table. • Select those records back from the database. • Delete those records. • Close the connection. Later, we will update this example to use prepared statements, which are generally more efficient. First, we must import the relevant classes: import java.sql.Connection; import java.sql.Statement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.DriverManager; Next, declare a main method: public class StatementClient { public static void main(String args[]) throws Exception { Load the driver, and connect to the database bpfinal on the server gw1: Class.forName("org.postgresql.Driver"); String url = "jdbc:postgresql://gw1/bpfinal"; Connection con = DriverManager.getConnection(url,"rick","password"); MatthewStones_4789C17.fm Page 510 Friday, March 4, 2005 6:45 PM CHAPTER 17 ■ ACCESSING POSTGRESQL FROM JAVA 511 Create a statement, and add two INSERT statements using a batch: Statement stmt = con.createStatement(); System.out.println("Inserting records"); stmt.addBatch("INSERT INTO customer(title,fname," + "lname,addressline,town,zipcode,phone) values " + "('Mr','Fred','Flintstone','31 Bramble Avenue'," + "'London','NT2 1AQ','023 9876')"); stmt.addBatch("INSERT INTO customer(title,fname," + "lname,addressline,town,zipcode,phone) values " + "('Mr','Barney','Rubble','22 Ramsons Avenue'," + "'London','PWD LS1','111 2313')"); Now execute the batch: stmt.executeBatch(); System.out.println("Records Inserted"); System.out.println(); Select records from the table: System.out.println("Selecting all records"); String selectSQL = "SELECT title, fname, lname, town" + "FROM customer"; ResultSet res = stmt.executeQuery(selectSQL); Retrieve the meta data for the result set, and use it to set the number of columns returned and display the column titles: ResultSetMetaData rsmd = res.getMetaData(); int colCount = rsmd.getColumnCount(); for(int i = 1; i <= colCount; i++) { System.out.print(rsmd.getColumnLabel(i) + "\t"); } System.out.println(); Loop through all the rows retrieved, displaying the data: while(res.next()) { for(int i = 1;i <= colCount; i++) { System.out.print(res.getString(i) + "\t"); } System.out.println(); } System.out.println(); MatthewStones_4789C17.fm Page 511 Friday, March 4, 2005 6:45 PM 512 CHAPTER 17 ■ ACCESSING POSTGRESQL FROM JAVA Delete the rows we just inserted, checking how many rows were deleted: System.out.println("Deleting records"); String deleteSQL = "DELETE FROM customer" + "WHERE (fname = 'Fred' AND lname = 'Flintstone')" + "OR (fname = 'Barney' AND lname = 'Rubble')"; System.out.println("Records deleted: " + stmt.executeUpdate(deleteSQL)); Finally, we must close the resources we have used: res.close(); stmt.close(); con.close(); } } Compile the class: $ javac StatementClient.java The output will be similar to the following, truncated for brevity: $ java StatementClient Inserting records Records Inserted Selecting all records title fname lname town Miss Jenny Stones Hightown Mr Andrew Stones Lowtown Miss Alex Matthew Nicetown Mr Adrian Matthew Yuleville Mr David Hudson Milltown Mr Fred Flintstone London Mr Barney Rubble London Deleting records Records deleted: 2 Using Prepared Statements Prepared statements are used for executing precompiled SQL statements, and they are modeled in the JDBC API using the java.sql.PreparedStatement interface. This interface extends the java.sql.Statement interface, and the JDBC driver vendor must provide the implementation class for this interface. Prepared statements are created using the Connection objects as we have already seen, but in addition, they can also be used for executing SQL statements with parameter placeholders for IN statements defined using the symbol ?. MatthewStones_4789C17.fm Page 512 Friday, March 4, 2005 6:45 PM CHAPTER 17 ■ ACCESSING POSTGRESQL FROM JAVA 513 Prepared statements are recommended for executing the same SQL statements more than once using different values for the IN parameters. This is because each time the database engine sees a SQL statement, it must parse it to determine its meaning, and also perform some processing to determine what it considers the most cost-efficient way of executing the state- ment. If the statement’s execution doesn’t involve much work, these preparatory steps can be a very significant part of the overall execution time of the command. Using a prepared state- ment allows the database to parse and generate an execution plan for the statement just once, which can significantly reduce the overhead. Executing Prepared SQL Statements The java.sql.PreparedStatement interface defines methods for executing SQL statements, such as SELECT, UPDATE, INSERT, DELETE, and CREATE. Unlike the corresponding methods defined in the Statement interface, these methods don’t take the SQL statements as arguments. The SQL statements are defined when the prepared statements are created using the Connection objects. Use the executeQuery method to execute the SELECT statement associated with the prepared statement and get back the result: public ResultSet executeQuery() throws SQLException Here is an example: try { String sql = "SELECT * FROM customer WHERE fname = ? "; Connection con = DriverManager.getConnection(url,prop); PreparedStatement stmt = con.prepareStatement(sql); stmt.setString(1, "Fred"); ResultSet res = stmt.executeQuery(); } catch(SQLException e) { // Handle exception } The execute method executes SQL statements that return results associated with prepared statements: public boolean execute() throws SQLException This returns True if the next result is a ResultSet object. The executeUpdate method executes SQL statements associated with prepared statements that don’t return result sets, such as INSERT and UPDATE: public int executeUpdate() throws SQLException This returns the number of rows affected by the SQL statement. Updating Data The prepared statement interface defines a set of setXXX methods for setting the values of the IN parameters for the precompiled SQL statements defined using the symbol ?. The parameter MatthewStones_4789C17.fm Page 513 Friday, March 4, 2005 6:45 PM 514 CHAPTER 17 ■ ACCESSING POSTGRESQL FROM JAVA indexes start from 1. The setXXX method used should be compatible with the expected SQL type. The following are a few of the more common methods (see the Java documentation for others): • public void setBoolean(int index, boolean x): Sets the IN parameter specified by the argument index to the boolean value specified by x. • public void setInt(int index, int x): Sets the IN parameter specified by the argument index to the int value specified by x. • public void setString(int index, string x): Sets the IN parameter specified by the argument index to the string value specified by x. The interface also defines a method for clearing the current values of all parameters immediately: public void clearParameters() throws SQLException Writing a JDBC Client Using Prepared Statements Now we will rewrite the previous StatementClient.java example using prepared statements and see how the same INSERT statement can be executed multiple times using different values. The key changes are highlighted: import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.DriverManager; public class PreparedStatementClient { public static void main(String args[]) throws Exception { // Load the JDBC driver and get a connection. // Create a prepared statement from the connection: Class.forName("org.postgresql.Driver"); String url = "jdbc:postgresql://gw1/bpfinal"; Connection con = DriverManager.getConnection(url,"rick","password"); PreparedStatement stmt; String insertSQL = "INSERT INTO customer(title,fname," + "lname,addressline,town,zipcode,phone) VALUES " + "(?,?,?,?,?,?,?)"; stmt = con.prepareStatement(insertSQL); System.out.println("Inserting records"); MatthewStones_4789C17.fm Page 514 Friday, March 4, 2005 6:45 PM [...]... the relational world of the SQL- based database In the next chapter, we will look at how to access PostgreSQL databases from C# MatthewStones_4789C18.fm Page 517 Friday, March 4, 2005 6:47 PM CHAPTER 18 ■■■ Accessing PostgreSQL from C# I n the previous chapter, we explained how to access PostgreSQL databases from Java In this chapter, we will look at how to access your PostgreSQL database from a similar... standard ODBC NET Data Provider method with Windows systems Then we will focus on using Npgsql Other alternatives for C# access to PostgreSQL are starting to appear, such as PgOleDb (http://gborg.postgresql.org/ project/oledb) and the Advanced Data Provider (http://advanced-ado.sourceforge.net/), but Npgsql has been around longer Also, as of PostgreSQL release 8.0, Npgsql is an optional part of the Windows... or a column name, dr["fname"] As you can see, once you connect to PostgreSQL using a standard ADO.NET data adapter, you access PostgreSQL in basically the same way as you access other relational databases from C# using Visual Studio Using Npgsql in Mono In this section, we will look at Npgsql (http://gborg.postgresql.org/project/npgsql) This is a solution primarily for users of Mono (http://www.mono-project.com),... PostgreSQL database MatthewStones_4789C18.fm Page 525 Friday, March 4, 2005 6:47 PM CHAPTER 18 ■ ACCESSING POSTGRESQL FROM C# Figure 18-1 Adding Npgsql to the project references in MonoDevelop Retrieving Data from the Database To retrieve data from the database, we need to use two additional Npgsql classes: the NpgsqlCommand class and the NpgsqlDataReader class We will start by looking at the NpgsqlCommand... using System; using Npgsql; public class connect { public static void Main(String[] args) { NpgsqlEventLog.Level = LogLevel.Debug; NpgsqlEventLog.LogName = "/tmp/Npgsqldebug.txt"; NpgsqlEventLog.EchoMessages = true; NpgsqlConnection conn = new NpgsqlConnection( "Server= 192 .168.0.3;User Id=rick;Password=password;Database=bpfinal;"); try { conn.Open(); NpgsqlCommand cmd = new NpgsqlCommand("SELECT * FROM... overhead PostgreSQL incurs each time it must parse and determine an execution plan from the SQL Just as we can with host variables in embedded C (discussed in Chapter 14) and with prepared statements in Java (discussed in Chapter 17), we can also generate SQL statements with parameters using Npgsql First, we need to look at the NpgsqlParameter class, which lets us create parameters Creating Parameters with. .. choose to use the Npgsql data adapter, which (currently) ships with Mono Npgsql provides a good range of data-access functions in a standard form You could choose to use Npgsql on Windows systems, but this choice is more likely if you need code compatibility between Windows and other operating systems This chapter ends our journey from PostgreSQL novice to PostgreSQL professional PostgreSQL has progressed... System.Data; using Microsoft.Data.Odbc; class PostgreSQL { static void Main(string[] args) { // First all details in one version // The string is split and concatenated to fit the book layout MatthewStones_4789C18.fm Page 5 19 Friday, March 4, 2005 6:47 PM CHAPTER 18 ■ ACCESSING POSTGRESQL FROM C# const string CONNECTION_STRING = "DRIVER={PostgreSQL};SERVER= 192 .168.0.3;" + "UID=rick;PWD=password;DATABASE=bpfinal";... references // vs-dataset.cs using System; using System.Data; using Microsoft.Data.Odbc; class PostgreSQL { static void Main(string[] args) { 5 19 MatthewStones_4789C18.fm Page 520 Friday, March 4, 2005 6:47 PM 520 CHAPTER 18 ■ ACCESSING POSTGRESQL FROM C# const string CONNECTION_STRING = "DRIVER={PostgreSQL};SERVER= 192 .168.0.3;" + "UID=rick;PWD=password;DATABASE=bpfinal"; OdbcConnection conn = new OdbcConnection();... NpgsqlParameter Class The NpgsqlParameter class is used to create parameter variables, which can be associated with a SQL statement in an NpgsqlCommand object It’s a relatively simple class; we really need to concern ourselves only with the parameter name and type, which are generally just passed in when the object is constructed Table 18 -9 lists the NpgsqlParameter properties MatthewStones_4789C18.fm . ■ CHAPTER 18 Accessing PostgreSQL from C# In the previous chapter, we explained how to access PostgreSQL databases from Java. In this chapter, we will look at how to access your PostgreSQL database from. database: MatthewStones_4789C17.fm Page 5 09 Friday, March 4, 2005 6:45 PM 510 CHAPTER 17 ■ ACCESSING POSTGRESQL FROM JAVA • public void addBatch(String sql) throws SQLException: The addBatch. ACCESSING POSTGRESQL FROM JAVA 505 Table 17-1 lists the mapping of Java types to PostgreSQL data types and JDBC data types. The different JDBC types are defined in the class java .sql. Types. Working with