org.ralasafe.util.DBUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.ralasafe.util.DBUtil.java

Source

/**
 * Copyright (c) 2004-2011 Wang Jinbao(Julian Wong), http://www.ralasafe.com
 * Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
 */
package org.ralasafe.util;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.ralasafe.RalasafeException;
import org.ralasafe.db.Column;
import org.ralasafe.db.DBPower;
import org.ralasafe.db.Table;

public class DBUtil {
    private static Log log = LogFactory.getLog(DBUtil.class);

    public static final String DB2 = "DB2";
    public static final String ORACLE = "ORACLE";
    public static final String MYSQL = "MYSQL";
    public static final String SQLSERVER = "SQL SERVER";
    public static final String OTHER_DATABASE = "OTHER";

    public static boolean supportsLimit(Connection conn) {
        String dataBase = getDatabaseProductName(conn);
        if (dataBase.equals(DB2) || dataBase.equals(ORACLE) || dataBase.equals(MYSQL)) {
            return true;
        } else {
            return false;
        }
    }

    public static void close(Connection conn) {
        if (conn != null) {
            try {
                if (!conn.isClosed()) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                conn = null;
            }
        }
    }

    public static void close(Statement stmt) {
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                stmt = null;
            }
        }
    }

    public static void close(ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                rs = null;
            }
        }
    }

    public static void close(Statement stmt, Connection conn) {
        close(stmt);
        close(conn);
    }

    public static void close(ResultSet rs, Statement stmt, Connection conn) {
        close(rs);
        close(stmt);
        close(conn);
    }

    public static String insertSql(String tableName, String[] columnNames) {
        StringBuffer buff = new StringBuffer();
        buff.append("INSERT INTO ");
        buff.append(tableName);
        buff.append(" (");
        StringUtil.append(buff, columnNames);
        buff.append(") VALUES(");
        StringUtil.append(buff, columnNames, false, "?", ",");
        buff.append(")");
        return buff.toString();
    }

    public static String selectSql(String tableName, String[] columnNames) {
        StringBuffer buff = new StringBuffer();
        buff.append("SELECT ");
        StringUtil.append(buff, columnNames);
        buff.append(" FROM ");
        buff.append(tableName);
        return buff.toString();
    }

    public static String selectSql(Table table) {
        String tableAlias = " t" + table.getId();
        StringBuffer buff = new StringBuffer();
        buff.append("SELECT ");
        buff.append(columnsString(table.getColumns(), tableAlias));
        buff.append(" FROM ");

        buff.append(table.getName() + tableAlias);
        return buff.toString();
    }

    private static StringBuffer columnsString(Column[] columns, String tableAlias) {
        StringBuffer buff = new StringBuffer();
        buff.append(columnString(columns[0], tableAlias));
        for (int i = 1; i < columns.length; i++) {
            buff.append(",").append(columnString(columns[i], tableAlias));
        }
        return buff;
    }

    private static String columnString(Column column, String tableAlias) {
        if (column.getFunction() == null || column.getFunction().equals(""))
            return tableAlias + "." + column.getName();
        else
            return column.getFunction() + "(" + tableAlias + "." + column.getName() + ")";
    }

    public static String updateSql(String tableName, String[] idColumnNames, String[] exceptIdColumnNames) {
        StringBuffer buff = new StringBuffer();
        buff.append("UPDATE ");
        buff.append(tableName);
        buff.append(" SET ");
        StringUtil.append(buff, exceptIdColumnNames, true, "=?", ",");
        buff.append(" WHERE ");
        StringUtil.append(buff, idColumnNames, true, "=?", " AND ");
        return buff.toString();
    }

    public static String deleteSql(String name, String[] idColumnNames) {
        StringBuffer buff = new StringBuffer();
        buff.append("DELETE FROM ");
        buff.append(name);
        buff.append(" WHERE ");
        StringUtil.append(buff, idColumnNames, true, "=?", " AND ");
        return buff.toString();
    }

    public static String createTableSql(String name, String[] columnNames, String[] columnSqlTypes) {
        StringBuffer buff = new StringBuffer();
        buff.append("CREATE TABLE ");
        buff.append(name.toLowerCase());
        buff.append("(");
        for (int i = 0; i < columnNames.length; i++) {
            if (i > 0) {
                buff.append(",");
            }
            buff.append(columnNames[i]);
            buff.append(" ");
            buff.append(columnSqlTypes[i]);
        }
        buff.append(")");
        return buff.toString();
    }

    public static void exec(Connection conn, String sql) throws SQLException {
        PreparedStatement pstmt = null;
        try {
            pstmt = conn.prepareStatement(sql);
            pstmt.execute();
        } finally {
            close(pstmt);
        }
    }

    public static int getMax(Table table, String columnName) throws SQLException {
        Connection conn = DBPower.getConnection(table.getId());
        Statement stmt = null;
        ResultSet rs = null;
        try {
            int max = 0;
            String sql = "select MAX( " + columnName + " ) from " + table.getName();
            stmt = conn.createStatement();
            rs = stmt.executeQuery(sql);
            if (rs.next()) {
                max = rs.getInt(1);
            } else {
                max = 0;
            }
            return max;
        } finally {
            DBUtil.close(rs, stmt, conn);
        }
    }

    // Sequence table name(save sequence value in table)
    private static final String RALASAFE_SEQUNCE = "ralasafe_sequence";

    /**
     * Get next value of certain column of table. For example: user table's id column.
     * 
     * @param table
     * @param columnName
     * @return
     * @throws SQLException
     */
    public static int getSequenceNextVal(Table table, String columnName) throws SQLException {
        Integer currentValue = readSequenceCurrentValFromDatabase(table, columnName);
        int nextValue = currentValue.intValue() + 1;
        synchronizeIntoDatabase(table, columnName, nextValue);

        return nextValue;
    }

    private static void synchronizeIntoDatabase(Table table, String columnName, int synValue) throws SQLException {
        Connection conn = null;
        PreparedStatement pstmt = null;
        try {
            conn = DBPower.getConnection(table.getId());

            pstmt = conn.prepareStatement("update " + RALASAFE_SEQUNCE + " set currentValue=? where name=?");
            String name = table.getName() + "_" + columnName;
            pstmt.setInt(1, synValue);
            pstmt.setString(2, name);
            pstmt.executeUpdate();
        } finally {
            DBUtil.close(pstmt, conn);
        }
    }

    private static Integer readSequenceCurrentValFromDatabase(Table table, String columnName) throws SQLException {
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            conn = DBPower.getConnection(table.getId());
            Integer currentValue = null;
            pstmt = conn.prepareStatement("select currentValue from " + RALASAFE_SEQUNCE + " where name=?");
            String name = table.getName() + "_" + columnName;
            pstmt.setString(1, name);
            rs = pstmt.executeQuery();
            if (rs.next()) {
                currentValue = new Integer(rs.getInt(1));
            }

            if (currentValue == null) {
                // there's no record in sequence table, then create a record
                int max = getMax(table, columnName);

                if (max < 0) {
                    max = 0;
                }

                DBUtil.exec(conn, "insert into " + RALASAFE_SEQUNCE + "(currentValue,name) values(" + max + ",'"
                        + name + "')");
                return new Integer(max);
            }

            return currentValue;
        } finally {
            DBUtil.close(rs, pstmt, conn);
        }
    }

    public static String roleTableCreateSql(String appName) {
        String sqlRole = " CREATE TABLE " + appName.toLowerCase()
                + "_role ( id integer NOT NULL,   name varchar(100) NOT NULL UNIQUE, "
                + "description varchar(500), PRIMARY KEY(id) ) ";
        return sqlRole;
    }

    public static String rolePrivilegeTableCreateSql(String appName) {
        String sqlRolePrivilege = " CREATE TABLE " + appName.toLowerCase()
                + "_roleprivilege (   roleid integer NOT NULL,   privilegeid integer NOT NULL, "
                + "PRIMARY KEY(roleid, privilegeid), FOREIGN KEY(roleid) REFERENCES " + appName
                + "_role (id), FOREIGN KEY(privilegeid) REFERENCES " + appName + "_privilege (id)) ";
        return sqlRolePrivilege;
    }

    public static String privilegeTableCreateSql(String appName) {
        String sqlPrivilege = " CREATE TABLE " + appName.toLowerCase()
                + "_privilege ( id integer NOT NULL, pid integer, "
                + "description varchar(500), name varchar(100) NOT NULL UNIQUE, "
                + "isLeaf integer, display integer, decisionPolicyCombAlg integer, "
                + "queryPolicyCombAlg integer, type integer, constantName varchar(40), "
                + "url varchar(100), target varchar(20), orderNum integer, PRIMARY KEY(id) ) ";
        return sqlPrivilege;
    }

    public static String userRoleTableCreateSql(String appName, String userTypeName, String idColumnName,
            String idColumnType) {
        String tableName = appName + "_" + userTypeName + "_userrole";
        String sqlUserRole = "CREATE TABLE " + tableName.toLowerCase() + " ( userid " + idColumnType
                + " NOT NULL, roleid integer NOT NULL, PRIMARY KEY(userid, roleid), "
                + "FOREIGN KEY(roleid) REFERENCES " + appName + "_role (id)) ";
        return sqlUserRole;
    }

    public static String roleTableDropSql(String appName) {
        String sqlRole = " DROP TABLE " + appName + "_role";
        return sqlRole;
    }

    public static String rolePrivilegeTableDropSql(String appName) {
        String sqlRolePrivilege = " DROP TABLE " + appName + "_roleprivilege";
        return sqlRolePrivilege;
    }

    public static String privilegeTableDropSql(String appName) {
        String sqlPrivilege = " DROP TABLE " + appName + "_privilege";
        return sqlPrivilege;
    }

    public static String userRoleTableDropSql(String appName, String userTypeName) {
        String tableName = appName + "_" + userTypeName + "_userrole";
        String sqlUserRole = "DROP TABLE " + tableName;
        return sqlUserRole;
    }

    public static String tableQueryCreateSql(String appName) {
        return "CREATE TABLE " + appName.toLowerCase()
                + "_query ( id int NOT NULL,name varchar(100) NOT NULL UNIQUE, " + "description varchar(500),"
                + "installDate date, " + "fileName varchar(40),pid int, isLeaf int," + "PRIMARY KEY(id) ) ";
    }

    public static String tableQueryDropSql(String appName) {
        return "DROP TABLE " + appName + "_query";
    }

    public static String tableUserCategoryCreateSql(String appName) {
        return "CREATE TABLE " + appName.toLowerCase()
                + "_usercategory ( id int NOT NULL, name varchar(100) NOT NULL UNIQUE, "
                + "description varchar(500), " + "installDate date, " + "fileName varchar(40),pid int, isLeaf int,"
                + "PRIMARY KEY(id) ) ";
    }

    public static String tableUserCategoryDropSql(String appName) {
        return "DROP TABLE " + appName + "_usercategory";
    }

    public static String tableDecisionEntitlementCreateSql(String appName) {
        return "create table " + appName.toLowerCase() + "_decision_entitlement(" + "id int NOT NULL,"
                + "privilegeId int," + "userCategoryId int," + "businessDataId int," + "effect varchar(100),"
                + "denyReason varchar(1000)," + "PRIMARY KEY(id) )";
    }

    public static String tableDecisionEntitlementDropSql(String appName) {
        return "DROP TABLE " + appName + "_decision_entitlement";
    }

    public static String tableQueryEntitlementCreateSql(String appName) {
        return "create table " + appName.toLowerCase() + "_query_entitlement(" + "id int NOT NULL,"
                + "privilegeId int," + "userCategoryId int," + "queryId int," + "description varchar(500),"
                + "PRIMARY KEY(id) )";
    }

    public static String tableQueryEntitlementDropSql(String appName) {
        return "DROP TABLE " + appName + "_query_entitlement";
    }

    public static String tableBusinessDataCreateSql(String appName) {
        return "CREATE TABLE " + appName.toLowerCase()
                + "_businessdata ( id int NOT NULL,name varchar(100) NOT NULL UNIQUE, "
                + "description varchar(500)," + "installDate date, "
                + "fileName varchar(40),pid int, isLeaf int,   " + "PRIMARY KEY(id) ) ";
    }

    public static String tableBusinessDataDropSql(String appName) {
        return "DROP TABLE " + appName + "_businessdata";
    }

    public static String tableBackUpCreateSql(String appName) {
        return "CREATE TABLE " + appName.toLowerCase() + "_backup ( id int NOT NULL,createTime timestamp, "
                + "description varchar(500),content blob," + "PRIMARY KEY(id) ) ";
    }

    public static String tableBackupDropSql(String appName) {
        return "DROP TABLE " + appName + "_backup";
    }

    public static String getLimitString(Connection conn, String sql, int first, int max) {
        String dataBase = getDatabaseProductName(conn);
        String result = sql;
        if (dataBase.equals(DB2)) {
            result = getDB2LimitString(sql, first, max);
        } else if (dataBase.equals(ORACLE)) {
            result = getOracleLimitString(sql, first, max);
        } else if (dataBase.equals(MYSQL)) {
            result = getMySQLLimitString(sql, first, max);
        }

        if (log.isDebugEnabled()) {
            log.debug("\n" + result);
        }

        return result;
    }

    private static String getMySQLLimitString(String sql, int first, int max) {
        return new StringBuffer(sql.length() + 20).append(sql).append(" limit " + first + ", " + max).toString();
    }

    private static String getOracleLimitString(String sql, int first, int max) {

        sql = sql.trim();
        boolean isForUpdate = false;
        if (sql.toLowerCase().endsWith(" for update")) {
            sql = sql.substring(0, sql.length() - 11);
            isForUpdate = true;
        }

        StringBuffer pagingSelect = new StringBuffer(sql.length() + 100);

        pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");

        pagingSelect.append(sql);

        // hibernate style
        // pagingSelect.append(" ) row_ ) where rownum_ <= " + (first + max)
        // + " and rownum_ > " + first);

        // better style
        pagingSelect.append(" ) row_ where rownum <= " + (first + max) + ") where " + " rownum_ >= " + (first + 1));

        if (isForUpdate) {
            pagingSelect.append(" for update");
        }

        return pagingSelect.toString();
    }

    private static String getDB2LimitString(String sql, int first, int max) {

        int startOfSelect = sql.toLowerCase().indexOf("select");

        StringBuffer pagingSelect = new StringBuffer(sql.length() + 100).append(sql.substring(0, startOfSelect)) // add the comment
                .append("select * from ( select ") // nest the main query in an
                // outer select
                .append(getRowNumber(sql)); // add the rownnumber bit into the
        // outer query select list

        if (hasDistinct(sql)) {
            pagingSelect.append(" row_.* from ( ") // add another (inner) nested
                    // select
                    .append(sql.substring(startOfSelect)) // add the main query
                    .append(" ) as row_"); // close off the inner nested select
        } else {
            pagingSelect.append(sql.substring(startOfSelect + 6)); // add the
            // main
            // query
        }

        pagingSelect.append(" ) as temp_ where rownumber_ ");

        // add the restriction to the outer select
        pagingSelect.append("between " + (first + 1) + " and " + (first + max));

        return pagingSelect.toString();
    }

    private static boolean hasDistinct(String sql) {
        return sql.toLowerCase().indexOf("select distinct") >= 0;
    }

    /**
     * Render the <tt>rownumber() over ( .... ) as rownumber_,</tt> bit, that
     * goes in the select list
     */
    private static String getRowNumber(String sql) {
        StringBuffer rownumber = new StringBuffer(50).append("rownumber() over(");

        int orderByIndex = sql.toLowerCase().indexOf("order by");

        if (orderByIndex > 0 && !hasDistinct(sql)) {
            rownumber.append(sql.substring(orderByIndex));
        }

        rownumber.append(") as rownumber_,");

        return rownumber.toString();
    }

    public static String getDatabaseProductName(Connection conn) {
        String dataBase;
        try {
            dataBase = conn.getMetaData().getDatabaseProductName();
            dataBase = dataBase.toUpperCase();
        } catch (SQLException e) {
            throw new RalasafeException(e);
        }

        if (dataBase.indexOf(DB2) >= 0) {
            return DB2;
        } else if (dataBase.indexOf(ORACLE) >= 0) {
            return ORACLE;
        } else if (dataBase.indexOf(MYSQL) >= 0) {
            return MYSQL;
        } else if (dataBase.indexOf(SQLSERVER) >= 0) {
            return SQLSERVER;
        } else {
            return OTHER_DATABASE;
        }
    }

    public static String getDefaultSchema(Connection conn) throws SQLException {
        String productName = getDatabaseProductName(conn);
        if (productName.equals(MYSQL) || productName.equals(SQLSERVER)) {
            return conn.getCatalog();
        } else {
            DatabaseMetaData metaData = conn.getMetaData();
            return metaData.getUserName();
        }
    }

    public static void setCommitMode(Connection conn, boolean autoCommit) {
        if (conn != null) {
            try {
                conn.setAutoCommit(autoCommit);
            } catch (SQLException e) {
            }
        }
    }

    public static void rollback(Connection conn) {
        if (conn != null) {
            try {
                conn.rollback();
            } catch (SQLException e) {
            }
        }
    }

}