JDBC学习笔记
1. jdbc概念
- Java数据库连接,Java语言操作数据库
- 本质:一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。可以通过这套接口(JDBC)编程。真正执行的代码时驱动jar包中的实现类。
2. 步骤
-
导入驱动包到本项目的lib文件下,并导入仓库
-
注册驱动
Class.forName("com.mysql.jc.jdbc.Driver")
-
获取数据库连接对象
DriverManager.getConnection("jdbc:mysql://localhost:3306/数据库","user","password");
-
定义SQL语句
String sql = "update goods set sellCount = 100 where id = 64"
-
获取数据库连接对象
.createStatement();
-
执行SQL语句,返回结果
.executeUpdate(sql);
-
释放资源
3. 详解
DriverManager:驱动管理对象
-
注册驱动:告诉程序使用那个数据库驱动jar mysql5之后 可以省略注册
-
使用代码:Class.forName(“com.mysql.cj.jdbc.Driver”);
-
源码:
static { try { java.sql.DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw new RuntimeException("Can't register driver!"); } }
-
获取连接参数:
- 方法:static Connection getCooection(String url, String usr, String password);
url:知道连接路径
- 语法:jdbc:mysql://IP地址(域名):端口号/数据库名称
user:用户名
password:密码
Connection:数据库连接对象
-
功能:
获取执行sql的对象
- statement createStatement() 创建一个statement对象,将SQL语句发送到数据库,没有参数的SQL语句
- PreparedStatement prepareStatement(String sql) 预编译
管理事务
- 开启事务:setAutoCommit(boolean autoCommit):调用该方法设置参数为false,即开启事务
- 提交事务:commit()
- 回滚事务:rollback()
-
Statement:执行sql的对象
执行sql:
-
boolean execute(String sql) :可以执行任意的sql 了解
-
int executeUpdate(String sql) :执行DML(insert、update、delete)语句、DDL(create,alter、drop)语句
- 返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功
- 返回值 > 0的则执行成功,反之,则失败。
-
ResultSet executeQuery(String sql) :执行DQL(select)语句
-
-
ResultSet:表示数据库结果集的数据表,通常通过执行查询数据库的语句产生
ResultSet对象保持一个光标指向其当前的数据行。最初,光标位于第一行之前。next方法将光标移动到下一行,并且由于在ResultSet对象中没有更多行时返回false,可以通过while循环来遍历结果集。
-
boolean next():游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),是则返回false,不是返回true
-
getXxx(参数):获取数据
-
Xxx:代表数据类型 int getInt() String getString()
-
参数:
int代表列表的编号,是从1开始
String 代表列名称
-
public class jdbc_resultSet { public static void main(String[] args) { Statement state = null; ResultSet rs = null; String url = "jdbc:mysql://localhost:3306/db_test"; String sql = "select * from course"; try { Class.forName("com.mysql.cj.jdbc.Driver"); Connection conn = DriverManager.getConnection(url, "root", "redhat"); state = conn.createStatement(); rs = state.executeQuery(sql); while (rs.next()) { int cid = rs.getInt(1); String cname = rs.getString("cname"); String teacher = rs.getString("teacher"); System.out.println("课程id:" + cid + " " + "课程名称:" + cname + " " + "教师:" + teacher); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (state != null) { try { state.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
-
抽取JDBC工具类:JDBCUtils
-
目的
通过读取配置文件的形式,减少代码的重复编写,提高效率
以静态代码块的形式获取
-
过程
- 编写配置文件 jdbc.properties
url=jdbc:mysql://localhost:3306/db_test user=root password=redhat driver=com.mysql.cj.jdbc.Driver
- 创建JDBCUtils类
import java.io.FileReader; import java.io.IOException; import java.sql.*; import java.util.Properties; public class JDBCUtils { private static String url; private static String user; private static String password; private static String driver; //通过静态代码块,一次性读取配置文件的内容 static { //读取资源文件,获取值 try { //创建Properties集合类 Properties pro = new Properties(); ClassLoader classLoader = JDBCUtils.class.getClassLoader(); URL res = classLoader.getResource("jdbc.properties"); String path = res.getPath(); pro.load(new FileReader(path)); //获取数据 url = pro.getProperty("url"); user = pro.getProperty("user"); password = pro.getProperty("password"); driver = pro.getProperty("driver"); //注册驱动 Class.forName(driver); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } //获取连接对象 public static Connection getConnection() throws SQLException { return DriverManager.getConnection(url, user, password); } //释放资源 public static void close(ResultSet rs, Statement stmt, Connection conn) { if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
- Jdbc_Demo_Utils 类去使用JDBCUtils工具类
import cn.superboy.jdbc.utils.JDBCUtils; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class Jdbc_Demo_Utils { public static void main(String[] args) { Connection conn = null; Statement statm = null; ResultSet rs = null; try { //连接数据库 conn = JDBCUtils.getConnection(); statm = conn.createStatement(); String sql = "select * from db_test.student"; rs = statm.executeQuery(sql); while (rs.next()) { int sid = rs.getInt("sid"); String sname = rs.getString("sname"); int age = rs.getInt("age"); String sex = rs.getString("sex"); String department = rs.getString("department"); String address = rs.getString("address"); String birthplace = rs.getString("birthplace"); int course_id = rs.getInt("course_id"); //将查询到的内容打印 System.out.println(sid + " " + sname + " " + age + " " + sex + " " + department + " " + address + " " + birthplace + " " + course_id); } } catch (SQLException e) { e.printStackTrace(); } finally { //释放资源 JDBCUtils.close(rs, statm, conn); } } }
JDBC控制事务
-
事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败。
-
操作:
-
开启事务
-
提交事务
-
回滚事务
-
-
使用Connection对象管理事务
- 开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
- 在执行sql之前开启事务
- 提交事务:commit()
- 当所有sql都执行完提交事务
- 回滚事务:rollback()
* 在catch中回滚事务
import cn.superboy.jdbc.utils.JDBCUtils1; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; public class Jdbc_Demo_Commit { public static void main(String[] args) { Connection conn = null; PreparedStatement pre1 = null; PreparedStatement pre2 = null; try { conn = JDBCUtils1.getConnection(); //开启事务 conn.setAutoCommit(false); String sql1 = "update db_test.sc set grade = grade - ? where sid = ? and cid = ?"; String sql2 = "update db_test.sc set grade = grade + ? where sid = ? and cid = ?"; pre1 = conn.prepareStatement(sql1); pre2 = conn.prepareStatement(sql2); pre1.setInt(1, 10); pre1.setInt(2, 3108001); pre1.setInt(3, 8108010); pre2.setInt(1, 20); pre2.setInt(2, 3108001); pre2.setInt(3, 8108003); //执行sql语句 pre1.executeUpdate(); //手动异常,使事务回滚 int i = 2 / 0; pre2.executeUpdate(); //事务提交 conn.commit(); } catch (SQLException e) { try { if (conn != null) { conn.rollback(); } } catch (SQLException e1) { e1.printStackTrace(); } e.printStackTrace(); }finally { JDBCUtils1.close(pre1,conn); JDBCUtils1.close(pre2,null); } } }
- 开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
4. 数据库连接池
概念:
存放数据库连接得容器,当初始化好后,容器被创建,容器会申请一些来连接对象,当用户来访问数据库时,从容器中获取连接对象,访问完之后,将连接对象归还给容器。
作用:
节约资源 提高访问效率
实现:
- 标准接口:DataSource
- 方法:
- 获取连接:getConnection()
- 归还连接:Connection.close()
- 实现得工具:
- C3P0:数据库连接池技术
- Druid:数据库连接池技术,阿里巴巴提供
C3P0:
- 导入jar包
- 定义配置文件c3p0.properties或者c3p0-config.xml
- 创建核心对象,数据库连接池对象ComboPooledDataSource
- 获取连接:getConnection
- code
import com.mchange.v2.c3p0.ComboPooledDataSource; import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException; public class C3P0Demo1 { public static void main(String[] args) throws SQLException { DataSource ds = new ComboPooledDataSource(); Connection connection = ds.getConnection(); System.out.println(connection); } }
druid:
- 导入jar包
- 定义配置文件 properties
- 加载配置文件
- 获取数据库连接池对象
- 获取连接
- code
import com.mchange.v2.c3p0.ComboPooledDataSource; import javax.sql.DataSource; import java.io.IOException; import java.io.InputStream; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; public class DruidDem01 { public static void main(String[] args) throws IOException, SQLException { Properties pro = new Properties(); InputStream is = DruidDem01.class.getClassLoader().getResourceAsStream("druid.properties"); pro.load(is); DataSource ds = new ComboPooledDataSource(); Connection conn = ds.getConnection(); System.out.println(conn); } }
Spring JDBC
-
Spring 框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发
-
步骤:
-
导入jar包
-
创建JdbcTemplate对象,依赖于数据源DataSource
JdbcTemplate template = new JdbcTemplate(ds);
-
调用JdbcTemplate的方法来完成CRUD操作
-
update() :执行DML语句,增,删,改查
-
querForMap():将查询结果封装为map集合,将列名作为key,将值作为value,但是此集合长度只是1
-
queryForList():查询结果封装为list集合,将每一条记录封装为map集合,再封装到List集合
-
query():查询结果,将结果封装为JavaBean对象
query的参数:RowMapper
一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装
new BeanPropertyRowMapper<类型>(类型.class)
-
queryForObject:查询结果,将结果封装为对象,一般用于聚合函数的查询
-
-