批处理和元数据

发表时间:2017-05-11 16:54:29 浏览量( 15 ) 留言数( 0 )

学习目标:

1、了解Java的历史

2、为什么要学习Java语言

3、端正学习态度


学习过程:

一、批处理

1、为什么需要使用批处理

JDBC驱动的最佳化是基于使用的是什么功能. 选择PreparedStatement还是Statement取决于你要怎么使用它们. 对于只执行一次的SQL语句选择Statement是最好的. 相反, 如果SQL语句被多次执行选用PreparedStatement是最好的。但是executeUpdate一次执行大量的数据时, 先Prepare一个INSERT语句再多次的执行, 会导致很多次的网络连接. 要减少JDBC的调用次数改善性能, 你可以使用PreparedStatement的AddBatch()方法一次性发送多个查询给数据库。

2、示例对比

(1)不是使用批处理

public void addUserTest2(List<User> users) {
		String sql = "insert into tb_user(user_name,user_pass) values(?,?)";
		try {
			getCon();
			preparedStatement = connection.prepareStatement(sql);
			for (User user : users) {
                preparedStatement.setString(1, user.getUserName());
                preparedStatement.setString(2, user.getUserPass());
				preparedStatement.executeUpdate();
			}


		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			closeAll();
		}
	}

在main方法中调用这个方法,测试一下所有的时间,我自己测试大于30秒左右

	public static void main(String[] args) {
		UserDao userDao = new UserDao();

		List<User> users = new ArrayList<User>();
		for (int i = 0; i < 100; i++) {
			User user1 = new User();
			user1.setUserName("dddd");
			user1.setUserPass("123");
			users.add(user1);
		}
	
		Date bdate = new Date();
		userDao.addUserTest2(users);
		Date edate = new Date();
		System.out.println((edate.getTime() - bdate.getTime()) + "毫秒");//
	}

(2)使用批处理

修改上面的实现方法。代码如下:

public void addUserTest2(List<User> users) {
		String sql = "insert into tb_user(user_name,user_pass) values(?,?)";
		try {
			getCon();
			// 自动提交功能关闭
			connection.setAutoCommit(false);
			preparedStatement = connection.prepareStatement(sql);
			for (User user : users) {
                preparedStatement.setString(1, user.getUserName());
                preparedStatement.setString(2, user.getUserPass());
				// preparedStatement.executeUpdate();
				preparedStatement.addBatch();
			}

			preparedStatement.executeBatch();

			// 手动提交
			connection.commit();

		} catch (Exception e) {
			try {
				connection.rollback();// 回滚
			} catch (SQLException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			e.printStackTrace();
		} finally {
			closeAll();
		}
	}

还是使用上面的main测试方法,大于0.5秒,不使用事务和批处理时需要30秒,可见效率提高了很多。

二、元数据

jdbc到了版本3以后加入元数据的功能,元数据就可以很方便的获取数据库相关的信息,如果大家想要获得连接数据库的基本信息可以使用读取数据库元数据的方式,或者大家想要封装一些底层的数据库访问方法时也可以使用元数据进行封装。

示例代码如下:

 // 查询全部 元数据
public List<User> getAllUser() {
    List<User> users = new ArrayList<User>();
    try {
        // 1、建立连接
        getCon();
        java.sql.DatabaseMetaData dbmd = connection.getMetaData();
        System.out.println("数据库产品名: " + dbmd.getDatabaseProductName());
        System.out.println("数据库是否支持事务: " + dbmd.supportsTransactions());
        System.out.println("数据库产品的版本号:" + dbmd.getDatabaseProductVersion());
        System.out.println("数据库的默认事务隔离级别:" + dbmd.getDefaultTransactionIsolation());
        System.out.println("支持批量更新:" + dbmd.supportsBatchUpdates());
        System.out.println("DBMS 的 URL:" + dbmd.getURL());
        System.out.println("数据库的已知的用户名称:" + dbmd.getUserName());
        System.out.println("数据库是否处于只读模式:" + dbmd.isReadOnly());
        System.out.println("数据库是否支持为列提供别名:" + dbmd.supportsColumnAliasing());
        System.out.println("是否支持指定 LIKE 转义子句:" + dbmd.supportsLikeEscapeClause());
        System.out.println("是否为外连接提供受限制的支持:" + dbmd.supportsLimitedOuterJoins());
        System.out.println("是否允许一次打开多个事务:" + dbmd.supportsMultipleTransactions());
        System.out.println("是否支持 EXISTS 表达式中的子查询:"
        + dbmd.supportsSubqueriesInExists());
        System.out.println("是否支持 IN 表达式中的子查询:" + dbmd.supportsSubqueriesInIns());
        System.out.println("是否支持给定事务隔离级别:"
        + dbmd.supportsTransactionIsolationLevel(1));
        System.out.println("此数据库是否支持事务:" + dbmd.supportsTransactions());
        System.out.println("此数据库是否支持 SQL UNION:" + dbmd.supportsUnion());
        System.out.println("此数据库是否支持 SQL UNION ALL:" + dbmd.supportsUnionAll());
        System.out.println("此数据库是否为每个表使用一个文件:" + dbmd.usesLocalFilePerTable());
        System.out.println("此数据库是否将表存储在本地文件中:" + dbmd.usesLocalFiles());
        System.out.println("底层数据库的主版本号:" + dbmd.getDatabaseMajorVersion());
        System.out.println("底层数据库的次版本号:" + dbmd.getDatabaseMinorVersion());
        String sql = "select * from tb_user";
        preExe(sql, null);
        resultSet = preparedStatement.executeQuery();
        // 获得数据库信息 元数据
        System.out.println("获得数据库的名称:"
        + resultSet.getMetaData().getCatalogName(1));
        System.out.println("表名称:" + resultSet.getMetaData().getTableName(1));
        System.out.println("表的各个字段:"+ resultSet.getMetaData().getColumnName(1));
        System.out.println("表的各个字段:"+ resultSet.getMetaData().getColumnName(2));
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        closeAll();
    }
    return users;
}

三、把连接信息写在配置文件中

我们把连接信息写在代码中,如下:

private String driver = "com.mysql.jdbc.Driver";
private String url = "jdbc:mysql://192.168.11.144/first?useUnicode=true&characterEncoding=utf8";
private String dbusername = "root";
private String dbpass = "123456";

如果用户需要修改数据库密码,这应该是一个很常见的操作,这样的话就需要修改源代码,然后重新编译打包了。会很麻烦,所以建议大家把这些信息写在配置文件中。在src下新建一个jdbc.properties。内容如下:

driver = com.mysql.jdbc.Driver
url = jdbc:mysql://192.168.11.144/first?useUnicode=true&characterEncoding=utf8
dbusername = root
dbpass =123456

读取配置文件只需要读取一次哦,所以你可以把上面的变量都定义为static静态,而且不需要初始化数据库了。直接读取配置文件即可。

static {
	Properties properties = new Properties();
	try {
		properties.load(BaseDao.class.getClassLoader().getResourceAsStream(
					"jdbc.properties"));
		driver = properties.getProperty("driver");
		url = properties.getProperty("url");
		dbusername = properties.getProperty("dbusername");
		dbpass = properties.getProperty("dbpass");
	} catch (IOException e) {
		e.printStackTrace();
	}

}