суббота, 9 февраля 2013 г.

JDBC. Получение подключения

Для JDBC, чтобы получить подключение используется два метода:
- DriverManager. Особенность этого класса в том, что с версии 4.0 он подгружает автоматически все драйвера, которые находятся в класспазе, после первого к нему обращения за конекшином. Конекшин он получает по урл.
- DataSource. Более сложный вариант. Но имеет ряд преимуществ. Чтобы он работал администратор должен задеплоить два вида датасорса в работающую систему. 1-й поставщика МРБД, второй поставщика ЕЕ сервера. Создается первый ДС и привязывается через JNDI в javax.naming.InitialContext, создается второй привязывает к себе первый и себя привязывает через JNDI тоже к javax.naming.InitialContext. Чтобы получить конекшин мы создаем обьект javax.naming.InitialContext и по JNDI второго ДС получаем его инстанцию, и теперь через гедКонекшин получаем конекшин указав юзернейм и пароль.



DriverManager

Его характерной особеностъю является то, что мы закрываем стейтмент, а не конекшин:
public Connection getConnection() throws SQLException {

    Connection conn = null;
    Properties connectionProps = new Properties();
    connectionProps.put("user", this.userName);
    connectionProps.put("password", this.password);

    if (this.dbms.equals("mysql")) {
        conn = DriverManager.getConnection(
                   "jdbc:" + this.dbms + "://" +
                   this.serverName +
                   ":" + this.portNumber + "/",
                   connectionProps);
    } else if (this.dbms.equals("derby")) {
        conn = DriverManager.getConnection(
                   "jdbc:" + this.dbms + ":" +
                   this.dbName +
                   ";create=true",
                   connectionProps);
    }
    System.out.println("Connected to database");
    return conn;
}

public static void viewTable(Connection con, String dbName)
    throws SQLException {

    Statement stmt = null;
    String query = "select COF_NAME, SUP_ID, PRICE, " +
                   "SALES, TOTAL " +
                   "from " + dbName + ".COFFEES";
    try {
        stmt = con.createStatement();
        ResultSet rs = stmt.executeQuery(query);
        while (rs.next()) {
            String coffeeName = rs.getString("COF_NAME");
            int supplierID = rs.getInt("SUP_ID");
            float price = rs.getFloat("PRICE");
            int sales = rs.getInt("SALES");
            int total = rs.getInt("TOTAL");
            System.out.println(coffeeName + "\t" + supplierID +
                               "\t" + price + "\t" + sales +
                               "\t" + total);
        }
    } catch (SQLException e ) {
        JDBCTutorialUtilities.printSQLException(e);
    } finally {
        if (stmt != null) { stmt.close(); }
    }
}
Начиная с JDK 7 мы можем упростить последний метод:
public static void viewTable(Connection con) throws SQLException {

    String query = "select COF_NAME, SUP_ID, PRICE, " +
                   "SALES, TOTAL " +
                   "from COFFEES";

    try (Statement stmt = con.createStatement()) {//LOOK HERE!

        ResultSet rs = stmt.executeQuery(query);

        while (rs.next()) {
            String coffeeName = rs.getString("COF_NAME");
            int supplierID = rs.getInt("SUP_ID");
            float price = rs.getFloat("PRICE");
            int sales = rs.getInt("SALES");
            int total = rs.getInt("TOTAL");
            System.out.println(coffeeName + ", " + supplierID +
                               ", " + price + ", " + sales +
                               ", " + total);
        }
    } catch (SQLException e) {
        JDBCTutorialUtilities.printSQLException(e);
    }//LOOK HERE!
}
Это благодаря The try-with-resources Statement

DataSource

Есть три вида ДС:
1) Обычный.
2) Пул.
3) Распределенный.

Второй позволяет не создавать каждый раз новый конекшин, а получать осовободившийся.
Третий обеспечивает комиты транзакции с несколько баз данных, который объединены как я понимаю репликацией. ДС-пул позволяет контролировать комиты, ролбеки и устанавливать автокомит=тру, распределенный это не позволяет за эти следит ДС сам.

