JDBC
1.概念
Java DataBase Connectivity Java 数据库连接,Java语言操作数据库
JDBC 本质:其实是官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库jar包。我们可以使用这套接口(JDBC)去编程,真正执行的代码是驱动包Jar包中的实现类。
2.快速入门
- 1,导入驱动jar包
- 2,注册驱动
- 3,获取数据库连接对象 Connection
- 4,定义sql
- 5,获取执行sql语句的对象Statement
- 6,执行sql,接收返回结果
- 7,处理结果
- 8,释放资源
**executeQuery:**用于产生单个结果集(ResultSet)的语句,例如:被执行最多的SELECT 语句。
**executeUpdate :**用于执行 INSERT、UPDATE 或 DELETE 语句以及 SQL DDL(数据定义语言)语句,例如 CREATE TABLE 和 DROP TABLE。
**execute:**可用于执行任何SQL语句,返回一个boolean值,表明执行该SQL语句是否返回了ResultSet。
如果执行后第一个结果是ResultSet,则返回true,否则返回false。
3.详解各个对象
1.DriverManger:驱动管理对象
功能:
#注册驱动:告诉程序员该使用哪一个数据库的驱动jar
static void registerDriver(Driver driver) :注册与给定的驱动程序 DriverManger。
写代码使用发现:在com.mysql.cj.jdbc.Driver类中存在静态代码块
static {try {DriverManager.registerDriver(new Driver());} catch (SQLException var1) {throw new RuntimeException(\"Can\'t register driver!\");}}
注意:mysql5之后的驱动jar包可以省略注册驱动的步骤
#获取数据库连接:
方法:static Connection getConnection(String url , String user , String Passsword)
参数::
url:指定的连接路径。
指定语法:jdbc:mysql://ip地址(域名):端口号/数据库名称。
例子:jdbc:mysql://localhost:3306/db
user:用户名
password:密码
2.Connection:数据库连接对象
功能:
#获取执行sql的对象
*Statement createStatement()
*PreparedStatement prepareStatement(String sql)
#管理事务
*开启事务 setAutoCommit(boolean autoComment ): 调用该方法设置参数值为false,即为开启事务
*提交事务:commit()
*回滚事务:rollback()
3.Statement:执行sql对象
功能:
#执行sql
*boolen execute(String sql): 可以执行任意sql。
*int executeUpdate:执行DML(instert,update,delete)语句,DDL(CREATE,ALTER,DROP)语句.
返回值是:影响的行数。可以通过影响的行数,判断dml语法是否执行成功!(如果返回值大于0则代表成功,反之不成功!)
*ResultSet executeQuery(String sql) :执行dql语句(select)语句 返回一个结果集。
4.ResultSet:结果集对象(封装结果集对象)
功能
#netx(); 游标向下移动 判断当前行是否是最后一行末尾(是否有数据),如果是则返回false,如果不是则返回true。
#getXXX(); xxx代表数据类型,如 int getInt(), String getString(),
参数:getString(1) 1代表列的编号,从1开始
getString(“列名”)代表列的名称
注意:
使用步骤:1游标向下移动一行.2判断是否有数据.3.获取数据.
5.PreparedStatement:执行sql兑现
#SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题。
解决sql注入问题:使用PreparedStatement对象来解决。
表示预编译的sql:参数使用?作为占位符号,在执行sql时赋值。
步骤:
- 1,导入驱动jar包
- 2,注册驱动
- 3,获取数据库连接对象 Connection
- 4,定义sql
- *注意:sql的阐述使用?作为占位符。 如:select * from user where username = ? and password= ?
- 5,获取执行sql语句的对象 PreparedStatement Connection.prepareStatement(String sql)
- 6,给占位符?赋值
- 方法: setXxx(参数1,参数2,)
- 参数1:?的位置。
- 参数2:?的值。
- 7,执行sql,接收返回结果,不需要传递sql语句了
- 9,处理结果
- 10,释放资源
*注意:后期都会使用PreparedStatement来完成增删改查的所有操作
1:可以防止sql注入。
2:效率更高。
&抽取JDBC工具类&
*目的:简化书写
*分析:
1,注册驱动也抽取。
2.抽取一个方法获取连接对象。
*不想传递参数(麻烦),还得保证工具类的通用性
解决方案:配置文件。
jdbc.properties
url =
user =
password =
读取资源文件
//读取资源文件,获取值//Properties//1,创建Properties类Properties pro = new Properties();//2.加载文件//获取src路径下的路径文件的方式 ClassLoader 类加载器pro.load(new FileReader(\"E:\\\\IdeaProjects\\\\javaweb\\\\jdbc\\\\src\\\\main\\\\resources\\\\jdbc.properties\"));//3获取属性赋值
3.抽取一个方法释放资源。
4.JDBC事务
1,事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败。
2,操作:
*,开启事务
&在执行sql之前开启事务
*,提交事务
&当所有sql都执行完提交事务
*,回滚事务
&在catch中回滚事务
3,使用Connection对象来管理事务
*开启事务 setAutoCommit(boolean autoComment ): 调用该方法设置参数值为false,即为开启事务
*提交事务:commit()
*回滚事务:rollback()
例子:
public class JDBCDemo3 {public static void main(String[] args) {Connection conn = null;PreparedStatement pstmt1 = null;PreparedStatement pstmt2 = null;try {//1,获取连接conn = JdbcUtils.getConnection();//开启事务conn.setAutoCommit(false);//定义sql//1,B-500String sql1 = \"update account set money = money - ? where id = ?\";//2,A+500String sql2 = \"update account set money = money + ? where id = ?\";//3获取sql执行对象pstmt1 = conn.prepareStatement(sql1);pstmt2 = conn.prepareStatement(sql2);//执行sqlpstmt1.setFloat(1, 500);pstmt1.setInt(2, 2);pstmt2.setFloat(1, 500);pstmt2.setInt(2, 1);pstmt1.executeUpdate();int i = 1/0;pstmt2.executeUpdate();//提交事务conn.commit();} catch (Exception e) {//事务的回滚try {if (conn != null) {conn.rollback();}} catch (SQLException ex) {ex.printStackTrace();}e.printStackTrace();} finally {JdbcUtils.close(pstmt1, conn);JdbcUtils.close(pstmt2, null);}}}
5,数据库连接池
**概念:**其实就是一个容器(集合)存放数据库连接的容器。
*当系统初始化好后,容器被创建,容器会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完后,会将对象归还给容器。
好处:
1,节约资源。
2,用户访问高效。
实现:
1,标准接口:DataSource javax.sql包下
方法:
- 获取连接:getConnection()
- 归还连接:如果连接对象Connection是从连接池获取的,那么调用Connection.close()方法,则不会再关闭连接了,而是归还连接。
2,一般我们不去实现它,由数据库厂商来实现。
* C3P0:数据库连接池技术。* Druid:数据库连接池实现技术(由阿里巴巴提供)。
#C3P0:
-
步骤:
1,导入jar包,cap0-0.9.5.2.jar mchange-commons-java-0.2.12.jar
2,定义配置文件,
名称:cap0.properties 或者 c3p0-config.xml。
<c3p0-config><!--使用默认的配置读取数据库连接池对象 --><default-config><!-- 连接参数 --><property name=\"driverClass\">com.mysql.cj.jdbc.Driver</property><property name=\"jdbcUrl\">jdbc:mysql://localhost:3306/jdbc</property><property name=\"user\">root</property><property name=\"password\">123456</property><!-- 连接池参数 --><!--初始化申请的连接数量--><property name=\"initialPoolSize\">5</property><!--最大的连接数量--><property name=\"maxPoolSize\">10</property><!--超时时间--><property name=\"checkoutTimeout\">3000</property></default-config></c3p0-config>
路径:直接将文件放在src目录下即可。
3,创建核心对象,数据库连接池对象 comboPooledDataSource.
4,获取连接:getConnection.
例子:
public class C3P0Demo1 {public static void main(String[] args) throws SQLException {//1,创建数据池连接对象DataSource ds = new ComboPooledDataSource();//2获取连接对象Connection conn = ds.getConnection();//3.打印System.out.println(conn);}}
#Druid:
步骤:
1,导入jar包
2,定义配置文件
*特点:
1是properties形式的.
2是可以叫任意名称,可以放在任意目录下
配置文件示例;
driverClassName=com.mysql.cj.jdbc.Driverurl=jdbc:mysql://localhost:3306/jdbcusername=rootpassword=123456#初始化连接数量initialSize=5#最大连接数量maxActive=10#最大等待时间maxWait=3000
3,加载配置文件 Properties pro = new Properties();
4,获取数据库连接池对象:
通过工厂类来获取 DruidDateSourceFactory
5,获取连接:getconnection
例子:
public class DruidDemo {public static void main(String[] args) throws Exception {//1,导入jar包//2,定义配置文件//3,加载配置文件Properties pro = new Properties();//加载配置文件InputStream is = DruidDemo.class.getClassLoader().getResourceAsStream(\"druid.properties\");pro.load(is);//4,获取连接池对象DataSource ds = DruidDataSourceFactory.createDataSource(pro);//5,获取连接Connection connection = ds.getConnection();System.out.println(connection);}}
定义工具类
1定义一个JdbcUtils
2提供静态代码块加载配置文件
3提供方法
#获取连接方法:通过数据库连接池来获取连接
#释放资源
#提供连接数据库连接池的方法
连接池工具类
/*** Druid连接池工具类*/public class JdbcUtils {private static DataSource ds;static {Properties pro = new Properties();try {pro.load(JdbcUtils.class.getClassLoader().getResourceAsStream(\"druid.properties\"));//获取DateSourceds = DruidDataSourceFactory.createDataSource(pro);} catch (IOException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}}/*** 获取连接的方法*/public static Connection getConnection() throws SQLException {return ds.getConnection();}/*** 释放资源*/public static void close(Statement stmt, Connection conn) {if (stmt != null) {try {stmt.close();} catch (SQLException e) {e.printStackTrace();}}if (conn != null) {try {conn.close();} catch (SQLException e) {e.printStackTrace();}}}/*** 释放资源重载*/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();}}}/*** 获取连接池方法*/public static DataSource getDataSource(){return ds;}}
测试连接池工具类
/*** 测试新工具类*/public class DruidDemo2 {public static void main(String[] args) {/*** 完成添加操作*///1获取连接PreparedStatement pstmt = null;Connection conn = null;try {conn = JdbcUtils.getConnection();//定义sqlString sql = \"insert into account values(null, ?, ?)\";//获取pstmr对象pstmt = conn.prepareStatement(sql);//给?赋值pstmt.setString(1, \"D\");pstmt.setFloat(2, 5000);//执行sqlint i = pstmt.executeUpdate();System.out.println(i);} catch (SQLException e) {e.printStackTrace();} finally {//释放资源JdbcUtils.close(pstmt,conn);}}}