package club.suhai.jdbc_demo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
//JDBC快速入门
public class JdbcDem01 {
public static void main(String[] args) {
// 1.导入jar包到libs目录下
try {
Class.forName("com.mysql.jdbc.Driver");
// 3.获取数据库链接对象
try {
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1", "root", "0610");
// 4.定义sql语句
String sql = "update stu set age = 99 where id = 1";
// 5.获取执行sql的对象 statement
Statement statement = connection.createStatement();
// 6.执行sql
int age = statement.executeUpdate(sql);
// 7.处理结果
System.out.println(age);
// 8.释放资源
statement.close();
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
2、1 详解各个对象
1. DriverManager:驱动管理对象
1、DriverManager:驱动管理对象
功能:1.注册驱动://告诉程序该使用哪一个数据库驱动jar包
public static void registerDriver(Driver driver) throws SQLException
//使用DriverManager注册给定的驱动程序
2.获取数据库连接
public static Connection getConnection(String url,
String user, String password)
url: 指定连接路径 jdbc:mysql://localhost(域名):3306(端口号)/数据库名
user: 数据库用户名
password: 数据库用户密码
连接本地数据库:url 可以简写:jdbc:mysql:///数据库名称
2、Connection:数据库连接对象
2、Connection:数据库连接对象
1.功能:获取执行sql的对象
Statement createStatement();
PreParedStatement preparedStatement(String sql);
2.管理事务
开启事务:
void setAutoCommit(boolean autoCommit) 将此连接的自动提交模式设置为给定状态。
提交事务:
void commit() 使自上次提交/回滚以来所做的所有更改成为永久更改,并释放此 Connection对象当前持有的所有数据库锁。
回滚事务:void rollback() 撤消当前事务中所做的所有更改,并释放此 Connection对象当前持有的所有数据库锁。
3、Statement:执行sql的对象
3、Statement:执行sql的对象(不安全,实际并不会使用)
1.执行sql:
1.1 boolean execute(String sql) 执行给定的SQL语句,该语句可能返回多个结果。
1.2(常用)int executeUpdate(String sql) 执行给定的SQL语句,这可能是 INSERT , UPDATE ,或 DELETE语句,或者不返回任何内容,如SQL DDL语句的SQL语句。
参数
sql -一个SQL数据操纵语言(DML)语句,比如INSERT , UPDATE或DELETE ; 或者不返回任何内容的SQL语句,例如DDL语句。
返回结果
//(1)SQL数据操作语言(DML)语句的行数 ---判断是否执行成功
//(2)0表示不返回任何内容的SQL语句
1.3ResultSet executeQuery(String sql) 执行给定的SQL语句,该语句返回单个 ResultSet对象。
4、ResultSet:结果集对象 //封装查询结果
4、ResultSet:结果集对象 //封装查询结果
1.boolean next() 将光标从当前位置向前移动一行。
2.getXXX(参数):获取数据
// XXX代表你要获取数据的数据类型
如:
//获取结果集id
int id = resultSet.getInt(1);
//获取结果集name
String name = resultSet.getString("name");
//获取结果集acount
double acount = resultSet.getDouble(3);
参数:
int :代表列的编号,从1开始,如getString(1);
String:代表列名称,如 getDouble("account");
3.注意:
使用步骤:
1.游标向下移动一行
2.判断是否有数据
3.获取数据
//循环判断游标是否是最后一行末尾
while (resultSet.next()){
//获取结果集id
int id = resultSet.getInt(1); //参数 1 代表获取第一列的id
//获取结果集name
String name = resultSet.getString("name");//参数 name 代表获取列名为 name 的数据
//获取结果集acount
double acount = resultSet.getDouble(3);
System.out.println(id+"---"+name+"---"+acount);
}
4.小练习
//定义一个方法,查询emp表的数据,并将其封装成对象,然后装在集合,返回
4.1 定义一个emp类
4.2 定义方法 public List findAll();
4.3 实现方法 select *from emp;
5、PreparedStatement:执行sql的对象
5、PreParedStatement:执行sql的对象
1.SQL注入问题:在拼接sql时有一些sql特殊关键字参与字符串的拼接,会造成安全性问题
1.输入用户随便,输入密码:a' or 'a' = 'a
请输入用户名:
adadad
请输入用户密码:
a' or 'a' = 'a
/E:/WorkSpace/JDBCDemo/out/production/JDBCDemo/jdbc.properties
select * from user where username = 'adadad' and password = 'a' or 'a' = 'a'
恭喜您adadad登录成功!
2.解决SQL注入问题:使用PreparedStatement对象来解决
3.预编译的sql: //参数使用?作为占位符
4.步骤
1.导入驱动jar包
2.注册驱动
3.获取数据库对象 Connection
4.定义sql
注意:// sql的参数使用?作为占位符,如 select * from user where username = ? and password = ?
5.获取执行sql语句的对象 PreParedStatement Connection.preparStatement(String sql)
6.给 ? 赋值:
方法:setXXX(参数1,参数2)
参数1:?的编号从1开始
参数2:?的值
7.执行sql ,接受返回的结果,不需要传递sql语句
8.处理结果
9.释放资源
5.注意:后期都会使用 PreParedStatement 来完成增删改查的所有操作,放弃使用statement,防止出现sql注入
2、2 抽取JDBC工具类( JDBCUtils)
目的:简化书写
分析:
-
注册驱动抽取
-
抽取一个方法获取连接对象
-
抽取方法释放资源
需求:不想传参(麻烦),还得保证工具类的通用性
解决:配置文件
jdbc.properties
url =
user =
password =
//工具类 package club.suhai.Util; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.net.URL; 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 { //读取资源文件 //1.创建Properties对象 Properties properties = new Properties(); //加载文件 //获取src路径下的文件的方式:---> ClassLoader 类加载器 ClassLoader classLoader = JdbcUtils.class.getClassLoader(); URL res = classLoader.getResource("jdbc.properties"); String path = res.getPath(); System.out.println(path); try { properties.load(new FileReader(path)); } catch (IOException e) { e.printStackTrace(); } //3.获取数据,赋值 url = properties.getProperty("url"); user = properties.getProperty("user"); password = properties.getProperty("password"); driver = properties.getProperty("driver"); try { Class.forName(driver); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException{ return DriverManager.getConnection(url,user,password); } public static void close(ResultSet resultSet,Statement statement, Connection connection){ if (statement!=null){ try { statement.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } if (connection!=null){ try { connection.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } if (resultSet!=null){ try { resultSet.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } } }
//配置文件 url = jdbc:mysql:///db1 user = root password = 0610 driver = com.mysql.jdbc.Driver
//测试类 package club.suhai.jdbc_demo; import club.suhai.Util.JdbcUtils; import club.suhai.domain.Emp; import java.sql.*; import java.util.ArrayList; import java.util.List; public class jdbcDemo7 { public static void main(String[] args) { // Listlist = new jdbcDemo6().findAll(); System.out.println(list); System.out.println(list.size()); } public List findAll(){ ResultSet resultSet = null; Statement statement = null; Connection connection = null; List list = null; //1.注册驱动 try { Class.forName("com.mysql.jdbc.Driver"); //2.获取连接 try { // connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=utf-8","root","0610"); connection = JdbcUtils.getConnection(); //3.定义sql String sql = "select* from users"; //4.获取执行sql的对象 statement = connection.createStatement(); //5。执行sql resultSet = statement.executeQuery(sql); //6.遍历结果集 Emp emp = null; //建立集合 list = new ArrayList<>(); while (resultSet.next()){ int id = resultSet.getInt("id"); String name = resultSet.getString("name"); Date birthday = resultSet.getDate("birthday"); String phone = resultSet.getString("phone"); //创建对象 emp = new Emp(); emp.setId(id); emp.setName(name); emp.setBirthday(birthday); emp.setPhone(phone); list.add(emp); } return list; } catch (SQLException throwables) { throwables.printStackTrace(); } } catch (ClassNotFoundException e) { e.printStackTrace(); }finally{ JdbcUtils.close(resultSet,statement,connection); } return list; } }
练习:
需求:
1.通过键盘录入用户名密码
2.判断用户是否登录成功
步骤:
1.创建用户数据表
create table user( id int primary key auto_increm, username varchar(32), password varchar(32) );3、JDBC控制事务
-
事务:一个包含多个步骤的业务操作,如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败
-
操作:
- 开启事务
- 提交事务
- 回滚事务
-
使用connection对象来管理事务
-
开启事务:setAutoCommit(booleam autoCommit): 调用该方法设置参数为 false,即开启事务
在执行sql前开启事务
-
提交事务:commit();
当所有sql执行完,提交事务
-
回滚事务:rollback();
在catch中回滚事务
-
1.概念:其实就是一个容器(集合),存放数据库连接的容器.
当系统初始化好后,容器被创建,容器中会申请一些数据库连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完后,会将连接对象归还给容器。
2.好处:
1.节约资源 2.用户访问高效
3.实现:
标准接口 :DataSource java.sql 包下的 方法: 获取连接:getConnection() 归还连接:如果连接对象Connection是从连接池中获取的,那么调用Connection.close()方法,则不会再关闭连接,而是归还连接。 一般我们不去实现它,有数据库厂商来实现 1. CP30: 数据库连接池技术(有点古老) 2. Druid: 数据库连接池技术,由阿里巴巴提供4、2 C3P0
步骤:
1.导入jar包,c3p0-0.9.5.2.jar和mchange-commons-java-0.2.12.jar 别忘记导入数据库驱动jar包 mysql-connector-java-5.1.37-bin.jar
2.定义配置文件:
文件:c3p0.properties 或者 c3p0-config.xml
路径:直接将文件放在src目录下即可
3.创建核心对象 数据库连接池对象 ComboPooleDataSource
4.获取连接: getC
package club.suhai.c3po;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
public class c3p0Demo2 {
public static void main(String[] args) throws SQLException {
//1.获取DataSource ,使用默认配置
DataSource dataSource = new ComboPooledDataSource();
//
for (int i = 1;i <= 11;i++ ) {
Connection connection = dataSource.getConnection();
System.out.println(i+":"+connection);
if (i==5){
connection.close(); //归还连接到连接池中
}
}
}
public void testNamedConfig() throws SQLException{
DataSource dataSource = new ComboPooledDataSource("otherc3p0");
for (int i = 1;i <= 11;i++ ) {
Connection connection = dataSource.getConnection();
System.out.println(i+":"+connection);
if (i==5){
connection.close(); //归还连接到连接池中
}
}
}
}
4、2 Druid
1、步骤: 1.导入jar包 druid-1.0.9.jar 2.定义配置文件: 是properties形式的 可以叫任意名称,可以放在任意目录下 3.获取数据库连接对象:通过工厂类来获取,DruidDataSourceFactory 4.获取连接:getConnection; 2、定义工具类 1.定义一个工具类DruidUtils 2.提供静态代码块加载配置文件 3.提供方法 1.获取连接方法:通过数据库连接池获取连接 2.释放资源 3.获取连接池的方法
//propterties 配置文件 driverClassName = com.mysql.jdbc.Driver #?设置字符集 url = jdbc:mysql://127.0.0.1:3306/db1?useUnicode=true&characterEncoding=utf-8 username = root password = 0610 #初始化连接数量 initialSize = 5 #最大连接数量 maxActive = 10 #最大等待时间 maxWait = 3000
package club.suhai.Druid;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;
public class DruidDemo {
public static void main(String[] args) throws Exception{
//
Properties pro = new Properties();
InputStream resourceAsStream = DruidDemo.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(resourceAsStream);
DataSource dataSource = DruidDataSourceFactory.createDataSource(pro);
Connection connection = dataSource.getConnection();
System.out.println(connection);
}
}
//提取工具类
package club.suhai.DruidUtils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
public class DruidUtils {
//定义成员变量
private static DataSource ds;
static {
try {
//1.加载配置文件
Properties pro = new Properties();
pro.load(DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
//获取Datasource
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
public static void close(PreparedStatement preparedStatement, Connection connection){
close(null,preparedStatement,connection);
}
public static void close(ResultSet resultSet,PreparedStatement preparedStatement, Connection connection){
if (preparedStatement!=null){
try {
preparedStatement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (connection!=null){
try {
connection.close();//归还连接
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (resultSet!=null){
try {
resultSet.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
public static DataSource getDatasource(){
return ds;
}
}
package club.suhai.Druid;
import club.suhai.DruidUtils.DruidUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
//测试工具类
public class DruidTestUtils {
public static void main(String[] args) {
//给数据库表中添加数据
Connection connection = null;
PreparedStatement preparedStatement = null;
//1.获取连接
try {
connection = DruidUtils.getConnection();
//2.定义sql
String sql = "insert into stu values(null,?,?)";
//3.获取PreparesStatement
preparedStatement = connection.prepareStatement(sql);
//4.给sql赋值
preparedStatement.setString(1,"丁六");
preparedStatement.setDouble(2,999.00);
int i = preparedStatement.executeUpdate(); //表示影响行数,判断是否执行成功
System.out.println(i);
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally{
DruidUtils.close(preparedStatement,connection);
}
}
}
5、JDBC Template
5、1 Spring JDBC
Spring JDBC 的简单封装,提供了一个JDBC Template 对象简化JDBC开发
步骤:
1.导入jar包
2.创建JDBCTemplate对象,依赖于数据源DataSource
JDBCTemplate template = new JDBCTemplate(ds);
3.调用JDBCTemplate方法来完成CRUD(增删改查)操作
update(): 执行DML语句,增删改语句
queryForMap(): 查询结果将结果集封装为Map集合
注意:Map结果集长度只能为1
queryForList():查询结果将结果集封装为List集合
注意:它是将每一条记录封装为一个一个Map集合,再把Map集合装载到List集合里面
query():查询结果,将结果集封装为 JavaBean 对象
query的参数:RowMapper
一般我们使用BeanProPertyRowMapper实现类 ,可以完成数据到JavaBean的自动封装
template.query(sql, new BeanPropertyRowMapper<类型>(类型.class));
queryForObject(): 查询结果,将结果集封装为对象
4.练习:
需求:
1.修改 1 号数据的account 为 10000.00
2.添加一条记录
3.删除刚才添加的记录
4.查询id = 1 的记录,将其封装为Map集合
注意:Map结果集长度只能为1
5.查询所有记录,将其封装为List
注意:它是将每一条记录封装为一个一个Map集合,再把Map集合装载到List集合里面
6.查询所有记录,将其封装为Emp对象的List集合
7.查询总的记录数
package club.suhai.JdbcTemplate;
import club.suhai.DruidUtils.DruidUtils;
import club.suhai.domain.Emp;
import club.suhai.domain.Emp2;
import org.junit.Test;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import java.util.Map;
public class JdbcTemplateDemo2 {
//Junit单元测试 可以如方法独立执行
//放在成员变量位置,不用重复书写,私有化,不让别的类引用
private JdbcTemplate template = new JdbcTemplate(DruidUtils.getDatasource());
@Test
public void test1(){
String sql = "update users set account = 5000.00 where id = ?";
int count = template.update(sql,1);
System.out.println(count);
}
@Test
public void test2(){
String sql = "insert into users (id,name,account,phone) values (?,?,?,?)";
int count = template.update(sql,6, "丁流",1000.00, "1111");
System.out.println(count);
}
@Test
public void test3(){
String sql = "delete from users where id = ?";
int count = template.update(sql,6);
System.out.println(count);
}
@Test
public void test4(){
String sql = "select *from users where id = ?";
Map map = template.queryForMap(sql,1);
System.out.println(map);
}
@Test
public void test5(){
String sql = "select *from users";
List 


