Servlet NewJavaServlet Test



Yüklə 11,16 Mb.
Pdf görüntüsü
səhifə91/97
tarix07.11.2018
ölçüsü11,16 Mb.
#78896
1   ...   87   88   89   90   91   92   93   94   ...   97

CHAPTER 12 

 DATABASES AND JYTHON: OBJECT RELATIONAL MAPPING AND USING JDBC 
 
242 
 
string-based query. Listing 12-14 shows how to use string concatenation for dynamically forming a 
query and also substituting variables. 
Listing 12-14. String Concatenation for Dynamic Query Formation 
# Assume that the user selected a pull-down menu choice determining 
# what results to retrieve from the database, either continent or country name. 
# The selected choice is stored in the selectedChoice variable.  Let's also assume 
# that we are interested in all continents or countries beginning with the letter "A" 
 
>>> qry = "select " + selectedChoice + " from country where " + selectedChoice + " like 
'A%'" 
>>> cursor.execute(qry) 
>>> while cursor.next(): 
...     print cursor.fetchone() 
... 
(u'Albania',) 
(u'American Samoa',) 
... 
This technique works very well for creating dynamic queries, but it also has its share of issues. For 
instance, reading through concatenated strings of code can become troublesome on the eyes. 
Maintaining such code is a tedious task. Above that, string concatenation is not the safest way to 
construct a query as it opens an application up for a SQL injection attack. SQL injection is a technique 
that is used to pass undesirable SQL code into an application in such a way that it alters a query to 
perform unwanted tasks. If the user has the ability to type free text into a textfield and have that text 
passed into a string concatenated query, it is best to perform some other means of filtering to ensure 
certain keywords or commenting symbols are not contained in the value. A better way of getting around 
these issues is to make use of prepared statements. 

 Note Ideally, never construct a query statement directly from user data. SQL injection attacks employ such 
construction as their attack vector. Even when not malicious, user data will often contain characters, such as 
quotation marks, that can cause the query to fail if not properly escaped. In all cases, it’s important to scrub and 
then escape the user data before it’s used in the query. 
One other consideration is that such queries will generally consume more resources unless the database 
statement cache is able to match it (if at all). 
But there are two important exceptions to our recommendation: 
SQL statement requirements: Bind variables cannot be used everywhere. However, specifics will depend 
on the database. 
Ad hoc or unrepresentative queries: In databases like Oracle, the statement cache will cache the execution 
plan, without taking in account lopsided distributions of values that are indexed, but are known to the 
database if presented literally. In those cases, a more efficient execution plan will result if the value is put in 
the statement directly. 
www.it-ebooks.info


CHAPTER 12 
■ 
DATABASES AND JYTHON: OBJECT RELATIONAL MAPPING AND USING JDBC 
 
243 
 
However, even in these exceptional cases, it's imperative that any user data is fully scrubbed. A good solution is to 
use some sort of mapping table, either an internal dictionary or a mapping table driven from the database itself. In 
certain cases, a carefully constructed regular expression may also work. Be careful. 
Prepared Statements 
To get around using the string concatenation technique for substituting variables, we can use a 
technique known as prepared statements. Prepared statements allow one to use bind variables for data 
substitution, and they are generally safer to use because most security considerations are taken care of 
without developer interaction. However, it is always a good idea to filter input to help reduce the risk. 
Prepared statements in zxJDBC work the same as they do in JDBC, just a simpler syntax. In Listing 12-15, 
we will perform a query on the country table using a prepared statement. Note that the question marks 
are used as place holders for the substituted variables. It is also important to note that the executemany() 
method is invoked when using a prepared statement. Any substitution variables being passed into the 
prepared statement must be in the form of a tuple or list. 
Listing 12-15. Using Prepared Statements 
# Passing a string value into the query 
qry = "select continent from country where name = ?" 
>>> cursor.executemany(qry,['Austria']) 
>>> cursor.fetchall() 
[(u'Europe',)] 
 
# Passing some variables into the query 
>>> continent1 = 'Asia' 
>>> continent2 = 'Africa' 
>>> qry = "select name from country where continent in (?,?)" 
>>> cursor.executemany(qry, [continent1, continent2]) 
>>> cursor.fetchall() 
[(u'Afghanistan',), (u'Algeria',), (u'Angola',), (u'United Arab Emirates',), (u'Armenia',), 
(u'Azerbaijan',), 
... 
Resource Management 
You should always close connections and cursors. This is not only good practice but absolutely essential 
in a managed container so as to avoid exhausting the corresponding connection pool, which needs the 
connections returned as soon as they are no longer in use. The with statement makes it easy. See Listing 
12-16. 
Listing 12-16. Managing Connections Using With Statements 
from __future__ import with_statement 
from itertools import islice 
from com.ziclix.python.sql import zxJDBC 
 
# externalize 
jdbc_url =  "jdbc:oracle:thin:@host:port:sid" 
www.it-ebooks.info


CHAPTER 12 

 DATABASES AND JYTHON: OBJECT RELATIONAL MAPPING AND USING JDBC 
 
244 
 
username = "world" 
password = "world" 
driver = "oracle.jdbc.driver.OracleDriver" 
 
with zxJDBC.connect(jdbc_url, username, password, driver) as conn: 
    with conn: 
        with conn.cursor() as c: 
            c.execute("select * from emp") 
            for row in islice(c, 20): 
                print row # let's redo this w/ namedtuple momentarily... 
 
The older alternative is available. It’s more verbose, and similar to the Java code that would 
normally have to be written to ensure that the resource is closed. See Listing 12-17. 
Listing 12-17. Managing Connections Avoiding the With Statement 
try: 
    conn = zxJDBC.connect(jdbc_url, username, password, driver) 
    cursor = conn.cursor() 
    #do something with the cursor 
# Be sure to clean up by closing the connection (and cursor) 
finally: 
    if cursor: 
        cursor.close() 
    if conn: 
        conn.close() 
Metadata 
As mentioned previously in this chapter, it is possible to obtain metadata information via the use of 
certain attributes that are available to both connection and cursor objects. zxJDBC matches these 
attributes to the properties that are found in the JDBC java.sql.DatabaseMetaData object. Therefore, 
when one of these attributes is called, the JDBC DatabaseMetaData object is actually obtaining the 
information. 
Listing 12-18 shows how to retrieve metadata about a connection, cursor, or even a specific query. 
Note that whenever obtaining metadata about a cursor, you must fetch the data after setting up the 
attributes. 
Listing 12-18. Retrieving Metadata About a Connection, Cursor or Specific Query 
# Obtain information about the connection using connection attributes 
>>> conn.dbname 
'PostgreSQL' 
>>> conn.dbversion 
'8.4.0' 
>>> conn.drivername 
'PostgreSQL Native Driver' 
# Check for existing cursors 
>>> conn.__cursors__ 
[

 
 
www.it-ebooks.info


Yüklə 11,16 Mb.

Dostları ilə paylaş:
1   ...   87   88   89   90   91   92   93   94   ...   97




Verilənlər bazası müəlliflik hüququ ilə müdafiə olunur ©www.genderi.org 2024
rəhbərliyinə müraciət

    Ana səhifə