1,jdbc连接比较耗时?

public class demo {
	public static void main(String[] args) {
		try {
			//加载驱动类
			Class.forName("com.mysql.jdbc.Driver");
			/**建立连接*/
			long start=System.currentTimeMillis();
			Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8","root","zzj234812");
			long end =System.currentTimeMillis();
			System.out.println(conn);
			System.out.println("建立连接耗时"+(end-start)+"ms");
			
		} catch (ClassNotFoundException | SQLException e){
			e.printStackTrace();
		}
	}
}

运行结果让人惊讶:

com.mysql.cj.jdbc.ConnectionImpl@7a30d1e6 建立连接耗时1447ms

连接对象内部其实包含了Socket对象,是一个远程的连接接,比较耗时!这是Connection对象管理的一个特点。实际开发中,为了提高效率,都会使用连接池来管理连接对象。

2,测试执行SQL语句及注入问题

public class demoa {
	public static void main(String[] args) {
		Connection conn=null;
		Statement stmt =null;
		try {
			//加载驱动类
			Class.forName("com.mysql.jdbc.Driver");
			//建立连接
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8","root","zzj234812");
			
			stmt = conn.createStatement();//实际工作中用的很少,传参数只能用拼字符串的方式操作,
			String name="赵奎";//处理参数很不方便,而且使用Statement容易发生SQL注入的危险
			String sql = "insert into stu_table (name,pwd,date) values ('"+name+"',58585,now())";
		    stmt.execute(sql);
			//测试SQL注入,这样一直为true,删除数据直至为空
//			String id="2 or 1=1";
//			String sql ="delete from stu_table where id="+id;
//			stmt.execute(sql);
		} catch (ClassNotFoundException e){
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}finally {
				try {
					if(stmt!=null) {
						stmt.close();
					}
				} catch (SQLException e) {
					e.printStackTrace();
				}try {
					if(conn!=null) {
						conn.close();
					}
				} catch (Exception e) {
			}
		}
	}
}

3,测试Statement接口的用法,执行SQL语句,以及SQL注入问题

public class demob {
	public static void main(String[] args) {
		Connection conn =null;
		PreparedStatement ps=null;
		try {
			//加载驱动类
			Class.forName("com.mysql.jdbc.Driver");
			//建立连接
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8","root","zzj234812");
			
			String sql="insert into stu_table (name,pwd) values (?,?)";//?表示传的必须是数字/字符串/时间占位符,预处理机制避免SQL注入
			//继承自Statement接口,比Statement效率更高且可以防止SQL注入
			ps=conn.prepareStatement(sql);
			
			//方法一
//			ps.setString(1, "李四");//参数索引从1开始算
//			ps.setString(2, "1111");
			
			//方法二,可以使用setObject方法处理参数,避免了字符串类型问题
			ps.setObject(1, "张吴");
			ps.setObject(2, "69898");
			
			System.out.println("插入记录");
//			ps.execute();
			int count = ps.executeUpdate();//返回的是一个数,更新和影响了多少条记录
			System.out.println(count);
				} catch (ClassNotFoundException e){
					e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}finally {
			try {
				if(ps!=null) {
					ps.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
			try {
				if(conn!=null) {
					conn.close();
				}
			} catch (Exception e) {
		}
	  }
	}
}

4,测试ResultSet基本用法

public class democ {
	public static void main(String[] args) {
		Connection conn =null;
		PreparedStatement ps=null;
		ResultSet rs=null;
		try {
			//加载驱动类
			Class.forName("com.mysql.jdbc.Driver");
			//建立连接
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8","root","zzj234812");
			
			String sql="select id,name,pwd from stu_table where id>?";//?表示传的必须是数字/字符串/时间占位符,预处理机制避免SQL注入
			//继承自Statement接口,比Statement效率更高且可以防止SQL注入
			ps=conn.prepareStatement(sql);
			ps.setObject(1, 2);//把id大于2的记录取出来
			
			rs=ps.executeQuery();
			while(rs.next()) {//通过这种方式可将遍历的结果全取出来,ResultSet经典使用方式
				System.out.println(rs.getInt(1)+"--"+rs.getString(2)+"--"+rs.getInt(3));
			}
			
		} catch (ClassNotFoundException e){
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			
			//关闭顺序遵循从ResultSet-->statement-->connection这样的关闭顺序!一定要将三个trycatch块分开写
				try {
					if (rs!=null)
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}try {
					if(ps!=null) {
						ps.close();
					}
				} catch (SQLException e) {
					e.printStackTrace();
				}
				try {
					if(conn!=null) {
						conn.close();
					}
				} catch (Exception e) {
			}
		}
	}
}

5,插入10000条数据,怎么提高效率?用Batch?

public class demod {
	public static void main(String[] args) {
		Connection conn =null;
		Statement stmt=null;
		ResultSet rs=null;
		try {
			Class.forName("com.mysql.jdbc.Driver");
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8","root","zzj234812");
			
			conn.setAutoCommit(false);//设为手动提交
			long start=System.currentTimeMillis();
			stmt=conn.createStatement();//创建Statement对象
			
			for(int i=0;i<10000;i++) {
				stmt.addBatch("insert into stu_table (name,pwd,date) values ('张"+i+"',8888,now())");
			}
			stmt.executeBatch();
			conn.commit();//提交事务
			long end=System.currentTimeMillis();
			System.out.println("插入10000条数据,耗时:"+(end-start)+"ms毫秒");
			
		} catch (ClassNotFoundException e){
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{//关闭顺序遵循从ResultSet-->statement-->connection这样的关闭顺序!一定要将三个trycatch块分开写
				try {
					if (rs!=null)
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}try {
					if(stmt!=null) {
						stmt.close();
					}
				} catch (SQLException e) {
					e.printStackTrace();
				}
				try {
					if(conn!=null) {
						conn.close();
					}
				} catch (Exception e) {
			}
		}
	}
}

结果如下

image.png image.png

用时:插入10000条数据,耗时:5207ms毫秒

注意:

1,建议使用statement,因为PreparedStatement的预编译空间有限,当数据量特别大时会发生异常。

2,jdbc事务操作改成false,设成手动提交。

批量删除/修改/插入数据时,使用Batch可以提高效率。