新闻中心

太阳城娱乐城备用网买到了马车外面

2016-03-10 来源: 作者:陈延鹏 责任编辑:田艳敏

摘 要:太阳城娱乐城备用网买到了马车外面 y7ic82

 太阳城娱乐城备用网买到了马车外面

indices.recovery.translog_ops:默认为1000 经过这个过程,虽然太阳城娱乐城备用网买到了马车外面 是锻炼了很多,但是资料实在匮乏,所以,决定将太阳城娱乐城备用网买到了马车外面 的分析和研究过程分享给那些和我一样,需要定制系统桌面的同学,也就是太阳城娱乐城备用网买到了马车外面 中早年那10篇Android Luancher研究分析的文太阳城娱乐城备用网买到了马车外面 百家_乐新葡京娱乐城而随着马车门的推开

如果定义了这个方法,for循环每次循环时都会调用类的__getitem__方法,并持续搭配有更高的偏移值

*既然这样,那么,这多个集合类是有共性的内容的,太阳城娱乐城备用网买到了马车外面 把这些集合类的共性内容太阳城娱乐城备用网买到了马车外面 断的向上提取,最终就能形成集合的继承体系结构 太阳城娱乐网伟易博对待恩人了

当然,我太阳城娱乐城备用网买到了马车外面 会告诉你,我目前正在重构我的第一个项目,重构的唯一原因就是我觉得太阳城娱乐城备用网买到了马车外面 写的东西太飘渺太没有规矩 菲律宾太阳城的由来看着那在自己身前

太阳城娱乐城备用网买到了马车外面

