2.1 使用配置文件读取需要的参数
2.1.1 为什么要使用配置文件?
数据库类型、账户等等信息发生变化只需要修改配置文件,而不用修改代码。同时为了让只注册一次驱动,可以将读取配置文件的代码写到JDBC工具类的静态代码块中。
static{
Class jdbcClass=JdbcUtil.class;
InputStream resourceAsStream = jdbcClass.getResourceAsStream("/jdbc.properties");
URL resource = jdbcClass.getResource("/jdbc.properties");
Properties properties=new Properties();
try {
properties.load(resourceAsStream);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
url=properties.getProperty("url");
user=properties.getProperty("user");
password=properties.getProperty("password");
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
2.1.2 Class.getResourceAsStream
为什么要使用Class.getResourceAsStream获得配置文件地址?
如果配置文件放在工程项目src目录,当我们让工具类在Web项目和普通JAVA项目中使用的时候,使用相对路径得到配置文件会出错,不符合JAVA一次成型的精神。因此使用getResourceAsStream,在两种项目来回切换也不会出现问题。
2.2 批处理
2.2.1 什么是批处理?
当需要向数据库发送大量SQL语句的时候,一条条发送,效率会很低,这时候使用批处理的话,可以提高效率。
2.2.2 使用批处理
addBatch()加入批处理
executeBatch()执行批处理
clearBatch()清理批处理
2.2.3 Statement下的批处理
private static void StatementWithBatch() {
Connection connection=null;
Statement createStatement=null;
try {
connection=JdbcUtil.getConnection();
createStatement=connection.createStatement();
for(int i=0;i<2000;i++){
createStatement.addBatch("INSERT INTO student(NAME,age,gender) VALUES('小铭',19,'男');");
if(i%20==0){
createStatement.executeBatch();
createStatement.clearBatch();
}
}
} catch (Exception e) {
// TODO: handle exception
}
}
private static void Statement() {
Connection connection = null;
Statement createStatement = null;
try {
connection=JdbcUtil.getConnection();
createStatement = connection.createStatement();
for(int i=0;i<2000;i++){
createStatement.executeUpdate("INSERT INTO student(NAME,age,gender) VALUES('小铭',19,'男');");
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally {
JdbcUtil.close(createStatement, connection);
}
}
运行结果StatementWithBatch使用时间5188 ,Statement使用时间4761,可见Mysql对于executeBatch没有优化,依旧是一句一句执行,但是如果我们使用oracle会看到StatementWithBatch效率明显提高。
2.2.3 PrepareStatement下的批处理
private static void PrepareStatement() {
Connection connection=null;
PreparedStatement createStatement=null;
try {
connection=JdbcUtil.getConnection();
createStatement=connection.prepareStatement("INSERT INTO student(NAME,age,gender) VALUES('小铭',19,'男');");
for(int i=0;i<2000;i++){
createStatement.executeUpdate();
}
} catch (Exception e) {
// TODO: handle exception
}
}
private static void PrepareStatementWithBatch() {
Connection connection=null;
PreparedStatement createStatement=null;
try {
connection=JdbcUtil.getConnection();
createStatement=connection.prepareStatement("INSERT INTO student(NAME,age,gender) VALUES('小铭',19,'男');");
for(int i=0;i<2000;i++){
createStatement.addBatch();
if(i%20==0){
createStatement.executeBatch();
createStatement.clearBatch();
}
}
} catch (Exception e) {
// TODO: handle exception
}
}
运行结果:PrepareStatement使用时间4496,PrepareStatementWithBatch使用时间4501,同样的我们发现MySql中PrepareStatement也没有进行批处理优化。
2.2.4 Statement与PrepareStatement批处理的对比
PrepareStatement:发送的是预编译SQL语句,效率高,但是只能发送参数不同但是语句相同的SQL语句。
Statement:可以发送多条不同的SQL语句,但是效率相对较慢。
通过以上对比,同时也发现MYSQL没有library cache类似的组件,所以性能上几乎没有提高。
2.3 实例-在数据库存放文件
private static void writeFile() {
Connection connection=null;
PreparedStatement prepareStatement=null;
try {
connection=JdbcUtil.getConnection();
prepareStatement = connection.prepareStatement("INSERT INTO attachments(NAME,FILE,author,saveTime) VALUES(?,?,?,?);");
BufferedInputStream bufferedInputStream=new BufferedInputStream(new FileInputStream("D:\\1.exe"));
prepareStatement.setString(1, "1.exe");
prepareStatement.setBlob(2, bufferedInputStream);
prepareStatement.setString(3, "安装包");
prepareStatement.setDate(4, new Date(System.currentTimeMillis()));
prepareStatement.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}
finally {
//关闭资源
JdbcUtil.close(prepareStatement, connection);
}
}
- 值得注意的是对于Bolb,无论写入还是读出,都要使用流。
- 当提示文件太大的时候,可以到mysql下修改配置文件,让每次传输的数据大小增大。
- 设置Date类时,要使用SQL包下的DATE类。