Есть стандартизированные имена JNDI для каждого вида:

Обычный "jdbc/billingDB":
com.dbaccess.BasicDataSource ds = new com.dbaccess.BasicDataSource();
ds.setServerName("grinder");
ds.setDatabaseName("CUSTOMER_ACCOUNTS");
ds.setDescription("Customer accounts database for billing");

Context ctx = new InitialContext();
ctx.bind("jdbc/billingDB", ds);

...

Context ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup("jdbc/billingDB");
Connection con = ds.getConnection("fernanda","brewed");

ДС-пул "jdbc/pool/fastCoffeeDB":
com.dbaccess.ConnectionPoolDS cpds = new com.dbaccess.ConnectionPoolDS();
cpds.setServerName("creamer");
cpds.setDatabaseName("COFFEEBREAK");
cpds.setPortNumber(9040);
cpds.setDescription("Connection pooling for " + "COFFEEBREAK DBMS");

Context ctx = new InitialContext();
ctx.bind("jdbc/pool/fastCoffeeDB", cpds);

...

com.applogic.PooledDataSource ds = new com.applogic.PooledDataSource();
ds.setDescription("produces pooled connections to COFFEEBREAK");
ds.setDataSourceName("jdbc/pool/fastCoffeeDB");
Context ctx = new InitialContext();
ctx.bind("jdbc/fastCoffeeDB", ds);

...

ctx = new InitialContext();
ds = (DataSource)ctx.lookup("jdbc/fastCoffeeDB");
Connection con = ds.getConnection(username, password);

Транзакционный ДС "jdbc/pool/fastCoffeeDB":
com.dbaccess.XATransactionalDS xads = new com.dbaccess.XATransactionalDS();
xads.setServerName("creamer");
xads.setDatabaseName("COFFEEBREAK");
xads.setPortNumber(9040);
xads.setDescription("Distributed transactions for COFFEEBREAK DBMS");

Context ctx = new InitialContext();
ctx.bind("jdbc/xa/distCoffeeDB", xads);

...

com.applogic.TransactionalDS ds = new com.applogic.TransactionalDS();
ds.setDescription("Produces distributed transaction " +
                  "connections to COFFEEBREAK");
ds.setDataSourceName("jdbc/xa/distCoffeeDB");
Context ctx = new InitialContext();
ctx.bind("jdbc/distCoffeeDB", ds);

...

Context ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup("jdbc/distCoffeesDB");
Connection con = ds.getConnection();


В ДатаСорсе, что характерно закрывается не експрешин, а именно конекшин:
import java.sql.*;
import javax.sql.*;
import javax.ejb.*;
import javax.naming.*;

public class ConnectionPoolingBean implements SessionBean {

    // ...

    public void ejbCreate() throws CreateException {
        ctx = new InitialContext();
        ds = (DataSource)ctx.lookup("jdbc/fastCoffeeDB");
    }

    public void updatePrice(float price, String cofName,
                            String username, String password)
        throws SQLException{

        Connection con;
        PreparedStatement pstmt;
        try {
            con = ds.getConnection(username, password);
            con.setAutoCommit(false);//ПРИЗНАК ТОГО, ЧТО ЭТО ДС-пул
            pstmt = con.prepareStatement("UPDATE COFFEES " +
                        "SET PRICE = ? " +
                        "WHERE COF_NAME = ?");
            pstmt.setFloat(1, price);
            pstmt.setString(2, cofName);
            pstmt.executeUpdate();

            con.commit();//ПРИЗНАК ТОГО, ЧТО ЭТО ДС-пул
            pstmt.close();

        } finally {
            if (con != null) con.close();
        }
    }

    private DataSource ds = null;
    private Context ctx = null;
}

Комментариев нет:

Отправить комментарий