九、JDBC
1、jdbc的概念以及作用是什么
- 概念:Java DataBase Connectivity java数据连接,使用java语言来操作数据库
- java定义一套操作所有的关系型数据库的规则(接口),各个数据库厂商实现这套接口,提供数据库驱动jar包,我们面向这套接口编程即可,真正执行的代码是驱动jar包的实现类
2、DriverManager对象(驱动管理对象)的作用
-
注册驱动:告诉程序应该使用哪个数据库驱动jar DriverManager.registerDriver()
Class.forName("com.mysql.jdbc.Driver"); //Driver类中包含一个静态代码块,调用了DriverManager的静态方法registerDriver(); static { try { java.sql.DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw new RuntimeException("Can't register driver!"); } }
-
获取数据库连接:DriverManager.getConnection(String url,String username,String password)
Connection conn = DriverManager.getConnection( "jdbc:mysql://127.0.0.1:3306/mnyuansql", "root", "1234");
3、Connection对象(数据库连接对象)的作用
-
获取执行sql对象
//1.获取静态sql对象Statement Statement statement = conn.createStatement(); //2.获取预编译sql对象PrepareStatement PrepareStatement state = conn.prepareStatement(sql);
-
管理事务
//开启事务 conn.setAutoCommit(boolean autoCommit);//参数设置为false开启事务(关闭事务的自动提交) //提交事务 conn.commit(); //事务回滚 conn.rollback();
4、Statement(静态sql对象,不推荐使用)
- 常用方法
- boolean execute(String sql) : 执行DQL和DML的sql语句(不推荐使用)
- ResultSet executeQuery(String sql) : 执行MQL的sql语句
- int executeUpdate(String sql) : 执行DML语句,返回影响的行数
- 缺点
- 会产生sql注入问题,影响程序安全
- 效率较低
- 不推荐使用,建议使用其子类PrepareStatement
5、ResultSet(查询结果集)对象
- boolean next() : 游标向下移动一行,并判断下一行是否含有数据(首次索引为1)
- getXxx(参数) : 获取数据
- Xxx代表数据类型
- 参数:
- int 类型:代表列的编号 如 getString(1)
- String 类型:代表列的名称 getDouble(“balance”)
6、PrepareStatement(预编译sql)对象
-
解决Sql注入问题:使用?作为占位符
-
获取:通过Connection数据库连接对象获取
PrepareStatement state = conn.PrepareStatement(String sql);
-
给?赋值:setXxx(int index,Object)
- Xxx代表数据类型
- 参数:
- 第一个参数:占位符?的位置
- 第二个参数: 给 ? 赋的值
7、抽取JDBC工具类JDBCUtils
-
jdbc.properties
driver=com.mysql.jdbc.Driver url=jdbc:mysql://127.0.0.1:3306/mnyuansql username=root password=1234
-
JDBCUtils
public class JDBCUtils { private static String driver; private static String url; private static String username; private static String password; static { ClassLoader loader = JDBCUtils.class.getClassLoader(); InputStream ras = loader.getResourceAsStream("jdbc.properties"); Properties prop = new Properties(); try { prop.load(ras); driver = prop.getProperty("driver"); url = prop.getProperty("url"); username = prop.getProperty("username"); password = prop.getProperty("password"); //注册驱动 Class.forName(driver); } catch (Exception e) { e.printStackTrace(); } } /** * 获取数据库连接 */ public static Connection getConnection() throws SQLException { return DriverManager.getConnection(url,username,password); } /** * 关闭资源 */ public static void close(Statement state,Connection conn){ if (state != null){ try { state.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } if (conn != null){ try { conn.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } } /** * 关闭资源 */ public static void close(ResultSet set,Statement state, Connection conn){ if (set != null){ try { set.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } close(state,conn); } }
8、数据库连接池
- 数据库连接池概念:本质上就是一个容器,用来存放数据库连接的容器。当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对选哪个归还给容器
- 优点:1.节约资源 2.用户访问高效
- 实现
- 标准接口:javax.sql.DataSource接口
- 方法:
- Connection getConnection() : 获取连接
- conn.close() : 归还连接,如果连接对象是从连接池中获取那么就是归还连接否则就是关闭连接
9、Druid数据库连接池
-
配置文件 .properties形式
-
获取数据库连接池对象:DruidDataSourceFactory
-
获取数据库连接:getConnection()
-
DuridUtils工具类:
public class DruidUtils { private static DataSource ds; //加载配置文件 static { try{ Properties prop = new Properties(); ClassLoader loader = DruidUtils.class.getClassLoader(); InputStream ras = loader.getResourceAsStream("druid.properties"); prop.load(ras); ds = DruidDataSourceFactory.createDataSource(prop); }catch (Exception e){ e.printStackTrace(); } } /** * 获取数据库连接 */ public static Connection getConnection() throws SQLException { return ds.getConnection(); } /** * 获取数据库连接池 */ public static DataSource getDataSource(){ return ds; } /** * 释放资源 */ public static void close(Statement state,Connection conn){ if (state != null){ try { state.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } if (conn != null){ try { conn.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } } /** * 释放资源 */ public static void close(ResultSet rSet,Statement state, Connection conn){ if (rSet != null){ try { rSet.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } close(state,conn); } }
-
druid.properties:
driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://127.0.0.1:3306/mnyuansql username=root password=1234 initialSize=5 maxActive=10 maxWait=3000
10、SpringJDBC
-
spring框架对JDBC做了简单封装,提供了一个JDBCTemplate对象简化开发
-
创建JdbcTemplate对象(依赖数据源DataSource)
JdbcTemplate template = new JdbcTemplate(DataSource ds)
-
JdbcTemplate的CRUD
- update() : 用来执行DML语句,增、删、改
- queryForMap() : 查询结果将封装为map集合,并且列名作为key,值作为value,所以查询的条数只能为1
- queryForList() : 将查询结果封装为list集合,底层:先封装为map在封装到list
- query() : 将查询结果封装为javaBean对象,并存放在list集合中,若数据库字段中含有null值,则javaBean中必须使用包装类
- query的参数:RowMapper
- 一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装
- new BeanPropertyRowMapper<类型>(类型.class)
- queryForObject : 将查询结果,封装为对象 一般用于聚合函数
-
方法使用的代码
public class SpringJdbcInit { //获取JdbcTemplate对象 private JdbcTemplate template = new JdbcTemplate(DruidUtils.getDataSource()); /** * 添加一条数据 */ @Test public void test1(){ String sql = "insert into t_user(id,username,balance) values(3,?,?)"; template.update(sql,"王五",1000); } /** * 修改一条数据 */ @Test public void test2(){ String sql = "update t_user set balance = 1000 where id = ?"; template.update(sql,1); } /** * 删除一条数据 */ @Test public void test3(){ String sql = "delete from t_user where id = ?"; template.update(sql,3); } /** * 查询id为1的记录,将其封装为Map集合 * 一次只能查询1行数据,否则报错 */ @Test public void test4(){ String sql = "select * from emp where empno = ?"; Map<String, Object> map = template.queryForMap(sql, 7369); System.out.println(map); } /** * 查询所有记录,将其封装为List * 底层:先将查询结果封装为map再封装为list */ @Test public void test5(){ String sql = "select * from emp"; List<Map<String, Object>> mapList = template.queryForList(sql); for (Map<String, Object> map : mapList) { System.out.println(map); } } /** * 查询所有记录,将其封装为Emp对象的List集合 * 数据库中为null的不能直接赋值给基本数据类型,该javaBean中含有基本数据类型,报异常 */ @Test public void test6(){ String sql = "select * from emp"; List<Emp> empList = template.query(sql, new BeanPropertyRowMapper<Emp>(Emp.class)); for (Emp emp : empList) { System.out.println(emp); } } /** * 查询所有记录,将其封装为User对象的List集合 * 将javaBean对象中的基本数据类型全部使用包装类 */ @Test public void test7(){ String sql = "select * from t_user"; List<User> users = template.query(sql, new BeanPropertyRowMapper<User>(User.class)); for (User user : users) { System.out.println(user); } } /** * 查询总记录数 */ @Test public void test8(){ String sql = "select count(*) from emp"; Long count = template.queryForObject(sql, Long.class); System.out.println(count); } }