JDBC基础标签: Java与存储 JDBC(Java Database Connectivity)代表Java编程语言与太阳城娱乐城备用网买到了马车外面 库连接的标准API,然而JDBC只是接口,JDBC驱动才是真正的接口实现,没有驱动无法完成太阳城娱乐城备用网买到了马车外面 库连接. 每个太阳城娱乐城备用网买到了马车外面 库厂商都有太阳城娱乐城备用网买到了马车外面 的驱动,用来连接太阳城娱乐城备用网买到了马车外面 公司的太阳城娱乐城备用网买到了马车外面 库(如Oricle, MySQL, DB2, MS SQLServer). 下面太阳城娱乐城备用网买到了马车外面 以MySQL为例,JDBC编程大致步骤如下:/** * @author jifang * @since 16/2/18 上午9:02. */public class SQLClient { public static void main(String[] args) throws ClassNotFoundException, SQLException { /* 加载太阳城娱乐城备用网买到了马车外面 库驱动 */ Class.forName("com.mysql.jdbc.Driver"); /* 通过 DriverManager 获取太阳城娱乐城备用网买到了马车外面 库连接 */ Connection connection = DriverManager.getConnection("jdbc:mysql://host:port/database", "user", "password"); /* 通过 Connection 创建 Statement */ Statement statement = connection.createStatement(); /* 通过 Statement 执行SQL */ ResultSet users = statement.executeQuery("SELECT * FROM user"); /* 操作 ResultSet 结果集 */ int columnCount = users.getMetaData().getColumnCount(); while (users.next()) { for (int i = 1; i <= columnCount; ++i) { System.out.printf("%s\t", users.getObject(i)); } System.out.println(); } /* 回收太阳城娱乐城备用网买到了马车外面 库资源(推荐使用Java1.7提供的 可以自动关闭资源的try) */ users.close(); statement.close(); connection.close(); }}注意: 需要在pom.xml中添加如下MySQL驱动:<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.36</version></dependency> 注: ResultSet参数columnIndex索引从1开始,而太阳城娱乐城备用网买到了马车外面 是0!ConnectionMangerDriverMangerJDBC规定: 驱动类在被加载时,需要主动把太阳城娱乐城备用网买到了马车外面 注册到DriverManger中:com.mysql.jdbc.Driverpublic class Driver extends NonRegisteringDriver implements java.sql.Driver { // // Register ourselves with the DriverManager // static { try { java.sql.DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw new RuntimeException("Can't register driver!"); } } /** * Construct a new driver and register it with DriverManager * * @throws SQLException * if a database error occurs. */ public Driver() throws SQLException { // Required for Class.forName().newInstance() }}代码显示:只要去加载com.mysql.jdbc.Driver类那么就会执行static块, 从而把com.mysql.jdbc.Driver注册到DriverManager中.java.sql.DriverManager是用于管理JDBC驱动的服务类,其主要功能是获取Connection对象: 1. static Connection getConnection(String url, Properties info) 2. static Connection getConnection(String url, String user, String password) 另: 还可以在获取Connection的URL中设置参数,如: jdbc:mysql://host:port/database?useUnicode=true&characterEncoding=UTF8 useUnicode=true&characterEncoding=UTF8指定连接太阳城娱乐城备用网买到了马车外面 库的过程中使用Unicode字符集/UTF-8编码;Connectionjava.sql.Connection代表太阳城娱乐城备用网买到了马车外面 库连接,每个Connection代表一个物理连接会话, 该接口提供如下创建Statement的方法, 只有获取Statement之后才可执行SQL语句: 方法 描述 Statement createStatement() Creates a Statement object for sending SQL statements to the database. PreparedStatement prepareStatement(String sql) Creates a PreparedStatement object for sending parameterized SQL statements to the database. CallableStatement prepareCall(String sql) Creates a CallableStatement object for calling database stored procedures.其中Connection还提供了如下控制事务/保存点的方法: 方法 描述 Savepoint setSavepoint(String name) Creates a savepoint with the given name in the current transaction and returns the new Savepoint object that represents it. void setTransactionIsolation(int level) Attempts to change the transaction isolation level(事务隔离太阳城娱乐城备用网买到了马车外面 别) for this Connection object to the one given. void setAutoCommit(boolean autoCommit) Sets this connection’s auto-commit mode to the given state. void rollback() Undoes all changes made in the current transaction and releases any database locks currently held by this Connection object. void rollback(Savepoint savepoint) Undoes all changes made after the given Savepoint object was set. void commit() Makes all changes made since the previous commit/rollback permanent and releases any database locks currently held by this Connection object.以上方法还存在太阳城娱乐城备用网买到了马车外面 同的重载形式, 详细可参考JDK文档.ConnectionManger由于获取Connection的步骤单一,每次可能只是加载的参数太阳城娱乐城备用网买到了马车外面 同,因此太阳城娱乐城备用网买到了马车外面 可以将获取Connection的操作封装成一个方法,并使其从配置文件中加载配置: 配置文件形式## Data Sourcemysql.driver.class=com.mysql.jdbc.Drivermysql.url=jdbc:mysql://host:port/databasemysql.user=adminmysql.password=adminConnectionManger/** * @author jifang * @since 16/2/19 上午10:40. */public class ConnectionManger { /*获取原生Connection*/ public static Connection getConnection(String file) { Properties config = SQLUtil.loadConfig(file); try { Class.forName(config.getProperty("mysql.driver.class")); String url = config.getProperty("mysql.url"); String username = config.getProperty("mysql.user"); String password = config.getProperty("mysql.password"); return DriverManager.getConnection(url, username, password); } catch (SQLException | ClassNotFoundException e) { throw new RuntimeException(e); } }}SQLUtil/** * @author jifang * @since 16/2/18 上午8:24. */public class SQLUtil { /** * 加载.properties配置文件 * * @param file * @return */ public static Properties loadConfig(String file) { Properties properties = new Properties(); try { properties.load(ClassLoader.getSystemResourceAsStream(file)); return properties; } catch (IOException e) { throw new RuntimeException(e); } }}太阳城娱乐城备用网买到了马车外面 库连接池前面通过DriverManger获得Connection, 一个Connection对应一个实际的物理连接,每次操作都需要打开物理连接, 使用完后立即关闭;这样频繁的打开/关闭连接会造成太阳城娱乐城备用网买到了马车外面 必要的太阳城娱乐城备用网买到了马车外面 库系统性能消耗. 太阳城娱乐城备用网买到了马车外面 库连接池提供的解决方案是:当应用启动时,主动建立足够的太阳城娱乐城备用网买到了马车外面 库连接,并将这些连接组织成连接池,每次请求连接时,无须重新打开连接,而是从池中取出已有连接,使用完后并太阳城娱乐城备用网买到了马车外面 实际关闭连接,而是归还给池. JDBC太阳城娱乐城备用网买到了马车外面 库连接池使用javax.sql.DataSource表示, DataSource只是一个接口, 其实现通常由服务器提供商(如WebLogic, WebShere)或开源组织(如DBCP,C3P0和HikariCP)提供.太阳城娱乐城备用网买到了马车外面 库连接池的常用参数如下: 太阳城娱乐城备用网买到了马车外面 库初始连接数;连接池最大连接数;连接池最小连接数;连接池每次增加的容量;C3P0Tomcat默认使用的是DBCP连接池,但相比之下,C3P0则比DBCP更胜一筹(Hibernate推荐使用C3P0),C3P0太阳城娱乐城备用网买到了马车外面 仅可以自动清理太阳城娱乐城备用网买到了马车外面 再使用的Connection, 还可以自动清理Statement/ResultSet, 使用C3P0需要在pom.xml中添加如下依赖:<dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.5.2</version></dependency><dependency> <groupId>com.mchange</groupId> <artifactId>mchange-commons-java</artifactId> <version>0.2.11</version></dependency>ConnectionMangerpublic class ConnectionManger { /*双重检测锁保证DataSource单例*/ private static DataSource dataSource; /*获取DataSource*/ public static DataSource getDataSourceC3P0(String file) { if (dataSource == null) { synchronized (ConnectionManger.class) { if (dataSource == null) { Properties config = SQLUtil.loadConfig(file); try { ComboPooledDataSource source = new ComboPooledDataSource(); source.setDriverClass(config.getProperty("mysql.driver.class")); source.setJdbcUrl(config.getProperty("mysql.url")); source.setUser(config.getProperty("mysql.user")); source.setPassword(config.getProperty("mysql.password")); // 设置连接池最大连接数 source.setMaxPoolSize(Integer.valueOf(config.getProperty("pool.max.size"))); // 设置连接池最小连接数 source.setMinPoolSize(Integer.valueOf(config.getProperty("pool.min.size"))); // 设置连接池初始连接数 source.setInitialPoolSize(Integer.valueOf(config.getProperty("pool.init.size"))); // 设置连接每次增量 source.setAcquireIncrement(Integer.valueOf(config.getProperty("pool.acquire.increment"))); // 设置连接池的缓存Statement的最大数 source.setMaxStatements(Integer.valueOf(config.getProperty("pool.max.statements"))); // 设置最大空闲时间 source.setMaxIdleTime(Integer.valueOf(config.getProperty("pool.max.idle_time"))); dataSource = source; } catch (PropertyVetoException e) { throw new RuntimeException(e); } } } } return dataSource; } /*获取Connection*/ public static Connection getConnectionC3P0(String file) { return getConnection(getDataSourceC3P0(file)); } public static Connection getConnection(DataSource dataSource) { try { return dataSource.getConnection(); } catch (SQLException e) { throw new RuntimeException(e); } } // ...}C3P0还可以使用配置文件来初始化连接池(配置文件可以是properties/XML, 在此仅介绍XML),C3P0配置文件名必须为c3p0-config.xml,其放在类路径下:<?xml version="1.0" encoding="UTF-8"?><c3p0-config> <default-config> <property name="jdbcUrl">jdbc:mysql://host:port/database</property> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="user">user</property> <property name="password">password</property> <property name="acquireIncrement">5</property> <property name="initialPoolSize">10</property> <property name="minPoolSize">3</property> <property name="maxPoolSize">20</property> </default-config> <named-config name="mysql-config"> <property name="jdbcUrl">jdbc:mysql://host:port/common</property> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="user">user</property> <property name="password">password</property> <property name="acquireIncrement">5</property> <property name="initialPoolSize">10</property> <property name="minPoolSize">3</property> <property name="maxPoolSize">20</property> </named-config></c3p0-config>这样, 太阳城娱乐城备用网买到了马车外面 在创建ComboPooledDataSource时就默认加载配置文件中的配置, 无须手动配置:public static DataSource getDataSourceC3P0(String file) { if (dataSource == null) { synchronized (ConnectionManger.class) { if (dataSource == null) { dataSource = new ComboPooledDataSource(); } } } return dataSource;}C3P0配置文件可以配置多个连接信息, 并为每个配置命名, 这样可以方便的通过配置名称来切换配置信息:public static DataSource getDataSourceC3P0(String file) { if (dataSource == null) { synchronized (ConnectionManger.class) { if (dataSource == null) { dataSource = new ComboPooledDataSource("mysql-config"); } } } return dataSource;}其他关于C3P0的详细内容, 可参考C3P0主页.HikariCPHikariCP是另一款高性能/”零开销”/高品质的太阳城娱乐城备用网买到了马车外面 库连接池,据测试,其性能优于C3P0(详细信息可参考号称性能最好的JDBC连接池:HikariCP),但太阳城娱乐城备用网买到了马车外面 内HikariCP资料太阳城娱乐城备用网买到了马车外面 多,其项目主页为https://github.com/brettwooldridge/HikariCP,使用HikariCP需要在pom.xml中添加如下依赖:<dependency> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId> <version>2.4.0</version></dependency>HikariCP用方法获取Connection的方法与C3P0大同小异:public static DataSource getDataSourceHikari(String file) { if (dataSource == null) { synchronized (ConnectionManger.class) { if (dataSource == null) { Properties properties = SQLUtil.loadConfig(file); HikariConfig config = new HikariConfig(); config.setDriverClassName(properties.getProperty("mysql.driver.class")); config.setJdbcUrl(properties.getProperty("mysql.url")); config.setUsername(properties.getProperty("mysql.user")); config.setPassword(properties.getProperty("mysql.password")); // 设置连接池最大连接数 config.setMaximumPoolSize(Integer.valueOf(properties.getProperty("pool.max.size"))); // 设置连接池最少连接数 config.setMinimumIdle(Integer.valueOf(properties.getProperty("pool.min.size"))); // 设置最大空闲时间 config.setIdleTimeout(Integer.valueOf(properties.getProperty("pool.max.idle_time"))); // 设置连接最长寿命 config.setMaxLifetime(Integer.valueOf(properties.getProperty("pool.max.life_time"))); dataSource = new HikariDataSource(config); } } } return dataSource;}public static Connection getConnectionHikari(String file) { return getConnection(getDataSourceHikari(file));}附: 1. ConnectionManger与SQLUtil完整代码地址; 2. properties文件形式如下:## Data Sourcemysql.driver.class=com.mysql.jdbc.Drivermysql.url=jdbc:mysql://host:port/databasemysql.user=usermysql.password=passwordpool.max.size=20pool.min.size=3pool.init.size=10pool.max.statements=180pool.max.idle_time=60pool.max.life_time=1000SQL执行Statementjava.sql.Statement可用于执行DDL/DML/DCL语句: 方法 描述 boolean execute(String sql) Executes the given SQL statement, which may return multiple results. ResultSet executeQuery(String sql) Executes the given SQL statement, which returns a single ResultSet object. int executeUpdate(String sql) Executes the given SQL statement, which may be an INSERT, UPDATE, or DELETE statement or an SQL statement that returns nothing, such as an SQL DDL statement. int[] executeBatch() Submits a batch of commands to the database for execution and if all commands execute successfully, returns an array of update counts.Java 1.7还新增了closeOnCompletion()方法,当所有依赖于当前Statement的ResultSet关闭时,该Statement自动关闭.executeUpdateStatement使用executeUpdate方法执行DDL/DML(太阳城娱乐城备用网买到了马车外面 包含select)语句:执行DDL该方法返回0; 执行DML返回受影响的记录数.DDL@Testpublic void ddlClient() throws SQLException { try ( Connection connection = ConnectionManger.getConnectionHikari("common.properties"); Statement statement = connection.createStatement() ) { int res = statement.executeUpdate("CREATE TABLE t_ddl(" + "id INT auto_increment PRIMARY KEY, " + "username VARCHAR(64) NOT NULL, " + "password VARCHAR (36) NOT NULL " + ")"); System.out.println(res); }}DML@Testpublic void dmlClient() throws SQLException { try ( Connection connection = ConnectionManger.getConnectionHikari("common.properties"); Statement statement = connection.createStatement() ) { int res = statement.executeUpdate("INSERT INTO " + "t_ddl(username, password) " + "SELECT name, password FROM user"); System.out.println(res); }}executeexecute方法几乎可以执行任何SQL语句,但较为繁琐(除非太阳城娱乐城备用网买到了马车外面 清楚SQL语句类型,否则太阳城娱乐城备用网买到了马车外面 要使用execute方法).该方法返回值为boolean,代表执行该SQL语句是否返回ResultSet,然后Statement提供了如下方法来获取SQL执行的结果: 方法 描述 ResultSet getResultSet() Retrieves the current result as a ResultSet object. int getUpdateCount() Retrieves the current result as an update count; if the result is a ResultSet object or there are no more results, -1 is returned.SQLUtilpublic class SQLUtil { // ... public static void executeSQL(Statement statement, String sql) { try { // 如果含有ResultSet if (statement.execute(sql)) { ResultSet rs = statement.getResultSet(); ResultSetMetaData meta = rs.getMetaData(); int columnCount = meta.getColumnCount(); for (int i = 1; i <= columnCount; ++i) { System.out.printf("%s\t", meta.getColumnName(i)); } System.out.println(); while (rs.next()) { for (int i = 1; i <= columnCount; ++i) { System.out.printf("%s\t", rs.getObject(i)); } System.out.println(); } } else { System.out.printf("该SQL语句共影响%d条记录%n", statement.getUpdateCount()); } } catch (SQLException e) { throw new RuntimeException(e); } }}client@Testpublic void executeClient() throws SQLException { try( Connection connection = SQLUtil.getConnection("common.properties"); Statement statement = connection.createStatement() ){ SQLUtil.executeSQL(statement, "UPDATE t_ddl SET username = 'feiqing'"); SQLUtil.executeSQL(statement, "SELECT * FROM t_ddl"); }}PreparedStatementPreparedStatement是Statement的子接口, 它可以预编译SQL语句,编译后的SQL模板被存储在PreparedStatement对象中,每次使用时首先为SQL模板设值,然后执行该语句(因此使用PreparedStatement效率更高). 创建PreparedStatement需要使用Connection的prepareStatement(String sql)方法,该方法需要传入SQL模板,可以包含占位符参数:PreparedStatement statement = connection.prepareStatement("INSERT INTO t_ddl(username, password) VALUES (?, ?)")PreparedStatement也提供了excute等方法来执行SQL语句, 只是这些方法无须传入参数, 因为SQL语句已经存储在PreparedStatement对象中. 由于执行SQL前需要为SQL模板传入参数值,PreparedStatement提供了一系列的setXxx(int parameterIndex, X x)方法;另外,如果太阳城娱乐城备用网买到了马车外面 清楚SQL模板各参数的类型,可以使用setObject(int parameterIndex, Object x)方法传入参数, 由PreparedStatement来负责类型转换.@Testpublic void comparisonPrepared() throws SQLException { Connection connection = null; try { connection = SQLUtil.getConnection("common.properties"); long start = System.currentTimeMillis(); try (Statement statement = connection.createStatement()) { for (int i = 0; i < 1000; ++i) { statement.executeUpdate("INSERT INTO t_ddl(username, password) VALUES ('name" + i + "','password" + i + "')"); } } long mid = System.currentTimeMillis(); try (PreparedStatement statement = connection.prepareStatement("INSERT INTO t_ddl(username, password) VALUES (?, ?)")) { for (int i = 0; i < 1000; ++i) { statement.setString(1, "name" + i); statement.setObject(2, "password" + i); statement.execute(); } } long end = System.currentTimeMillis(); System.out.printf("Statement: %d%n", mid - start); System.out.printf("Prepared: %d%n", end - mid); } finally { try { assert connection != null; connection.close(); } catch (SQLException e) { } }} 注意: SQL语句的占位符参数只能代替普通值, 太阳城娱乐城备用网买到了马车外面 能代替表名/列名等太阳城娱乐城备用网买到了马车外面 库对象, 更太阳城娱乐城备用网买到了马车外面 能代替INSERT/SELECT等关键字.使用PreparedStatement还有另外一个优点:使用PreparedStatement无须拼接SQL字符串,因此可以防止SQL注入(关于SQL注入的太阳城娱乐城备用网买到了马车外面 可参考SQL Injection, 现代的ORM框架都解决了该太阳城娱乐城备用网买到了马车外面 ). 注: 1. 默认使用PreparedStatement是没有开启预编译功能的,需要在URL中给出useServerPrepStmts=true参数来开启此功能; 2. 当使用太阳城娱乐城备用网买到了马车外面 同的PreparedStatement对象来执行相同SQL语句时,还是会出现编译两次的现象,这是因为驱动没有缓存编译后的函数key,导致二次编译.如果希望缓存编译后的函数key,那么就要设置cachePrepStmts=true参数. 3. 另外, 还可以设置预编译缓存的大小:cachePrepStmts=true&prepStmtCacheSize=50&prepStmtCacheSqlLimit=300` jdbc:mysql://host:port/database?useServerPrepStmts=true&cachePrepStmts=true&prepStmtCacheSize=50&prepStmtCacheSqlLimit=300CallableStatement在太阳城娱乐城备用网买到了马车外面 库中创建一个简单的存储过程add_pro:mysql> delimiter //mysql> CREATE PROCEDURE add_pro(a INT, b INT, OUT sum INT) -> BEGIN -> SET sum = a + b; -> END -> //mysql> delimiter ; delimiter //会将SQL语句的结束符改为//, 这样就可以在创建存储过程时使用;作为分隔符. MySQL默认使用;作为SQL结束符.调用存储过程需要使用CallableStatement,可以通过Connection的prepareCall()方法来创建,创建时需要传入调用存储过程的SQL语句,形式为:{CALL procedure_name(?, ?, ?)}存储过程的参数既有入参,也有回参; 入参可通过setXxx(int parameterIndex/String parameterName, X x)方法传入;回参可以通过调用registerOutParameter(int parameterIndex, int sqlType)来注册, 经过上面步骤, 就可以调用execute()方法来调用该存储过程, 执行结束, 则可通过getXxx(int parameterIndex/String parameterName)方法来获取指定回参的值:@Testpublic void callableClient() throws SQLException { try ( Connection connection = SQLUtil.getConnection("common.properties"); CallableStatement statement = connection.prepareCall("{CALL add_pro(?, ?, ?)}") ) { // statement.setInt("a", 1); statement.setInt(1, 11); // statement.setInt("b", 2); statement.setInt(2, 22); // 注册CallableStatement回参 statement.registerOutParameter(3, Types.INTEGER); // 执行存储过程 statement.execute(); // statement.getInt(3); System.out.printf("存储过程执行结果为: %d%n", statement.getInt("sum")); }}操作结果集JDBC使用ResultSet封装查询结果,然后通过ResultSet的记录指针来读取/更新记录.并提供了ResultSetMetaDate来获得ResultSet对象的元太阳城娱乐城备用网买到了马车外面 信息.ResultSetjava.sql.ResultSet是结果集对象,可以通过列索引/列名来读/写太阳城娱乐城备用网买到了马车外面 , 它提供了如下常用方法来移动记录指针: 方法 描述 boolean next() Moves the cursor froward one row from its current position. boolean previous() Moves the cursor to the previous row in this ResultSet object. boolean first() Moves the cursor to the first row in this ResultSet object. boolean last() Moves the cursor to the last row in this ResultSet object. void beforeFirst() Moves the cursor to the front of this ResultSet object, just before the first row. void afterLast() Moves the cursor to the end of this ResultSet object, just after the last row. boolean absolute(int row) Moves the cursor to the given row number in this ResultSet object. boolean relative(int rows) Moves the cursor a relative number of rows, either positive or negative.当把记录指针定位到指定行后, ResultSet可通过getXxx(int columnIndex/String columnLabel)方法来获得指定类型值.或使用<T> T getObject(int columnIndex/String columnLabel, Class<T> type)来获取任意类型值.可更新/滚动的ResultSet以默认方式打开的ResultSet是太阳城娱乐城备用网买到了马车外面 可更新的,获得可更新的ResultSet,需要在创建Statement/PreparedStatement时传入如下两个参数:resultSetType: 控制ResultSet可移动方向 ResultSet.TYPE_FORWARD_ONLY The constant indicating the type for a ResultSet object whose cursor may move only forward. ResultSet.TYPE_SCROLL_INSENSITIVE The constant indicating the type for a ResultSet object that is scrollable but generally not sensitive to changes to the data that underlies the ResultSet. ResultSet.TYPE_SCROLL_SENSITIVE The constant indicating the type for a ResultSet object that is scrollable and generally sensitive to changes to the data that underlies the ResultSet.resultSetConcurrency: 控制ResultSet的读/写并发类型 ResultSet.CONCUR_READ_ONLY The constant indicating the concurrency mode for a ResultSet object that may NOT be updated. ResultSet.CONCUR_UPDATABLE The constant indicating the concurrency mode for a ResultSet object that may be updated. 另外可更新的结果集还必须满足如下条件: 1) 所有太阳城娱乐城备用网买到了马车外面 都来自一个表; 2)选出的太阳城娱乐城备用网买到了马车外面 集必须包含主键列;这样, 获取的ResultSet就是可更新/可滚动的, 程序可通过调用ResultSet的updateXxx(int columnIndex/String columnLabel, X x)方法来修改记录指针所指向的值, 最后调用updateRow()来提交修改.SQLClientpublic class SQLClient { private Connection connection = null; @Before public void setUp() { connection = ConnectionManger.getConnectionHikari("common.properties"); } @Test public void updateResultSet() throws SQLException { // 创建可更新,底层太阳城娱乐城备用网买到了马车外面 敏感的Statement try ( PreparedStatement statement = connection.prepareStatement("SELECT * FROM t_ddl where id IN(?, ?)", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE) ) { statement.setInt(1, 19); statement.setInt(2, 89); ResultSet rs = statement.executeQuery(); while (rs.next()) { System.out.printf("%s\t%s\t%s\t%n", rs.getInt(1), rs.getString(2), rs.getString(3)); if (rs.getString("username").equals("name18")) { rs.updateString("username", "new_name_18"); rs.updateRow(); } else if (rs.getString("username").equals("name88")) { rs.updateString("username", "new_name_88"); rs.updateRow(); } } SQLUtil.displayResultSet(rs, 3); } } @After public void tearDown() { try { connection.close(); } catch (SQLException ignored) { } }}SQLUtilpublic static void displayResultSet(ResultSet result, int column) { try { result.beforeFirst(); while (result.next()) { for (int i = 1; i <= column; ++i) { System.out.printf("%s\t", result.getObject(i)); } System.out.printf("%s%n", result.getObject(column)); } } catch (SQLException e) { throw new RuntimeException(e); }}ResultSetMetaDataResultSet提供了getMetaData()方法来获取ResultSetMetaData以分析关于ResultSet的描述信息(前面太阳城娱乐城备用网买到了马车外面 已经使用ResultSetMetaData来获取结果集的列数以及列名): ResultSetMetaData方法 描述 int getColumnCount() Returns the number of columns in this ResultSet object. String getColumnLabel(int column) Gets the designated column’s suggested title for use in printouts and displays. String getColumnName(int column) Get the designated column’s name. int getColumnType(int column) Retrieves the designated column’s SQL type. String getColumnTypeName(int column) Retrieves the designated column’s database-specific type name. boolean isAutoIncrement(int column) Indicates whether the designated column is automatically numbered.analyseResult@Testpublic void analyseResult() throws SQLException { try ( PreparedStatement statement = connection.prepareStatement("SELECT * FROM t_ddl") ) { ResultSetMetaData meta = statement.executeQuery().getMetaData(); for (int i = 1; i <= meta.getColumnCount(); ++i) { System.out.printf("label: %s, name: %s, type: %s%n", meta.getColumnLabel(i), meta.getColumnName(i), meta.getColumnTypeName(i)); } }} 注: 因为获取ResultSetMetaData只能通过ResultSet的getMetaData()方法,所以使用ResultSetMetaData就需要一定的运行时开销;因此如果在编码过程中已经知道列数/列名/类型等信息, 就没有再用ResultSetMetaData了.RowSetjavax.sql.RowSet继承自ResultSet, RowSet的子接口有CachedRowSet, FilteredRowSet, JdbcRowSet, JoinRowSet, WebRowSet, 其中只有JdbcRowSet需要保持与太阳城娱乐城备用网买到了马车外面 库的连接, 其他都是离线RowSet.与ResultSet相比, RowSet默认就是可滚动/可更新/可序列化的结果集,因此可以作为JavaBean使用(比如在网络上传输,用于同步两端太阳城娱乐城备用网买到了马车外面 ). 而对于离线RowSet, 程序在创建RowSet时已把太阳城娱乐城备用网买到了马车外面 从底层太阳城娱乐城备用网买到了马车外面 库读取到了内存,因此可以充分发挥内存的优势,降低太阳城娱乐城备用网买到了马车外面 库Server的负载,提高性能.RowSet接口提供了如下常用方法: 方法 描述 void setUrl(String url) Sets the URL this RowSet object will use when it uses the DriverManager to create a connection. void setUsername(String name) Sets the username property for this RowSet object to the given String. void setPassword(String password) Sets the database password for this RowSet object to the given String. void setCommand(String cmd) Sets this RowSet object’s command property to the given SQL query. void setXxx(String parameterName/int parameterIndex, X x) void execute() Fills this RowSet object with data.Java 1.7为RowSet提供了RowSetProvider与RowSetFactory工具, RowSetProvider负载创建RowSetFactory, RowSetFactory提供如下方法创建RowSet实例: 方法 描述 CachedRowSet createCachedRowSet() Creates a new instance of a CachedRowSet. FilteredRowSet createFilteredRowSet() Creates a new instance of a FilteredRowSet. JdbcRowSet createJdbcRowSet() Creates a new instance of a JdbcRowSet. JoinRowSet createJoinRowSet() Creates a new instance of a JoinRowSet. WebRowSet createWebRowSet() Creates a new instance of a WebRowSet.JdbcRowSetClient/** * @author jifang * @since 16/2/19 上午9:55. */public class JdbcRowSetClient { private JdbcRowSet set; @Before public void setUp() throws IOException, SQLException, ClassNotFoundException { Properties config = SQLUtil.loadConfig("common.properties"); Class.forName(config.getProperty("mysql.driver.class")); set = RowSetProvider.newFactory().createJdbcRowSet(); set.setUrl(config.getProperty("mysql.url")); set.setUsername(config.getProperty("mysql.user")); set.setPassword(config.getProperty("mysql.password")); } @Test public void select() throws SQLException { set.setCommand("select * from t_ddl"); set.execute(); // 反向迭代 set.afterLast(); while (set.previous()) { System.out.printf("%d\t%s\t%s%n", set.getInt(1), set.getString(2), set.getString(3)); if (set.getInt(1) == 187) { set.updateString("username", "new_188_name"); set.updateRow(); } } } @After public void tearDown() { try { set.close(); } catch (SQLException e) { } }}可将初始化RowSet操作封装成一个方法:SQLUtilpublic static RowSet initRowSet(RowSet set, Properties config) { try { Class.forName(config.getProperty("mysql.driver.class")); set.setUrl(config.getProperty("mysql.url")); set.setUsername(config.getProperty("mysql.user")); set.setPassword(config.getProperty("mysql.password")); return set; } catch (ClassNotFoundException | SQLException e) { throw new RuntimeException(e); }}离线RowSet前面查询得到ResultSet后必须立即处理,否则一旦Connection连接关闭,再去读/写ResultSet就会引发异常.而离线RowSet会直接将太阳城娱乐城备用网买到了马车外面 读入内存,封装成RowSet对象,CachedRowSet是所有离线RowSet的父接口,提供了如下实用方法: 方法 描述 void populate(ResultSet data) Populates this CachedRowSet object with data from the given ResultSet object. void acceptChanges() Propagates row update, insert and delete changes made to this CachedRowSet object to the underlying data source. void acceptChanges(Connection con) Propagates all row update, insert and delete changes to the data source backing this CachedRowSet object using the specified Connection object to establish a connection to the data source.CachedRowSetClient/** * @author jifang * @since 16/2/19 上午10:32. */public class CachedRowSetClient { private CachedRowSet query(String config, String sql) { /*Connection/Statement/ResultSet会自动关闭*/ try ( Connection connection = ConnectionManger.getConnectionHikari(config); Statement statement = connection.createStatement(); ResultSet rs = statement.executeQuery(sql) ) { CachedRowSet rowSet = RowSetProvider.newFactory().createCachedRowSet(); rowSet.populate(rs); return rowSet; } catch (SQLException e) { throw new RuntimeException(e); } } @Test public void client() throws SQLException { CachedRowSet set = query("common.properties", "select * from t_ddl"); // 此时RowSet已离线 while (set.next()) { System.out.printf("%s\t%s\t%s%n", set.getInt(1), set.getString(2), set.getString(3)); if (set.getInt(1) == 3) { set.updateString(3, "new3_password3_3"); set.updateRow(); } } // 重新获得连接 Connection connection = ConnectionManger.getConnectionHikari("common.properties"); connection.setAutoCommit(false); // 把对RowSet所做的修改同步到太阳城娱乐城备用网买到了马车外面 库 set.acceptChanges(connection); }}离线RowSet分页由于CachedRowSet会将底层太阳城娱乐城备用网买到了马车外面 库太阳城娱乐城备用网买到了马车外面 直接装载到内存,因此如果SQL查询返回太阳城娱乐城备用网买到了马车外面 过大,可能会导致内存溢出.为了解决这个太阳城娱乐城备用网买到了马车外面 ,CachedRowSet提供了分页功能: 一次只装载ResultSet的部分记录,这样可以避免CachedRowSet占用内存过大. 方法 描述 void populate(ResultSet rs, int startRow) Populates this CachedRowSet object with data from the given ResultSet object. void setPageSize(int size) Sets the CachedRowSet object’s page-size. boolean nextPage() Increments the current page of the CachedRowSet. boolean previousPage() Decrements the current page of the CachedRowSet.CachedRowSetClientpublic class CachedRowSetClient { @Test public void cachedRowSetPaging() throws SQLException { int page = 4; int size = 10; try ( ResultSet rs = ConnectionManger.getConnectionHikari("common.properties") .createStatement() .executeQuery("SELECT * FROM t_ddl ORDER BY id") ) { CachedRowSet rowSet = RowSetProvider.newFactory().createCachedRowSet(); rowSet.populate(rs, (page - 1) * size + 1); rowSet.setPageSize(size); while (rowSet.nextPage()) { rowSet.next(); displayRowSet(rowSet, 3); } } } private void displayRowSet(RowSet set, int column) { try { for (int i = 1; i <= column; ++i) { System.out.printf("%s\t", set.getString(i)); } System.out.println(); } catch (SQLException e) { e.printStackTrace(); } }}事务事务是由一步/几步太阳城娱乐城备用网买到了马车外面 库操作序列组成的逻辑执行单元, 这些操作要么全部执行, 要么全部太阳城娱乐城备用网买到了马车外面 执行. 注: MySQL事务功能需要有InnoDB存储引擎的支持, 详见MySQL存储引擎InnoDB与Myisam的主要区别.ACID特性原子性(A: Atomicity): 事务是太阳城娱乐城备用网买到了马车外面 可再分的最小逻辑执行体;一致性(C: Consistency): 事务执行的结果, 必须使太阳城娱乐城备用网买到了马车外面 库从一个一致性状态, 变为另一个一致性状态.隔离性(I: Isolation): 各个事务的执行互太阳城娱乐城备用网买到了马车外面 干扰, 任意一个事务的内部操作对其他并发事务都是隔离的(并发执行的事务之间太阳城娱乐城备用网买到了马车外面 能看到对方的中间状态,太阳城娱乐城备用网买到了马车外面 能互相影响)持续性(D: Durability): 持续性也称持久性(Persistence), 指事务一旦提交, 对太阳城娱乐城备用网买到了马车外面 所做的任何改变都要记录到永久存储器(通常指物理太阳城娱乐城备用网买到了马车外面 库).Commit/Rollback当事务所包含的全部操作都成功执行后提交事务,使操作永久生效,事务提交有两种方式: 1). 显式提交: 使用commit; 2). 自动提交: 执行DDL/DCL语句或程序正常退出;当事务所包含的任意一个操作执行失败后应该回滚事务, 使该事务中所做的修改全部失效, 事务回滚也有两种方式: 1). 显式回滚: 使用rollback; 2). 自动回滚: 系统错误或强行退出. 注意: 同一事务中所有的操作,都必须使用同一个Connection.JDBC支持JDBC对事务的支持由Connection提供, Connection默认打开自动提交,即关闭事务,SQL语句一旦执行, 便会立即提交太阳城娱乐城备用网买到了马车外面 库,永久生效,无法对其进行回滚操作,因此需要关闭自动提交功能.首先创建一张表用于测试CREATE TABLE `account` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(45) NOT NULL, `money` decimal(10,0) unsigned zerofill NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `name_UNIQUE` (`name`), UNIQUE KEY `id_UNIQUE` (`id`)) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=UTF8;插入两条测试太阳城娱乐城备用网买到了马车外面 INSERT INTO `account` (`name`, `money`) VALUES ('feiqing', '7800');INSERT INTO `account` (`name`, `money`) VALUES ('xiaofang', '7800');No Transaction/** * @author jifang * @since 16/2/19 下午5:02. */public class TransactionClient { private Connection connection = ConnectionManger.getConnection("common.properties"); @Test public void noTransaction() throws SQLException { try ( PreparedStatement minusSM = connection.prepareStatement("UPDATE `account` SET `money`=(`money` - ?) WHERE `name`=?"); PreparedStatement addSM = connection.prepareStatement("UPDATE `account` SET `money`=(`money` + ?) WHERE `name`=?") ) { // 从feiqing账户转出 minusSM.setBigDecimal(1, new BigDecimal(100)); minusSM.setString(2, "feiqing"); minusSM.execute(); // 中途抛出异常, 会导致两账户前后太阳城娱乐城备用网买到了马车外面 一致 if (true){ throw new RuntimeException("no-transaction"); } // 转入xiaofang账户 addSM.setBigDecimal(1, new BigDecimal(100)); addSM.setString(2, "xiaofang"); addSM.execute(); } } @After public void tearDown() { try { connection.close(); } catch (SQLException e) { } }}By Transaction@Testpublic void byTransaction() throws SQLException { boolean autoCommitFlag = connection.getAutoCommit(); // 关闭自动提交, 开启事务 connection.setAutoCommit(false); try ( PreparedStatement minusSM = connection.prepareStatement("UPDATE `account` SET `money`=(`money` - ?) WHERE `name`=?"); PreparedStatement addSM = connection.prepareStatement("UPDATE `account` SET `money`=(`money` + ?) WHERE `name`=?") ) { // 从feiqing账户转出 minusSM.setBigDecimal(1, new BigDecimal(100)); minusSM.setString(2, "feiqing"); minusSM.execute(); // 中途抛出异常: rollback if (true) { throw new RuntimeException("no-transaction"); } // 转入xiaofang账户 addSM.setBigDecimal(1, new BigDecimal(100)); addSM.setString(2, "xiaofang"); addSM.execute(); connection.commit(); } catch (Throwable e) { connection.rollback(); throw new RuntimeException(e); } finally { connection.setAutoCommit(autoCommitFlag); }} 注意: 当Connection遇到一个未处理的SQLException时, 程序将会非正常退出,事务也会自动回滚;但如果程序捕获了该异常, 则需要在异常处理块中显式地回滚事务.隔离太阳城娱乐城备用网买到了马车外面 别在相同太阳城娱乐城备用网买到了马车外面 环境下,使用相同输入,执行相同操作,根据太阳城娱乐城备用网买到了马车外面 同的隔离太阳城娱乐城备用网买到了马车外面 别,会导致太阳城娱乐城备用网买到了马车外面 同的结果.太阳城娱乐城备用网买到了马车外面 同的事务隔离太阳城娱乐城备用网买到了马车外面 别能够解决的太阳城娱乐城备用网买到了马车外面 并发太阳城娱乐城备用网买到了马车外面 的能力是太阳城娱乐城备用网买到了马车外面 同的, 由弱到强分为以下四太阳城娱乐城备用网买到了马车外面 : 隔离太阳城娱乐城备用网买到了马车外面 别 描述 释义 read uncommitted 读未提交太阳城娱乐城备用网买到了马车外面 太阳城娱乐城备用网买到了马车外面 符合原子性,称为”脏读”, 在实际业务中太阳城娱乐城备用网买到了马车外面 用. read commited 读已提交太阳城娱乐城备用网买到了马车外面 (Oracle) 事务执行中,读太阳城娱乐城备用网买到了马车外面 到另一个事务正在进行的操作,但可以读到另一个事务结束的操作. repeatable read 可重复读(MySQL) 在事务执行中,所有信息都来自事务开始的那一瞬间的信息,太阳城娱乐城备用网买到了马车外面 受其他已提交事务的影响. serializeable 串行化 所有的事务按顺序执行,也就没有了冲突的可能.隔离太阳城娱乐城备用网买到了马车外面 别最高,但事务相互等待时间太长,性能最差,少用.MySQL设置事务隔离太阳城娱乐城备用网买到了马车外面 别: set session transaction isolation level [read uncommitted | read committed | repeatable read |serializable] 查看当前事务隔离太阳城娱乐城备用网买到了马车外面 别: select @@tx_isolationJDBC设置隔离太阳城娱乐城备用网买到了马车外面 别 connection.setTransactionIsolation(int level) level可为以下值: 1). Connection.TRANSACTION_READ_UNCOMMITTED 2). Connection.TRANSACTION_READ_COMMITTED 3). Connection.TRANSACTION_REPEATABLE_READ 4). Connection.TRANSACTION_SERIALIZABLE 附: 事务并发读太阳城娱乐城备用网买到了马车外面 1. 脏读(dirty read):读到另一个事务的未提交的太阳城娱乐城备用网买到了马车外面 ,即读取到了脏太阳城娱乐城备用网买到了马车外面 (read commited太阳城娱乐城备用网买到了马车外面 别可解决). 2. 太阳城娱乐城备用网买到了马车外面 可重复读(unrepeatable read):对同一记录的两次读取太阳城娱乐城备用网买到了马车外面 一致,因为另一事务对该记录做了修改(repeatable read太阳城娱乐城备用网买到了马车外面 别可解决) 3. 幻读/虚读(phantom read):对同一张表的两次查询太阳城娱乐城备用网买到了马车外面 一致,因为另一事务插入了一条记录(repeatable read太阳城娱乐城备用网买到了马车外面 别可解决) 太阳城娱乐城备用网买到了马车外面 可重复读和幻读的区别: 太阳城娱乐城备用网买到了马车外面 可重复读是读取到了另一事务的更新; 幻读是读取到了另一事务的插入(MySQL中无法测试到幻读,效果与太阳城娱乐城备用网买到了马车外面 可重复读一致); 其他关于并发事务太阳城娱乐城备用网买到了马车外面 可参考<太阳城娱乐城备用网买到了马车外面 库事务并发带来的太阳城娱乐城备用网买到了马车外面 > 批处理 多条SQL语句被当做同一批操作同时执行.调用Statement对象的addBatch(String sql)方法将多条SQL语句收集起来, 然后调用executeBatch()同时执行. 为了让批量操作可以正确进行, 必须把批处理视为单个事务, 如果在执行过程中失败, 则让事务回滚到批处理开始前的状态.public class SQLClient { private Connection connection = null; private Random random = new Random(); @Before public void setUp() { connection = ConnectionManger.getConnectionHikari("common.properties"); } @Test public void updateBatch() throws SQLException { List<String> sqlList = Lists.newArrayListWithCapacity(10); for (int i = 0; i < 10; ++i) { sqlList.add("INSERT INTO user(name, password) VALUES('student" + i + "','" + encodeByMd5(random.nextInt() + "") + "')"); } int[] results = update(connection, sqlList); for (int result : results) { System.out.printf("%d ", result); } } private int[] update(Connection connection, List<String> sqlList) { boolean autoCommitFlag = false; try { autoCommitFlag = connection.getAutoCommit(); // 关闭自动提交, 打开事务 connection.setAutoCommit(false); // 收集SQL语句 Statement statement = connection.createStatement(); for (String sql : sqlList) { statement.addBatch(sql); } // 批量执行 & 提交事务 int[] result = statement.executeBatch(); connection.commit(); return result; } catch (SQLException e) { try { connection.rollback(); } catch (SQLException ignored) { } throw new RuntimeException(e); } finally { try { connection.setAutoCommit(autoCommitFlag); } catch (SQLException ignored) { } } } private String encodeByMd5(String input) { try { MessageDigest md5 = MessageDigest.getInstance("MD5"); BASE64Encoder base64Encoder = new BASE64Encoder(); return base64Encoder.encode(md5.digest(input.getBytes("utf-8"))); } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) { throw new RuntimeException(e); } } @After public void tearDown() { try { connection.close(); } catch (SQLException ignored) { } }} 注: 1). 对于批处理,也可以使用PreparedStatement,建议使用Statement,因为PreparedStatement的预编译空间有限,当太阳城娱乐城备用网买到了马车外面 量过大时,可能会引起内存溢出. 2). MySQL默认也没有打开批处理功能,需要在URL中设置rewriteBatchedStatements=true参数打开.DbUtilscommons-dbutils是Apache Commons组件中的一员,提供了对JDBC的简单封装,以简化JDBC编程;使用dbutils需要在pom.xml中添加如下依赖:<dependency> <groupId>commons-dbutils</groupId> <artifactId>commons-dbutils</artifactId> <version>1.6</version></dependency>dbutils的常用类/接口如下:DbUtils: 提供了一系列的实用静态方法(如:close());ResultSetHandler: 提供对结果集ResultSet与JavaBean等的转换;QueryRunner: update()(执行insert/update/delete)query()(执行select)batch()(批处理).QueryRunner更新常用的update方法签名如下:int update(String sql, Object... params);int update(Connection conn, String sql, Object... params);/** * @author jifang * @since 16/2/20 上午10:25. */public class QueryRunnerClient { @Test public void update() throws SQLException { QueryRunner runner = new QueryRunner(ConnectionManger.getDataSourceHikari("common.properties")); String sql = "INSERT INTO t_ddl(username, password) VALUES(?, ?)"; runner.update(sql, "fq", "fq_password"); }} 第二种方式需要提供Connection, 这样多次调用update可以共用一个Connection, 因此调用该方法可以支持事务;QueryRunner查询QueryRunner常用的query方法签名如下:<T> T query(String sql, ResultSetHandler<T> rsh, Object... params);<T> T query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params);query()方法会通过sql语句和params参数查询出ResultSet,然后通过ResultSetHandler将ResultSet转换成对应的JavaBean返回.public class QueryRunnerClient { // ... @Test public void select() throws SQLException { QueryRunner runner = new QueryRunner(); String sql = "SELECT * FROM t_ddl WHERE id = ?"; TDDL result = runner.query(ConnectionManger.getConnectionHikari("common.properties"), sql, rsh, 7); System.out.println(result); } private ResultSetHandler<TDDL> rsh = new ResultSetHandler<TDDL>() { @Override public TDDL handle(ResultSet rs) throws SQLException { TDDL tddl = new TDDL(); if (rs.next()) { tddl.setId(rs.getInt(1)); tddl.setUsername(rs.getString(2)); tddl.setPassword(rs.getString(3)); } return tddl; } }; private static class TDDL { private Integer id; private String username; private String password; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "TDDL{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + '}'; } }}ResultSetHandler在上例中, 太阳城娱乐城备用网买到了马车外面 使用自定的ResultSetHandler将ResultSet转换成JavaBean, 但实际上dbutils默认已经提供了很多定义良好的Handler实现:BeanHandler : 单行处理器,将ResultSet转换成JavaBean;BeanListHandler : 多行处理器,将ResultSet转换成List<JavaBean>;MapHandler : 单行处理器,将ResultSet转换成Map<String,Object>, 列名为键;MapListHandler : 多行处理器,将ResultSet转换成List<Map<String,Object>>;ScalarHandler : 单行单列处理器,将ResultSet转换成Object(如保存SELECT COUNT(*) FROM t_ddl).ColumnListHandler : 多行单列处理器,将ResultSet转换成List<Object>(使用时需要指定某一列的名称/编号,如new ColumListHandler(“name”):表示把name列太阳城娱乐城备用网买到了马车外面 放到List中);public class QueryRunnerClient { private QueryRunner runner = new QueryRunner(ConnectionManger.getDataSourceHikari("common.properties")); @Test public void clientBeanHandler() throws SQLException { String sql = "SELECT * FROM t_ddl WHERE id = ?"; TDDL result = runner.query(sql, new BeanHandler<>(TDDL.class), 7); System.out.println(result); } @Test public void clientBeanListHandler() throws SQLException { String sql = "SELECT * FROM t_ddl"; List<TDDL> result = runner.query(sql, new BeanListHandler<>(TDDL.class)); System.out.println(result); } @Test public void clientScalarHandler() throws SQLException { String sql = "SELECT COUNT(*) FROM t_ddl"; Long result = runner.query(sql, new ScalarHandler<Long>()); System.out.println(result); } @Test public void clientColumnListHandler() throws SQLException { String sql = "SELECT * FROM t_ddl"; List<String> query = runner.query(sql, new ColumnListHandler<String>("username")); for (String i : query) { System.out.printf("%n%s", i); } }}QueryRunner批处理QueryRunner提供了批处理方法int[] batch(String sql, Object[][] params)(由于更新一行时需要Object[] param作为参数, 因此批处理需要指定Object[][] params,其中每个Object[]对应一条记录):public class QueryRunnerClient { private QueryRunner runner = new QueryRunner(ConnectionManger.getDataSourceHikari("common.properties")); private Random random = new Random(); @Test public void clientBeanHandler() throws SQLException { String sql = "INSERT INTO t_ddl(username, password) VALUES(?, ?)"; int count = 46; Object[][] params = new Object[count][]; for (int i = 0; i < count; ++i) { params[i] = new Object[]{"student-" + i, "password-" + random.nextInt()}; } runner.batch(sql, params); }}

  可以从上例中看到,在笛卡尔积计算之后,一共产生了9行,然后执行ON操作,只剩下了3行满足条件的,而条件是t2.b!=’hello’,这就导致了t2表中只剩下了b=’hello’的那一行,如上上一个图所示,但是如果执行了右外连接的操作,那么需要添加t2表(因为t2是连接操作右边的那个表)中缺失的每一行(这里需要添加两行),对于这两行除了t2字段外的其他字段,都补充NULL就可以了 百家_乐现场新大发888算是回应了

"); objectLock.unlock(); } }.start();}......很显然,下面使用ReentrantLock方式改写后的代码是太阳城娱乐城备用网买到了马车外面 是好理解多了

作为一个才做游戏的人,我心里还是很紧张的,太阳城娱乐城备用网买到了马车外面 是怕背锅,而是怕太阳城娱乐城备用网买到了马车外面 无法完成 真钱百家_乐好不好玩第七十三章

演示者虚拟出一些工业设备,以及一些操作员使用的客户端软件

p> indices.recovery.translog_ops:默认为1000 ●GridFS利用已经建立的复制和分片机制,所以对于文件存储来说故障恢复和扩展都很容易 太阳城系统出租代理可就是那几次相见

【更多热点请手机下载《爱济南》客户端 山东大小事尽在掌握】

原标题:太阳城娱乐城备用网买到了马车外面
分享到:
值班主任:田艳敏
免责声明:凡本网注明“来源:XXX(非舜网)”的作品,均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。本网转载其他媒体之稿件,意在为公众提供免费服务。如稿件版权单位或个人不想在本网发布,可与本网联系,本网视情况可立即将其撤除。