设计模式拾荒之装饰器模式( Decorator Pattern): Oracle 数据库打印PreparedStatement

本文参考:
1. Overpower PreparedStatement
2. Bind variables - The key to application performance

此文作为本人23种设计模式学习笔记系列之一, 个人制定的对设计模式的学习方法是在实际项目中用一种模式, 写一篇笔记, 希望能够早日写完23中设计模式的笔记, 完成对所有设计模式的初步掌握

设计模式用前须知

  • 设计模式中一句出现频率非常高的话是,“ 在不改动。。。。的情况下, 实现。。。。的扩展“ 。
  • 对于设计模式的学习者来说,充分思考这句话其实非常重要, 因为这句往往只对框架/ 工具包的设计才有真正的意义。因为框架和工具包存在的意义,就是为了让其他的程序员予以利用, 进行功能的扩展,而这种功能的扩展必须以不需要改动框架和工具包中代码为前提
  • 对于应用程序的编写者, 从理论上来说, 所有的应用层级代码至少都是处于可编辑范围内的, 如果不细加考量, 就盲目使用较为复杂的设计模式, 反而会得不偿失, 毕竟灵活性的获得, 也是有代价的。

PrepareStatement 的好处

有一定java数据库开发经验的人都知道PreparedStatement 相对于Statement的优点 :

  • 因为预解析(Parse),编译(Compile)了SQL语句,计划(Plan)了SQL的数据获取路径, 所以通常来说PreparedStatement都会比Statement快, 至少不会比Statement慢
  • 防止了SQL 注入,因为它对可执行SQL和数据进行了分离 , 数据参数会被在SQL语句转化为执行计划以后, 另作单独的数据包传输过去,所以避免了拼接可能引发的SQL注入问题
  • 简化了设置非标准类型参数的方法,例如 Date,Time,Timestamp,BigDecimal,InputStream (Blob) , Reader (Clob)
    • 例如
preparedStatement = connection.prepareStatement("INSERT INTO Person (name,email,birthdate,photo) VALUES (?,?,?)");
preparedStatement.setString(1,person.getName());
preparedStatement.setString(2,person.getEmail());
preparedStatement.setTimestamp(3,new Timestamp(person.getBirthdate().getTime()));
preparedStatement.executeUpdate();

如何打印PrepareStatement

但是使用PreparedStatement 对于需要保留sql 语句执行记录的场景可能会遇到问题( 例如本人所在的公司交易系统应用对所有的sql 语句都会记log ), 如果想打印以上的PreparedStatement 真正被执行的sql 语句,获得了如下形式的内容

例如 INSERT INTO Person (name,birthdate) VALUES (John,john@hotmail.com,19660606)

则有可能遇到问题。 因为JDBC API 并没有定义专门用于获取PreparedStatement 执行语句内容的方法, 而PreparedStatemet.toString() 获得的结果取决于使用JDBC Driver,如果使用的是PostgreSQL 8.x and MySQL 5.x, 那直接在参数被set 后,调用 System.out.println(preparedStatement); 即可获得想要sql 语句内容。 如果是其他的JDBC Driver 例如 Oracle,执行该语句只会获得一串对象码。

所以问题情境是,当前开发的系统中,使用了PreparedStatement 的地方都没有办法打印带参数的sql 语句, 只能打印出带问号的部分, 在应用测试阶段不便于问题的排查, 所以需要一种最低侵入式, 改动范围最小的方法支持PreparedStatement 语句的打印 。

  • 可能的解决思路:
    • 继承 oracle jdbc 对 PreparedStatement实现类, 重写set 方法, 在set被调用时记录参数内容, 然后自行添加toString 方法, 拼接处整的sql 语句内容
      • 事实证明不可行, 因为ojdbc driver 的 PreparedStatement 的实现类的访问权限是包内权限, 所以无法继承。
    • 使用Log4jdbc 或 P6Spy 等来自StackOverFlow 推荐的日志工具
      • 缺点: 为了一个小需求给项目添加了新的依赖, 还需要一系列设置, 太麻烦。
    • 利用设计模式之装饰器模式(Decorator),实现一个DebuggableStatement接口, 以下列方式打印PreparedStatement
      • 缺点: 除需要向原有的项目中添加几个类以外, 几乎没有。
Connection con = DriverManager.getConnection(url);

// 当DebugLevel 为OFF时, StatementFactory.getStatement(con,sql,debug);返回的依旧是PreparedStatement 
DebugLevel debug = DebugLevel.ON;
String sql = "SELECT name,rate FROM EmployeeTable WHERE rate > ?";

//下面通过一个工厂类而不是Connection来获取PreparedStatement,//PreparedStatement ps = con.prepareStatement(sql);
  PreparedStatement ps = StatementFactory.getStatement(con,debug);
  ps.setInt(1,25);

//如果 ps 是一个实现了DebuggableStatement的对象,便可以打印出实际执行的sql语句
//otherwise,an object identifier is displayed
  System.out.println(" debuggable statement= " + ps.toString());
  • 优点:

    • 对原有业务部分的代码改动很小, 只需要修改一行获取PreparedStatement 的方式 。
    • 不需要添加额外的依赖库
    • 可以通过一个变量开关决定使用的PreparedStatement 类型, 方便随时关闭DebuggableStatement 的开销
  • 代码实现方式(代码来自参考文章一, 但是做了一些改动, 避免报错无法运行):

    • 需要向项目中新增以下类:
      • DebuggableStatement
      • StatementFactory
      • SqlFormatter
      • DefaultSqlFormatter
      • OracleSqlFormatter
      • DebugLevel
  • 代码说明:

    • DebuggableStatement 是这里的核心, 也是应用代理模式的地方
      • 需要注意的是PreparedStatement 是一个接口, 由数据库提供商的Driver 提供商提供实现, 所以这里DebuggableStatement要实现PreparedStatement 接口, 需要实现一大堆方法, 很显然,这个让我们自己实现几乎不可行, 所以这里便是应用装饰器模式的绝佳场景 。 下面抽取DebuggableStatement 的部分代码进行说明。
class DebuggableStatement implements PreparedStatement{

    private PreparedStatement ps;       //preparedStatement being proxied for.
    private String sql;                 //original statement going to database.
    private String filteredSql;         //statement filtered for rogue '?' that are not bind variables.
    private DebugObject[] variables;    //array of bind variables
    private SqlFormatter formatter;     //format for dates
    private long startTime;             //time that statement began execution
    private long executeTime;           //time elapsed while executing statement
    private DebugLevel debugLevel;      //level of debug

    ....

