数据句连接被用于向数据库服务器发送命令和sql语句,并接受数据库服务器返回的结果,其实一个数据库连接就是一个Socket连接 在java.sql包中有3个接口分别定义了对数据库的调用的不同方式: Statement:用于执行静态SQL语句并返回所生成结果的对象 PreparedStatement:是Statement的一个子接口,表示一条预编译的sql语句,SQL语句被预编译并存储在此对象中,可以使用此对象多次高效的执行该语句 CallableStatement:用于执行SQL存储过程
getColumnName()方法:有别名则获取别名 getColumnLabel()方法:获取列名 ORM编程思想:
一个数据库对应一个java类表中的一条记录对应java类的一个对象表中的一个字段对应java类的一个属性通用查询方法:
/** * 通用查询方法 */ public static <T> T queryForObject(String sql, Class<T> clazz, Object... args) throws Exception { Connection connection = getConnection(); PreparedStatement ps = connection.prepareStatement(sql); //设置占位符 for (int i = 0; i < args.length; i++) { ps.setObject(i + 1, args[i]); } ResultSet result = ps.executeQuery(); ResultSetMetaData metaData = result.getMetaData(); int count = metaData.getColumnCount(); T t = null; if (result.next()) { t = clazz.getDeclaredConstructor().newInstance(); for (int i = 0; i < count; i++) { Field field = clazz.getDeclaredField(metaData.getColumnLabel(i + 1)); field.setAccessible(true); field.set(t, result.getObject(i + 1)); } } return t; }通用查询方法:
/** * 通用查询方法 */ public static <T> List<T> queryForObjectList(String sql, Class<T> clazz, Object... args) throws Exception { Connection connection = getConnection(); PreparedStatement ps = connection.prepareStatement(sql); if(args.length > 0) { //设置占位符 for (int i = 0; i < args.length; i++) { ps.setObject(i + 1, args[i]); } } ResultSet result = ps.executeQuery(); ResultSetMetaData metaData = result.getMetaData(); int count = metaData.getColumnCount(); T t = null; List<T> list = new ArrayList<>(); while (result.next()) { t = clazz.getDeclaredConstructor().newInstance(); for (int i = 0; i < count; i++) { Field field = clazz.getDeclaredField(metaData.getColumnLabel(i + 1)); field.setAccessible(true); field.set(t, result.getObject(i + 1)); } list.add(t); } return list; }PreparedStatement的好处: 解决sql拼串,sql注入问题,可以插入blob数据 可以实现更高效的批量插入
两种思想:
面向接口编程思想ORM思想 一个数据表对应一个java类表中的一条记录对应java类的一个对象表中的一个字段对应java类的一个属性两种技术:
JDBC结果集的元数据:ResultMetaData 获取列数:getColumnCount()获取列的别名:getColumnLabel() 通过反射,创建指定类的对象,获取指定的属性并赋值mysql中,blob是一个二进制大型对象,是一个可以存储大量数据的容器,他能容纳不同大小的数据 插入blob类型的数据必须使用PreparedStatement,因为BLOB类型的数据是无法使用字符串拼接写的 mysql的四种blob类型: TinyBlob:最大255b Blob:最大65K MediumBlob:最大16M LongBlob:最大4G 插入blob数据:
@Test public void test7() throws Exception{ Connection connection = JdbcUtils.getConnection(); String sql = "insert into customers(name,email,birth,photo) values(?,?,?,?)"; PreparedStatement ps = connection.prepareStatement(sql); ps.setObject(1, "张无忌"); ps.setObject(2, "zhangwuji@qq.com"); ps.setObject(3, "2000-07-14"); InputStream inputStream = new FileInputStream(new File("src/main/resources/1.png")); ps.setBlob(4, inputStream); ps.execute(); }读取blob数据:
@Test public void test8() throws Exception{ Connection connection = JdbcUtils.getConnection(); String sql = "select * from customers where id=20"; PreparedStatement ps = connection.prepareStatement(sql); ResultSet result = ps.executeQuery(); while(result.next()) { Integer id = result.getInt(1); String name = result.getString(2); String email = result.getString(3); Date date = new Date(result.getDate(4).getTime()); Customers customer = new Customers(id,name,email,date,null); Blob blob = result.getBlob(5); InputStream is = blob.getBinaryStream(); int len = 0; byte[] data = new byte[1024]; OutputStream os = null; while((len = is.read(data)) != -1) { os = new FileOutputStream("test.png"); os.write(data, 0, len); } System.out.println(customer); is.close(); os.close(); } ps.close(); result.close(); }如果指定了相关的Blob类型以后,还报错:xxx to large,那么在mysql的安装目录下,找到mysql.ini文件加上配置参数:max_allowed_packet=16M,修改后需要重启mysql服务才能生效.
结果: 进一步优化插入数据:
/** * 批量数据操作 * 使用批处理之前:插入500条记录耗时68秒 * 使用批处理之后:插入500条记录耗时250毫秒 * 设置不自动提交:插入500条记录耗时128毫秒 */ @Test public void batch() throws Exception{ Connection connection = JdbcUtils.getConnection(); //设置不允许自动提交 connection.setAutoCommit(false); String sql = "insert into customers(name,email,birth) values(?,?,?)"; PreparedStatement ps = connection.prepareStatement(sql); /** * 批处理 * mysql服务器默认是关闭批处理的,开启需要在url后面加上rewriteBatchedStatements=true */ long start = System.currentTimeMillis(); for(int i = 0;i < 501;i ++) { ps.setString(1, "李四"+i); ps.setString(2, "zhangsan"+i+"@qq.com"); ps.setString(3, "2000-07-14"); ps.addBatch(); if(i % 500 == 0) { ps.executeBatch(); ps.clearBatch(); } } //提交数据 connection.commit(); long end = System.currentTimeMillis(); System.out.println("花费的时间:"+(end-start)+"毫秒"); connection.close(); ps.close(); }