    @Override
    public boolean getMoreResults(int current) throws SQLException {
        return ps.getMoreResults();
    ....
    }

注意到DebuggableStatement第一个成员对象ps 是PreparedStatement , 而我们实现PreparedStatement 的方法内容都无须自行编写, 都是直接调用ps对象的对应方法。 而ps 对象的获取是在如下的构造方法中, 通过connection 获取。

protected DebuggableStatement(Connection con,String sqlStatement,SqlFormatter formatter,DebugLevel debugLevel) throws SQLException{
        //set values for member variables
        if (con == null)
            throw new SQLException("Connection object is null");
        this.ps = con.prepareStatement(sqlStatement); //被代理对象的获取
        this.sql = sqlStatement;
        this.debugLevel = debugLevel;
        this.formatter = formatter;

至此, DebuggableStatement 的实现方式就已经完全清晰了, 至于sql 的拼接就是在每一个set 中将具体的参数值保存在一个数组中, 最后toString 的时候, 填充即可

  • SqlFormatter
  • OracleSqlFormatter

这两个类只是为了实现sql 语句中, 对于日期(Date)等非基本类型的参数打印的格式化实现而已,非常简单。

完整的代码

  • DebuggableStatement
class DebuggableStatement implements PreparedStatement{

    private PreparedStatement ps;       //preparedStatement being proxied for.
    private String sql;                 //original statement going to database.
    private String filteredSql;         //statement filtered for rogue '?' that are not bind variables.
    private DebugObject[] variables;    //array of bind variables
    private SqlFormatter formatter;     //format for dates
    private long startTime;             //time that statement began execution
    private long executeTime;           //time elapsed while executing statement
    private DebugLevel debugLevel;      //level of debug

    /** Construct new DebugableStatement. Uses the SqlFormatter to format date,time,timestamp outputs  @param con Connection to be used to construct PreparedStatement  @param sqlStatement sql statement to be sent to database.  @param debugLevel DebugLevel can be ON,OFF,VERBOSE. */
    protected DebuggableStatement(Connection con,DebugLevel debugLevel) throws SQLException{
        //set values for member variables
        if (con == null)
            throw new SQLException("Connection object is null");
        this.ps = con.prepareStatement(sqlStatement);
        this.sql = sqlStatement;
        this.debugLevel = debugLevel;
        this.formatter = formatter;

        //see if there are any '?' in the statement that are not bind variables
        //and filter them out.
        boolean isString = false;
        char[] sqlString = sqlStatement.toCharArray();
        for (int i = 0; i < sqlString.length; i++){
            if (sqlString[i] == '\'')  // 为了判断要替换的问号是否是否在单引号内部
                isString = !isString;
            //substitute the ? with an unprintable character if the ? is in a
            //string.
            if (sqlString[i] == '?' && isString) // 单引号中的问号不能替换
                sqlString[i] = '\u0007';
        }
        filteredSql = new String(sqlString);

        //find out how many variables are present in statement.
        int count = 0;
        int index = -1;
        while ((index = filteredSql.indexOf("?",index+1)) != -1){
            count++;
        }

        //show how many bind variables found
        if (debugLevel == DebugLevel.VERBOSE)
            System.out.println("count= " + count);

        //create array for bind variables
        variables = new DebugObject[count];

    }

    /** * Facade for PreparedStatement */
    public void addBatch() throws SQLException{
        ps.addBatch();
    }

    /** * Facade for PreparedStatement */
    public void addBatch(String sql) throws SQLException{
        ps.addBatch();
    }

    /** * Facade for PreparedStatement */
    public void cancel() throws SQLException{
        ps.cancel();
    }

    /** * Facade for PreparedStatement */
    public void clearBatch() throws SQLException{
        ps.clearBatch();
    }

    /** * Facade for PreparedStatement */
    public void clearParameters() throws SQLException{
        ps.clearParameters();
    }

    /** * Facade for PreparedStatement */
    public void clearWarnings() throws SQLException{
        ps.clearWarnings();
    }

    /** * Facade for PreparedStatement */
    public void close() throws SQLException{
        ps.close();
    }

    /** * Executes query and Calculates query execution time if DebugLevel = VERBOSE * @return results of query */
    public boolean execute() throws SQLException{
        //execute query
        Boolean results = null;
        try{
            results = (Boolean)executeVerboseQuery("execute",null);
        }catch(Exception e){
           throw new SQLException("Could not execute sql command - Original message: " + e.getMessage());
        }
        return results.booleanValue();
    }

    /** * This method is only here for convenience. If a different sql string is executed * than was passed into Debuggable,unknown results will occur. * Executes query and Calculates query execution time if DebugLevel = VERBOSE * @param sql should be same string that was passed into Debuggable * @return results of query */
    public boolean execute(String sql) throws SQLException{
        //execute query
        Boolean results = null;
        try{
            results = (Boolean)executeVerboseQuery("execute",new Class[]{sql.getClass()});
        }catch(Exception e){
            throw new SQLException("Could not execute sql command - Original message: " + e.getMessage());
        }
        return results.booleanValue();
    }

    /** * Executes query and Calculates query execution time if DebugLevel = VERBOSE * @return results of query */
    public int[] executeBatch() throws SQLException{
        //execute query
        int[] results = null;
        try{
            results = (int[])executeVerboseQuery("executeBatch",null);
        }catch(Exception e){
            throw new SQLException("Could not execute sql command - Original message: " + e.getMessage());
        }
        return results;
    }

    /** * Executes query and Calculates query execution time if DebugLevel = VERBOSE * @return results of query */
    public ResultSet executeQuery() throws SQLException{
        //execute query
        ResultSet results = null;
        try{
// results = (ResultSet)executeVerboseQuery("executeQuery",null);
            results  = ps.executeQuery();
        }catch(Exception e){
            throw new SQLException("Could not execute sql command - Original message: " + e.getMessage());
        }
        return results;
    }

    /** * This method is only here for convenience. If a different sql string is executed * than was passed into Debuggable,unknown results will occur. * Executes query and Calculates query execution time if DebugLevel = VERBOSE * @param sql should be same string that was passed into Debuggable * @return results of query */
    public ResultSet executeQuery(String sql) throws SQLException{
        //execute query
        ResultSet results = null;
        try{
            results = (ResultSet)executeVerboseQuery("executeQuery",new Class[]{sql.getClass()});
        }catch(Exception e){
            throw new SQLException("Could not execute sql command - Original message: " + e.getMessage());
        }
        return results;
    }

    /** * Executes query and Calculates query execution time if DebugLevel = VERBOSE * @return results of query */
    public int executeUpdate() throws SQLException{
        //execute query
        Integer results = null;
        try{
            results = (Integer)executeVerboseQuery("executeUpdate",null);
        }catch(Exception e){
            throw new SQLException("Could not execute sql command - Original message: " + e.getMessage());
        }
        return results.intValue();
    }

    /** * This method is only here for convenience. If a different sql string is executed * than was passed into Debuggable,unknown results will occur. * Executes query and Calculates query execution time if DebugLevel = VERBOSE * @param sql should be same string that was passed into Debuggable * @return results of query */
    public int executeUpdate(String sql) throws SQLException{
        //execute query
        Integer results = null;
        try{
            results = (Integer)executeVerboseQuery("executeUpdate",new Class[]{sql.getClass()});
        }catch(Exception e){
            throw new SQLException("Could not execute sql command - Original message: " + e.getMessage());
        }
        return results.intValue();
    }

    /** * Facade for PreparedStatement */
    public Connection getConnection() throws SQLException{
        return ps.getConnection();
    }

    @Override
    public boolean getMoreResults(int current) throws SQLException {
        return ps.getMoreResults();
    }

    @Override
    public ResultSet getGeneratedKeys() throws SQLException {
        return ps.getGeneratedKeys();

    }

    @Override
    public int executeUpdate(String sql,int autoGeneratedKeys) throws SQLException {
        return ps.executeUpdate(sql,autoGeneratedKeys);
    }

    @Override
    public int executeUpdate(String sql,int[] columnIndexes) throws SQLException {
        return ps.executeUpdate(sql,columnIndexes);
    }

    @Override
    public int executeUpdate(String sql,String[] columnNames) throws SQLException {
        return ps.executeUpdate( sql,columnNames);
    }

    @Override
    public boolean execute(String sql,int autoGeneratedKeys) throws SQLException {
        return ps.execute(sql,autoGeneratedKeys);
    }

    @Override
    public boolean execute(String sql,int[] columnIndexes) throws SQLException {
        return ps.execute(sql,columnIndexes);
    }

    @Override
    public boolean execute(String sql,String[] columnNames) throws SQLException {
        return ps.execute(sql,columnNames);
    }

    @Override
    public int getResultSetHoldability() throws SQLException {
        return ps.getResultSetHoldability();
    }

    @Override
    public boolean isClosed() throws SQLException {
        return ps.isClosed();
    }

    @Override
    public void setPoolable(boolean poolable) throws SQLException {
        ps.setPoolable(poolable);
    }

    @Override
    public boolean isPoolable() throws SQLException {
        return ps.isPoolable();
    }

    @Override
    public void closeOnCompletion() throws SQLException {
        ps.closeOnCompletion();
    }

    @Override
    public boolean isCloseOnCompletion() throws SQLException {
        return ps.isCloseOnCompletion();
    }

    /** * Facade for PreparedStatement */
    public int getFetchDirection() throws SQLException{
        return ps.getFetchDirection();
    }

    /** * Facade for PreparedStatement */
    public int getFetchSize() throws SQLException{
        return ps.getFetchSize();
    }

    /** * Facade for PreparedStatement */
    public int getMaxFieldSize() throws SQLException{
        return ps.getMaxFieldSize();
    }

    /** * Facade for PreparedStatement */
    public int getMaxRows() throws SQLException{
        return ps.getMaxRows();
    }

    /** * Facade for PreparedStatement */
    public ResultSetMetaData getMetaData() throws SQLException{
        return ps.getMetaData();
    }

    /** * Facade for PreparedStatement */
    public boolean getMoreResults() throws SQLException{
        return ps.getMoreResults();
    }

    /** * Facade for PreparedStatement */
    public int getQueryTimeout() throws SQLException{
        return ps.getQueryTimeout();
    }

    /** * Facade for PreparedStatement */
    public ResultSet getResultSet() throws SQLException{
        return ps.getResultSet();
    }

    /** * Facade for PreparedStatement */
    public int getResultSetConcurrency() throws SQLException{
        return ps.getResultSetConcurrency();
    }

    /** * Facade for PreparedStatement */
    public int getResultSetType() throws SQLException{
        return ps.getResultSetType();
    }

    /** * Facade for PreparedStatement */
    public String getStatement(){
        return sql;
    }

    /** * Facade for PreparedStatement */
    public int getUpdateCount() throws SQLException{
        return ps.getUpdateCount();
    }

    /** * Facade for PreparedStatement */
    public SQLWarning getWarnings() throws SQLException{
        return ps.getWarnings();
    }

    /** * Tests Object o for parameterIndex (which parameter is being set) and places * object in array of variables. * @param parameterIndex which PreparedStatement parameter is being set. * Sequence begins at 1. * @param o Object being stored as parameter * @exception throw if index exceeds number of variables. */
    private void saveObject(int parameterIndex,Object o)throws ParameterIndexOutOfBoundsException {
        if(parameterIndex > variables.length)
            throw new ParameterIndexOutOfBoundsException("Parameter index of " +
            parameterIndex + " exceeds actual parameter count of " + variables.length);

        variables[parameterIndex-1] = new DebugObject(o);
    }

    /** Adds name of the Array's internal class type(by using x.getBaseTypeName()) to the debug String. If x is null,NULL is added to debug String.  @param i index of parameter  @param x parameter Object */
    public void setArray(int i,java.sql.Array x) throws SQLException{
        saveObject(i,x);
        ps.setArray(i,x);
    }

    /** Debug string prints NULL if InputStream is null,or adds "stream length = " + length */
    public void setAsciiStream(int parameterIndex,InputStream x,int length) throws SQLException{
        saveObject(parameterIndex,(x==null?"NULL":"<stream length= " + length+">"));
        ps.setAsciiStream(parameterIndex,x,length);
    }

    /** Adds BigDecimal to debug string in parameterIndex position.  @param parameterIndex index of parameter  @param x parameter Object */
    public void setBigDecimal(int parameterIndex,BigDecimal x) throws SQLException{
        saveObject(parameterIndex,x);
        ps.setBigDecimal(parameterIndex,or adds "stream length= " + length.  @param parameterIndex index of parameter  @param x parameter Object  @param length length of InputStream */
    public void setBinaryStream(int parameterIndex,(x==null?"NULL":"<stream length= " + length+">"));
        ps.setBinaryStream(parameterIndex,length);
    }

    /** Adds name of the object's class type(Blob) to the debug String. If object is null,NULL is added to debug String.  @param parameterIndex index of parameter  @param x parameter Object */
    public void setBlob(int parameterIndex,Blob x) throws SQLException{
        saveObject(parameterIndex,x);
        ps.setBlob(parameterIndex,x);
    }

    /** Adds boolean to debug string in parameterIndex position.  @param parameterIndex index of parameter  @param x parameter Object */
    public void setBoolean(int parameterIndex,boolean x) throws SQLException{
        saveObject(parameterIndex,new Boolean(x));
        ps.setBoolean(parameterIndex,x);
    }

    /** Adds byte to debug string in parameterIndex position.  @param parameterIndex index of parameter  @param x parameter Object */
    public void setByte(int parameterIndex,byte x) throws SQLException{
        saveObject(parameterIndex,new Byte(x));
        ps.setByte(parameterIndex,x);
    }

    /** Adds byte[] to debug string in parameterIndex position.  @param parameterIndex index of parameter  @param x parameter Object */
    public void setBytes(int parameterIndex,byte[] x) throws SQLException{
        saveObject(parameterIndex,(x==null?"NULL":"byte[] length="+x.length));
        ps.setBytes(parameterIndex,x);
    }

    /** Debug string prints NULL if reader is null,or adds "stream length= " + length.  @param parameterIndex index of parameter  @param reader parameter Object  @param length length of InputStream */
    public void setCharacterStream(int parameterIndex,Reader reader,(reader==null?"NULL":"<stream length= " + length+">"));
        ps.setCharacterStream(parameterIndex,reader,length);
    }

    /** Adds name of the object's class type(Clob) to the debug String. If object is null,NULL is added to debug String.  @param i index of parameter  @param x parameter Object */
    public void setClob(int i,Clob x) throws SQLException{
        saveObject(i,x);
        ps.setClob(i,x);
    }

    public void setCursorName(String name) throws SQLException{
        ps.setCursorName(name);
    }

    /** Debug string displays date in YYYY-MM-DD HH24:MI:SS.# format.  @param parameterIndex index of parameter  @param x parameter Object */
    public void setDate(int parameterIndex,java.sql.Date x) throws SQLException{
        saveObject(parameterIndex,x);
        ps.setDate(parameterIndex,x);
    }

    /** this implementation assumes that the Date has the date,and the calendar has the local info. For the debug string,the cal date is set to the date of x. Debug string displays date in YYYY-MM-DD HH24:MI:SS.# format.  @param parameterIndex index of parameter  @param x parameter Object  @param cal uses x to set time */
    public void setDate(int parameterIndex,java.sql.Date x,Calendar cal) throws SQLException{
        cal.setTime(new java.util.Date(x.getTime()));
        saveObject(parameterIndex,cal);
        ps.setDate(parameterIndex,cal);
    }

    /** Adds double to debug string in parameterIndex position.  @param parameterIndex index of parameter  @param x parameter Object */
    public void setDouble(int parameterIndex,double x) throws SQLException{
        saveObject(parameterIndex,new Double(x));
        ps.setDouble(parameterIndex,x);
    }

    /** * Facade for PreparedStatement */
    public void setEscapeProcessing(boolean enable) throws SQLException{
        ps.setEscapeProcessing(enable);
    }

    /** * Facade for PreparedStatement */
    public void setFormatter(SqlFormatter formatter){
        this.formatter = formatter;
    }

    /** * Facade for PreparedStatement */
    public void setFetchDirection(int direction) throws SQLException{
        ps.setFetchDirection(direction);
    }

    /** * Facade for PreparedStatement */
    public void setFetchSize(int rows) throws SQLException{
        ps.setFetchSize(rows);
    }

    /** Adds float to debug string in parameterIndex position.  @param parameterIndex index of parameter  @param x parameter Object */
    public void setFloat(int parameterIndex,float x) throws SQLException{
        saveObject(parameterIndex,new Float(x));
        ps.setFloat(parameterIndex,x);
    }

    /** Adds int to debug string in parameterIndex position.  @param parameterIndex index of parameter  @param x parameter Object */
    public void setInt(int parameterIndex,int x) throws SQLException{
        saveObject(parameterIndex,new Integer(x));
        ps.setInt(parameterIndex,x);
    }

    /** Adds long to debug string in parameterIndex position.  @param parameterIndex index of parameter  @param x parameter Object */
    public void setLong(int parameterIndex,long x) throws SQLException{
        saveObject(parameterIndex,new Long(x));
        ps.setLong(parameterIndex,x);
    }

    /** * Facade for PreparedStatement */
    public void setMaxFieldSize(int max) throws SQLException{
        ps.setMaxFieldSize(max);
    }

    /** * Facade for PreparedStatement */
    public void setMaxRows(int max) throws SQLException{
        ps.setMaxRows(max);
    }

    /** Adds a NULL to the debug String.  @param parameterIndex index of parameter  @param sqlType parameter Object */
    public void setNull(int parameterIndex,int sqlType) throws SQLException{
        saveObject(parameterIndex,"NULL");
        ps.setNull(parameterIndex,sqlType);
    }

    /** Adds a NULL to the debug String.  @param parameterIndex index of parameter  @param sqlType parameter Object  @param typeName type of Object */
    public void setNull(int parameterIndex,int sqlType,String typeName) throws SQLException{
        saveObject(parameterIndex,sqlType,typeName);
    }

    @Override
    public void setURL(int parameterIndex,URL x) throws SQLException {
        ps.setURL(parameterIndex,x);
    }

    @Override
    public ParameterMetaData getParameterMetaData() throws SQLException {
        return ps.getParameterMetaData();
    }

    @Override
    public void setRowId(int parameterIndex,RowId x) throws SQLException {
        ps.setRowId(parameterIndex,x);
    }

    @Override
    public void setNString(int parameterIndex,String value) throws SQLException {
        ps.setNString(parameterIndex,value);
    }

    @Override
    public void setNCharacterStream(int parameterIndex,Reader value,long length) throws SQLException {
        ps.setNCharacterStream(parameterIndex,value,length);
    }

    @Override
    public void setNClob(int parameterIndex,NClob value) throws SQLException {
        ps.setNClob(parameterIndex,value);
    }

    @Override
    public void setClob(int parameterIndex,long length) throws SQLException {
        ps.setClob(parameterIndex,length);
    }

    @Override
    public void setBlob(int parameterIndex,InputStream inputStream,long length) throws SQLException {
        ps.setBlob(parameterIndex,inputStream,long length) throws SQLException {
        ps.setNClob(parameterIndex,length);
    }

    @Override
    public void setSQLXML(int parameterIndex,SQLXML xmlObject) throws SQLException {
        ps.setSQLXML(parameterIndex,xmlObject);
    }

    /** Adds name of the object's class type to the debug String. If object is null,NULL is added to debug String.  @param parameterIndex index of parameter  @param x parameter Object */
    public void setObject(int parameterIndex,Object x) throws SQLException{
        saveObject(parameterIndex,(x==null?"NULL":x.getClass().getName()));
        ps.setObject(parameterIndex,x);
    }

   /** Adds name of the object's class type to the debug String. If object is null,NULL is added to debug String.  @param parameterIndex index of parameter  @param x parameter Object  @param targetSqlType database type */
    public void setObject(int parameterIndex,Object x,int targetSqlType) throws SQLException{
        saveObject(parameterIndex,targetSqlType);
    }

    /** Adds name of the object's class type to the debug String. If object is null,NULL is added to debug String.  @param parameterIndex index of parameter  @param x parameter Object  @param targetSqlType database type  @param scale see PreparedStatement */
    public void setObject(int parameterIndex,int targetSqlType,int scale) throws SQLException{
        saveObject(parameterIndex,targetSqlType,scale);
    }

    @Override
    public void setAsciiStream(int parameterIndex,long length) throws SQLException {
        ps.setAsciiStream(parameterIndex,length);
    }

    @Override
    public void setBinaryStream(int parameterIndex,long length) throws SQLException {
        ps.setBinaryStream(parameterIndex,length);
    }

    @Override
    public void setCharacterStream(int parameterIndex,long length) throws SQLException {
        ps.setCharacterStream(parameterIndex,length);
    }

    @Override
    public void setAsciiStream(int parameterIndex,InputStream x) throws SQLException {
        ps.setAsciiStream(parameterIndex,x);
    }

    @Override
    public void setBinaryStream(int parameterIndex,InputStream x) throws SQLException {
        ps.setBinaryStream(parameterIndex,x);
    }

    @Override
    public void setCharacterStream(int parameterIndex,Reader reader) throws SQLException {
        ps.setCharacterStream(parameterIndex,reader);
    }

    @Override
    public void setNCharacterStream(int parameterIndex,Reader value) throws SQLException {
        ps.setNCharacterStream(parameterIndex,Reader reader) throws SQLException {
        ps.setClob(parameterIndex,reader);
    }

    @Override
    public void setBlob(int parameterIndex,InputStream inputStream) throws SQLException {
        ps.setBlob(parameterIndex,inputStream);
    }

    @Override
    public void setNClob(int parameterIndex,Reader reader) throws SQLException {
        ps.setNClob(parameterIndex,reader);
    }

    /** * Facade for PreparedStatement */
    public void setQueryTimeout(int seconds) throws SQLException{
        ps.setQueryTimeout(seconds);
    }

    /** From the javadocs: A reference to an SQL structured type value in the database. A Ref can be saved to persistent storage. The output from this method call in DebuggableStatement is a string representation of the Ref object by calling the Ref object's getBaseTypeName() method. Again,this will only be a String representation of the actual object being stored in the database.  @param i index of parameter  @param x parameter Object */

    public void setRef(int i,Ref x) throws SQLException{
        saveObject(i,x);
        ps.setRef(i,x);
    }

    /** Adds short to debug string in parameterIndex position.  @param parameterIndex index of parameter  @param x parameter Object */
    public void setShort(int parameterIndex,short x) throws SQLException{
        saveObject(parameterIndex,new Short(x));
        ps.setShort(parameterIndex,x);
    }

    /** Adds String to debug string in parameterIndex position. If String is null "NULL" is inserted in debug string. ****note**** In situations where a single ' is in the string being inserted in the database. The debug string will need to be modified to reflect this when running the debug statement in the database.  @param parameterIndex index of parameter  @param x parameter Object */
    public void setString(int parameterIndex,String x) throws SQLException{
        saveObject(parameterIndex,x);
        ps.setString(parameterIndex,x);
    }

    /** Debug string displays Time in HH24:MI:SS.# format.  @param parameterIndex index of parameter  @param x parameter Object */
    public void setTime(int parameterIndex,Time x) throws SQLException{
        saveObject(parameterIndex,x);
        ps.setTime(parameterIndex,x);
    }

   /** This implementation assumes that the Time object has the time and Calendar has the locale info. For the debug string,the cal time is set to the value of x. Debug string displays time in HH24:MI:SS.# format.  @param parameterIndex index of parameter  @param x parameter Object  @param cal sets time based on x */
    public void setTime(int parameterIndex,Time x,cal);
        ps.setTime(parameterIndex,cal);
    }

    /** Debug string displays timestamp in YYYY-MM-DD HH24:MI:SS.# format.  @param parameterIndex index of parameter  @param x parameter Object */
    public void setTimestamp(int parameterIndex,Timestamp x) throws SQLException{
        saveObject(parameterIndex,x);
        ps.setTimestamp(parameterIndex,x);
    }

    /** This implementation assumes that the Timestamp has the date/time and Calendar has the locale info. For the debug string,the cal date/time is set to the default value of Timestamp which is YYYY-MM-DD HH24:MI:SS.#. Debug string displays timestamp in DateFormat.LONG format.  @param parameterIndex index of parameter  @param x parameter Object  @param cal sets time based on x */
    public void setTimestamp(int parameterIndex,Timestamp x,cal);
        ps.setTimestamp(parameterIndex,cal);
    }

    /** Method has been deprecated in PreparedStatement interface. This method is present only to satisfy interface and does not do anything. Do not use...  @deprecated */
    public void setUnicodeStream(int parameterIndex,int length) throws SQLException{
        //ps.setUnicodeStream(parameterIndex,length);
    }

    /** this toString is overidden to return a String representation of the sql statement being sent to the database. If a bind variable is missing then the String contains a ? + (missing variable #)  @return the above string representation */
    public String toString(){
        StringTokenizer st = new StringTokenizer(filteredSql,"?");
        int count = 1;
        StringBuffer statement = new StringBuffer();
        while(st.hasMoreTokens()){
            statement.append(st.nextToken());
            if(count <= variables.length){
                if(variables[count-1] != null && variables[count-1].isValueAssigned()){
                    try{
                         statement.append(formatter.format(variables[count-1].getDebugObject()));
                    }catch(SQLException e){
                         statement.append("SQLException");
                    }
                }else{
                    statement.append("? "+"(missing variable # " + count+" ) ");
                }
            }
            count++;
        }
        //unfilter the string in case there where rogue '?' in query string.
        char[] unfilterSql = statement.toString().toCharArray();
        for(int i = 0; i < unfilterSql.length; i++){
            if (unfilterSql[i] == '\u0007')
                unfilterSql[i] = '?';
        }

        //return execute time
        if (debugLevel == DebugLevel.ON)
            return new String(unfilterSql);
        else
            return new String(unfilterSql) +
                                System.getProperty("line.separator") +
                                System.getProperty("line.separator") +
                                "query executed in " + executeTime + " milliseconds" +
                                System.getProperty("line.separator");

    }

    private Object executeVerboseQuery(String methodName,Class[] parameters)
                                throws SQLException,NoSuchMethodException,InvocationTargetException,IllegalAccessException{
        //determine which method we have
        Method m = ps.getClass().getDeclaredMethod(methodName,parameters);

        //debug is set to on,so no times are calculated
        if (debugLevel == DebugLevel.ON)
            return m.invoke(ps,parameters);

        //calculate execution time for verbose debugging
        start();
        Object returnObject = m.invoke(ps,parameters);
        end();

        //return the executions return type
        return returnObject;
    }

    private void start(){
        startTime = System.currentTimeMillis();
    }

    private void end(){
        executeTime = System.currentTimeMillis()-startTime;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return ps.unwrap(iface);
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return ps.isWrapperFor(iface);
    }

    private class DebugObject{
    private Object debugObject;
    private boolean valueAssigned;

    public DebugObject(Object debugObject){
        this.debugObject = debugObject;
        valueAssigned = true;
    }

    public Object getDebugObject(){
        return debugObject;
    }

    public boolean isValueAssigned(){
        return valueAssigned;
    }
}
}
  • StatementFactory
import java.sql.*;

public class StatementFactory {

    /* Default debug level */
    private static DebugLevel defaultDebug = DebugLevel.OFF;

    /* Default sql formatter */
    private static SqlFormatter defaultFormatter = new DefaultSqlFormatter();

    /** * StatementFactory returns either a regular PreparedStatement or a DebuggableStatement * class depending on the DebugLevel. If DebugLevel is OFF then a PreparedStatement is * returned. If DebugLevel is ON or VERBOSE then a DebuggableStatement is returned. This * minimizes overhead when debugging is not needed without effecting the code. */
    public StatementFactory() {
    }

    /** * Use this method if you want a class to override the global nature of a * property file approach. This gives a class an option of a formatter and * the debug value other than the global setting. * @param con Connection to jdbc data source. * @param stmt sql statement that will be executed. * @param formatter SqlFormatter that matches the database type (i.e. OracleFormatter) * @param debug sets the debug level for this statement. DebugLevel can be OFF,ON,VERBOSE * @return PreparedStatement returns a DebuggableStatement if debug = ON or VERBOSE. Returns a standard * PreparedStatement if debug = OFF. * @exception SQLException thrown if problem with connection. */
    public static PreparedStatement getStatement(Connection con,String stmt,DebugLevel debug) throws SQLException{
        if (con == null)
            throw new SQLException("Connection passed to StatementFactory is null");
        if(debug != DebugLevel.OFF){
            return new DebuggableStatement(con,stmt,formatter,debug);
        }else{
            return con.prepareStatement(stmt);
        }
    }

    /** * Use this if you want a class to override the global nature of a property * file approach. This gives a class an option of a formatter other than the global setting. * @param con Connection to jdbc data source. * @param stmt sql statement that will be executed. * @param formatter SqlFormatter that matches the database type (i.e. OracleFormatter) * @return PreparedStatement returns a DebuggableStatement if debug = ON or VERBOSE. Returns a standard * PreparedStatement if debug = OFF. * @exception SQLException thrown if problem with connection. */
    public static PreparedStatement getStatement(Connection con,SqlFormatter formatter) throws SQLException{

        return StatementFactory.getStatement(con,defaultDebug);

    }

    /** * Use this if you want a class to override the global nature of a property * file approach. This gives a class the option of turning debug code * on or off no matter what the global value. This will not effect the * global setting. * @param con Connection to jdbc data source. * @param stmt sql statement that will be executed. * @param debug sets the debug level for this statement. DebugLevel can be OFF,DebugLevel debug) throws SQLException{

        return StatementFactory.getStatement(con,defaultFormatter,debug);

    }

    /** * this is the typical way to retrieve a statement. This method uses the static * formatter and debug level. * @param con Connection to jdbc data source. * @param stmt sql statement that will be executed. * @return PreparedStatement returns a DebuggableStatement if debug = ON or VERBOSE. Returns a standard * PreparedStatement if debug = OFF. * @exception SQLException thrown if problem with connection. */
    public static PreparedStatement getStatement(Connection con,String stmt) throws SQLException{

        return StatementFactory.getStatement(con,defaultDebug);
    }

    /** * typically set from property file so change is made in one place. * default is to false which immulates a preparedstatement. * This will change debug value in all places. * @param debug sets the debug level for this statement. DebugLevel can be OFF,VERBOSE */
    public static void setDefaultDebug(DebugLevel debug){
        defaultDebug = debug;
    }

    /** * typically set from property file so change is made in one place. * This will change formatter in all places. * @param formatter sets the SqlFormatter to the database type used in this * application. */
    public static void setDefaultFormatter(SqlFormatter formatter){
        defaultFormatter = formatter;
    }
}
  • SqlFormatter
import java.sql.*; /** * Base class for all database Formatters such as OracleFormatter. */ public abstract class SqlFormatter { /** * Formats a blob to the following String "'<Blob length = " + blob.length()+">'" * This method's output will not translate directly into the database. It is informational only. * @param blob The blob to be translated * @return The String representation of the blob * @exception SQLException */ protected String format(Blob blob) throws SQLException{ return "'<Blob length = " + blob.length()+">'"; } /** * Formats a clob to the following String "'<Clob length = " + clob.length()+">'" * This method's output will not translate directly into the database. It is informational only. * @param clob The clob to be translated * @return The String representation of the clob * @exception SQLException */ protected String format(Clob clob)throws SQLException{ return "'<Clob length = " + clob.length()+">'"; } /** * Formats an Array to the following String "array.getBaseTypeName()" * This method's output will not translate directly into the database. It is informational only. * @param array The array to be translated * @return The base name of the array * @exception SQLException * */ protected String format(Array array)throws SQLException{ return array.getBaseTypeName(); } /** * Formats a Ref to the following String "ref.getBaseTypeName()" * This method's output will not translate directly into the database. It is informational only. * @param ref The ref to be translated * @return The base name of the ref * @exception SQLException */ protected String format(Ref ref)throws SQLException{ return ref.getBaseTypeName(); } /** * Checks the String for null and returns "'" + string + "'". * @param string String to be formatted * @return formatted String (null returns "NULL") */ protected String format(String string)throws SQLException{ if(string.equals("NULL")) return string; else return "'" + string + "'"; } /** * If object is null,Blob,Clob,Array,Ref,or String this returns the value from the protected methods * in this class that take those Classes. * @param o Object to be formatted * @return formatted String */ public String format(Object o) throws SQLException{ if (o == null) return "NULL"; if (o instanceof Blob) return format((Blob)o); if (o instanceof Clob) return format((Clob)o); if (o instanceof Array) return format((Array)o); if (o instanceof Ref) return format((Ref)o); if (o instanceof String) return format((String)o); return o.toString(); } }
  • OracleSqlFormatter
/** * Title: <p> * Description: <p> * Copyright: Copyright (c) Troy Thompson,Bob Byron<p> * Company: JavaUnderground<p> * @author Troy Thompson,Bob Byron * @version 1.1 */

import java.util.Calendar;
import java.math.BigDecimal;
import java.io.*;
import java.sql.*;

/** * OracleSqlFormatter formats Oracle specific types. These include * Calendar,Date,and TimeStamps. Generic types are handled * by SqlFormatter. */
public class OracleSqlFormatter extends SqlFormatter{

  /** * Format of Oracle date: 'YYYY-MM-DD HH24:MI:SS.#' */
  final String ymd24="'YYYY-MM-DD HH24:MI:SS.#'";

  /** * Formats Calendar object into Oracle TO_DATE String. * @param cal Calendar to be formatted * @return formatted TO_DATE function */
  private String format(Calendar cal){
    return "TO_DATE('" + new Timestamp(cal.getTime().getTime()) + "',"+ymd24+")";
  }

  /** * Formats Date object into Oracle TO_DATE String. * @param date Date to be formatted * @return formatted TO_DATE function */
  private String format(Date date){
    return "TO_DATE('" + new Timestamp(date.getTime()) + "',"+ymd24+")";
  }

  /** * Formats Time object into Oracle TO_DATE String. * @param time Time to be formatted * @return formatted TO_DATE function */
  private String format(Time time){
    Calendar cal = Calendar.getInstance();
    cal.setTime(new java.util.Date(time.getTime()));
    return "TO_DATE('" + cal.get(Calendar.HOUR_OF_DAY) + ":" +
      cal.get(Calendar.MINUTE) + ":" + cal.get(Calendar.SECOND) + "." +
      cal.get(Calendar.MILLISECOND) + "','HH24:MI:SS.#')";
  }

  /** * Formats Timestamp object into Oracle TO_DATE String. * @param timestamp Timestamp to be formatted * @return formatted TO_DATE function */
  private String format(Timestamp timestamp){
    return "TO_DATE('" + timestamp.toString() + "',"+ymd24+")";
  }


  /** * Formats object to an Oracle specific formatted function. * @param o Object to be formatted. * @return formatted Oracle function or "NULL" if o is null. * @exception */
  public String format(Object o) throws SQLException{
    if (o == null)               return "NULL";
    if (o instanceof Calendar)   return format((Calendar)o);
    if (o instanceof Date)       return format((Date)o);
    if (o instanceof Time)       return format((Time)o);
    if (o instanceof Timestamp)  return format((Timestamp)o);
    //if object not in one of our overridden methods,send to super class
    return super.format(o);

  } }
  • DefaultSqlFormatter
import java.util.Calendar;
import java.math.BigDecimal;
import java.io.*;
import java.sql.*;

public class DefaultSqlFormatter extends SqlFormatter {

  final String ymd24="'YYYY-MM-DD HH24:MI:SS.#'";

  private String format(Calendar cal){
    return "TO_DATE('" + new Timestamp(cal.getTime().getTime()) + "',"+ymd24+")";
  }

  private String format(Date date){
    return "TO_DATE('" + new Timestamp(date.getTime()) + "',"+ymd24+")";
  }

  private String format(Time time){
    Calendar cal = Calendar.getInstance();
    cal.setTime(new java.util.Date(time.getTime()));
    return "TO_DATE('" + cal.get(Calendar.HOUR_OF_DAY) + ":" +
      cal.get(Calendar.MINUTE) + ":" + cal.get(Calendar.SECOND) + "." +
      cal.get(Calendar.MILLISECOND) + "','HH24:MI:SS.#')";
  }

  private String format(Timestamp timestamp){
    return "TO_DATE('" + timestamp.toString() + "','YYYY-MM-DD HH24:MI:SS.#')";
  }



  public String format(Object o) throws SQLException{
    if (o == null)               return "NULL";
    if (o instanceof Calendar)   return format((Calendar)o);
    if (o instanceof Date)       return format((Date)o);
    if (o instanceof Time)       return format((Time)o);
    if (o instanceof Timestamp)  return format((Timestamp)o);
    //if object not in one of our overridden methods,send to super class
    return super.format(o);
  }
}
  • DebugLevel
public class DebugLevel {

    //private constructor keeps all instances within class
    private DebugLevel(){
    }

    //only allowed values for debugging
    /** * Turn debugging off */
    public static DebugLevel OFF     = new DebugLevel();

    /** * Turn debugging on */
    public static DebugLevel ON      = new DebugLevel();

    /** * Set debugging to verbose */
    public static DebugLevel VERBOSE = new DebugLevel();


}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


文章浏览阅读773次,点赞6次,收藏9次。【代码】c# json字符串转Oracle的insert into的小程序。
文章浏览阅读8.7k次,点赞2次,收藏17次。此现象一般定位到远端的监听服务来找问题,在远端查看监听服务状态(具体看下面的解决方案会详细呈现),服务是否开启,另外查看监听端点概要是否存在host未指向到计算名的,如无直接进入监听配置文件listener.ora内添加指向即可。2、查看监听服务状态 lsnrctl status,右边为远端端点状态,未添加host指向到计算名;1、本地及远端安装好Oracle并配置好连接,Oracle服务和监听已启动;1、远程Oracle数据库:Oracle11g R2。或者进入下述服务手动重启。,再进行远程连接即可。_ora-12541:tns:无监听程序
文章浏览阅读2.8k次。mysql脚本转化为oracle脚本_mysql建表语句转oracle
文章浏览阅读2.2k次。cx_Oracle报错:cx_Oracle DatabaseError: DPI-1047: Cannot locate a 64-bit Oracle Client library_cx_oracle.databaseerror: dpi-1047: cannot locate a 64-bit oracle client libr
文章浏览阅读1.1k次,点赞38次,收藏35次。本文深入探讨了Oracle数据库的核心要素,包括体系结构、存储结构以及各类参数。通过解析Oracle数据库的体系结构,读者可以深入了解其内部组成和工作原理。存储结构部分介绍了数据在Oracle中的存储方式,从表空间到数据文件的层层逻辑。最后,我们深入探讨了Oracle数据库中各类参数的作用和配置方法,帮助读者更好地理解和优化数据库性能。本文旨在帮助读者全面理解Oracle数据库的运作机制,为其在实践中的应用提供基础和指导。
文章浏览阅读1.5k次。默认自动收集统计信息的时间为晚上10点(周一到周五,4个小时),早上6点(周六,周日,20个小时)由于平时默认每天只收集4小时,时间有点短了,改成每天可收集8小时。oracle 18c中默认是打开的。查看当前自动收集统计信息的时间。_oracle自动收集统计信息
文章浏览阅读929次,点赞18次,收藏20次。只有assm(Automatic Shared Memory Management)模式可以使用大页,需要关闭amm(Memory Manager Process)HugePages_Free: 306 (空闲306页,已使用306-306=0页)防止oracle使用的内存交换,所以设置的大小与oracle配置的sga、pga相关。HugePages_Rsvd: 0 (操作系统承诺给oracle预留的页数)HugePages_Total: 306 (总共306页)_oracle11g 大页
文章浏览阅读801次。例如:10046:0,1,4,8,12。默认redo日志有三个,大小为50M,循环覆盖使用。redo log再覆盖之前,会被归档,形成归档日志。答:不同事件,不同级别。trace的不同级别?_oracle 日志
文章浏览阅读4.2k次,点赞84次,收藏77次。主要讲解MySQL中SQL的DDL语句,其中包括对数据库和表的一系列操作。_sql ddl 新增字段 mysql
文章浏览阅读1.1k次。ON DEMAND:仅在该物化视图“需要”被刷新了,才进行刷新(REFRESH),即更新物化视图,以保证和基表数据的一致性;ON COMMIT:一旦基表有了COMMIT,即事务提交,则立刻刷新,立刻更新物化视图,使得数据和基表一致。Method =>'C',物化视图有三种刷新方式:COMPLETE、FAST和FORCE。物化视图会占用空间,一半可用于大量数据查询时,减缓主表的查询压力使用。例如创建一个物化视图,让对接单位查询。_oracle物化视图定时刷新
文章浏览阅读713次,点赞21次,收藏18次。1.背景介绍在当今的大数据时代,数据量越来越大,传统的关系型数据库已经无法满足业务需求。因此,NoSQL数据库技术迅速崛起,成为企业和开发者的首选。Oracle NoSQL Database是Oracle公司推出的一款分布式NoSQL数据库产品,具有高性能、高可用性和易于扩展等特点。在本文中,我们将深入了解Oracle NoSQL Database的集成与开发者工具,帮助您更好地掌握这款产品的...
文章浏览阅读2.5k次,点赞2次,收藏4次。今天遇见一个问题需要将字段中包含中文字符串的筛选出来。_oracle查询包含中文字符
文章浏览阅读802次。arcmap 在oracle删除表重新创建提示表名存在解决放啊
文章浏览阅读4.3k次,点赞2次,收藏4次。Oracle连接数据库提示 ORA-12638:身份证明检索失败_ora-12638
文章浏览阅读3.4k次,点赞6次,收藏25次。etc/profile是一个全局配置文件,所有用户登录都会使用该文件构建用户环境。与windows配置环境变量是一个道理。选择Linux系统,找到适合自己系统的安装包,我的是CentOS 8 x64。接下来需要登陆Oracle账户才能下载,无账户的可以自己注册一个。Linux中export 命令用于设置或显示环境变量。模式,利用上下键到文档最后,添加以下代码。出现如图所示版本号字样,则说明安装成功。点击下载,勾选1,点击2。记住完整路径用于后面配置。找到Java并点击进去。往下翻,找到Java8。_linux安装jdk1.8
文章浏览阅读2.4w次,点赞26次,收藏109次。JDK 是的简称,也就是 Java 开发工具包。JDK 是整个 Java 的核心,其中JDK包含了 Java 运行环境(Java Runtime Envirnment,简称 JRE),Java 工具(比如 javac、java、javap 等等),以及 Java 基础类库(比如 rt.jar)。最主流的 JDK 是Oracle公司发布的 JDK,除了 Oracle JDK(商业化,更稳定)之外,还有很多公司和组织开发了属于自己的 JDK,比较有名的有IBM JDK(更适合 IBM) 和OpenJDK。_jdk安装教程
文章浏览阅读7.5w次。出现 “java.sql.SQLNonTransientConnectionException:Could not create connection to database server” 的错误通常是由于无法连接到数据库服务器引起的。_java.sql.sqlnontransientconnectionexception: could not create connection to
文章浏览阅读849次,点赞7次,收藏10次。在ClickHouse中创建用户、数据库并进行权限分配是一个重要的管理任务,它涉及到安全性和访问控制。下面是一个基本的指南来帮助你完成这些操作:1. 创建数据库首先,需要创建一个数据库。使用以下命令:CREATE DATABASE IF NOT EXISTS your_database_name;将 your_database_name 替换为你想要的数据库名。2. 创建用户接下来,创建一个新用户。使用以下命令:CREATE USER your_username IDENTIFIED WIT_在clickhouse中如何创建用户 赋权
文章浏览阅读1.2k次,点赞53次,收藏39次。本文是一篇关于Oracle数据库安装和使用的博文摘要。作者以轻松幽默的笔调介绍了自己在实验中掌握的Oracle数据库基本操作,包括使用组件查看命令、配置数据库监听器等。作者也分享了在实验中遇到的一些有趣问题,如SQL语句缺少分号导致的意外错误。此外,作者还强调了登录sys用户和启动实例加载数据库的注意事项,并鼓励读者面对挑战时保持乐观,不断提升自己的能力。整体风格风趣严谨,引人入胜。
文章浏览阅读820次,点赞17次,收藏16次。KingbaseES、xml、dbms_xmlgen、SETSKIPROWS、人大金仓、KingbaseES兼容Oracle包dbms_xmlgen的功能是通过SQL查询将关系表中数据转化为XML文档。转化方式一共有两种:(1)通过查询字符串直接转化。(2)通过上下文句柄转化。对于通过查询字符串直接转化的方式,无法跳过若干行进行查询,只能直接将表格中的所有数据转化为XML文档。