目录
一、JDBC简介
面向接口编程
二、JDBC快速入门
public class JdbcDemo1 {
public static void main(String[] args) throws Exception {
//1、注册驱动
//将Driver加载进程序中,mysql驱动5之后可以不写这段代码
//Class.forName("com.mysql.jdbc.Driver");
//2、获取连接
/**
* jdbc:mysql: 固定格式
* localhost:3306 mysql服务器所在的主机ip和端口号
* student 数据库名称
* characterEncoding=utf8 字符集使用utf-8
* useSSL=false 是否加密
*/
String url = "jdbc:mysql://localhost:3306/student?/characterEncoding=utf8&useSSL=false";
String username = "root"; //数据库用户名
String password = "123456"; //数据库密码
Connection con = DriverManager.getConnection(url,username,password);
//3、定义sql语句
String sql = "update account set money = money + 500 where name = \"李四\"";
//4、获取执行sql的对象 Statement
Statement stmt = con.createStatement();
//5、执行sql,返回受影响的行
int i = stmt.executeUpdate(sql);
//6、输出结果
System.out.println(i);
//7、释放资源
con.close();
stmt.close();
}
}
三、JDBC API详解
1、DriverManager
2、Connection
2.1、获取执行SQL的对象
SQL注入
String name = "张三";
//模拟SQL注入
//原理:select * from user where username='张三' and password='' or '1' = '1'
//不论这个输入的用户名或者密码是否正确,他都会成功登录系统后台,因为通过拼接or使得左右两边只要有一个为真值就为真
//而1=1为真,所以会被系统判断为真
String pwd = "'or '1' = '1";
//3、定义sql语句
//通过字符串拼接查询输入的信息
String sql = "select * from user where username='"+name+"' and password='"+pwd+"'";
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(sql);
if (rs.next()){
System.out.println("登陆成功!");
System.out.println(rs.getString("username"));
System.out.println(rs.getString("password"));
System.out.println(rs.getString("product"));
}else {
System.out.println("登陆失败!");
}
//7、释放资源
con.close();
stmt.close();
preparedStatement 防止SQL注入
//3、定义sql语句
String name = "张三";
String pwd = "12345";
String sql = "select * from user where username = ? and password = ?";
//4、创建PreparedStatement防止sql注入
PreparedStatement psmt = con.prepareStatement(sql);
//5、设置问号参数
//防止SQL注入 会将输入的敏感字符进行转义,会将注入语句'or '1' = '1 变成 \'or \'1\' = \'1 使它只能是一个符号而不参与运算
psmt.setString(1,name);
psmt.setString(2,pwd);
//6、执行sql语句
ResultSet rs = psmt.executeQuery();
//7、处理结果
if (rs.next()){
System.out.println("登陆成功");
}else {
System.out.println("登陆失败");
}
//8、释放资源
psmt.close();
con.close();
PreparedStatement原理
直接将SQL语句写死,select * from tb_user where name = '张三';这样每次写一条语句都要经过检查、编译、执行会降低系统性能,而使用预编译SQL,参数采用符号代替,它只需要预编译这个带占位符?的语句一次,接收参数值后进行执行,使系统性能更高。
开启预编译
url中添加:useServerPrepStmts=true
//2、获取连接
//useServerPrepStmts=true 开启预编译
String url = "jdbc:mysql://localhost:3306/student?/characterEncoding=utf8&useSSL=false&useServerPrepStmts=true";
String username = "root"; //数据库用户名
String password = "123456"; //数据库密码
Connection con = DriverManager.getConnection(url,username,password);
//3、定义sql语句
String name = "张三";
String pwd = "'or '1' = '1";
String sql = "select * from user where username = ? and password = ?";
//4、创建PreparedStatement防止sql注入
//创建的时候写入sql,执行时不添加
PreparedStatement psmt = con.prepareStatement(sql);
//5、设置问号参数
//防止SQL注入 会自动将输入的字符进行转义,会将注入语句'or '1' = '1 变成 \'or \'1\' = \'1 使它只能是一个符号而不参与运算
psmt.setString(1,name);
psmt.setString(2,pwd);
//6、执行sql语句
//执行时不能加sql
ResultSet rs = psmt.executeQuery();
在使用preparedStatement时在创建时导入sql语句就可以了,在执行的时候不能再加入sql否则会报语法错误,如果是使用字符串拼接要加单引号
//插入数据 加单引号
//拼接变量accountId
String sql ="select username,sex,money from bank where accountid = '" +accountId + "'";
2.2、 事务管理
try {
//开启事务
con.setAutoCommit(false);
//执行sql,返回受影响的行
int i1 = stmt.executeUpdate(sql1);
//输出结果
System.out.println(i1);
//中间出错,事务回滚
int i = 4/0;
//执行sql,返回受影响的行
int i2 = stmt.executeUpdate(sql2);
//输出结果
System.out.println(i2);
//没有出错提交事务
con.commit();
} catch (Exception e) {
//出错了回滚事务
con.rollback();
}finally {
//7、释放资源
con.close();
stmt.close();
}
}
3、Statement
//3、定义sql语句
String sql = "INSERT INTO account VALUES(NULL,'王五',2000); ";
//4、获取执行sql的对象 Statement
Statement stmt = con.createStatement();
//5、执行sql语句,返回受影响的行
int i = stmt.executeUpdate(sql);
//6、处理结果,执行DML的sql语句,可以通过判断结果是否大于0判断是否执行成功
//处理DDL的sql语句不可以,执行成功也可能返回0,比如删除数据库
if(i > 0){
System.out.println("执行成功");
}else {
System.out.println("执行失败");
}
4、ResultSet
它是用来封装Statement查询的结果再通过方法调用输出查询的结果。
ResultSet会将表的查询结果封装起来,其内部有一个游标,默认位置在当前数据的上一行,获取数据时,它会判断当前行是否是有效行。
//新建sql语句
String sql = "select * from account";
//获取statement对象
Statement stmt = con.createStatement();
//执行sql
ResultSet rs = stmt.executeQuery(sql);
//打印查询结果
//光标向下移动一行,并判断是否有数据
while(rs.next()){
//获取该行的字段
//通过id获取字段
System.out.println(rs.getInt(1));
//System.out.println(rs.getString(2));
//也可以通过对应列的名称获取
System.out.println(rs.getString("name"));
System.out.println(rs.getDouble(3));
System.out.println("-----------------------");
}
//释放资源
//后启动先释放
stmt.close();
con.close();
}
注意在获取数据封装对象时,要先对对象进行初始化,在创建对象,否则对象无法被返回
public class JdbcTest {
//创建一个静态容器
public static final List<Account> accounts = new ArrayList<>();
public static void main(String[] args) throws Exception {
//将数据库中的数据查询到java容器中
Class.forName("com.mysql.jdbc.Driver");
//1、获取数据库连接
String url = "jdbc:mysql://localhost:3306/student?/charaterEncoding=utf-8&useSSL=false";
String usernamme = "root";
String password = "123456";
Connection con = DriverManager.getConnection(url,usernamme,password);
//2、创建sql语句
String sql = "select * from account";
//3、创建Statement
Statement stmt = con.createStatement();
//4、执行sql语句
ResultSet rs = stmt.executeQuery(sql);
//如果要读取数据封装成对象要在循环外对对象初始化
//Account accout = null
//5、处理查询结果
while (rs.next()){
//然后在内部创建对象
//account = new Account()
int id = rs.getInt("id");
String name = rs.getString("name");
double money = rs.getDouble("money");
//将获取到的数据封装成账户对象
Account account = new Account(id,name,money);
//将账户对象放入容器
accounts.add(account);
}
//6、对集合容器进行遍历输出
System.out.println(accounts);
}
}
四、数据库连接池
1、数据库连接池简介
![](https://i-blog.csdnimg.cn/blog_migrate/00b83a001964022e75f86173c5a4ce0f.png)
在不使用数据库连接池与数据库交互时,每来一个用户请求,就需要创建一个数据库连接,用户使用完后关闭连接,由于开启数据库连接是个非常耗时的工作,而关闭连接也需要消耗资源,无法进行资源复用,就相当于招聘一个饭店服务员,服务员将客户带到空余座位后就将这个服务员开除,因此非常消耗资源,所以引入数据库连接池,处理一个用户的请求后再回到连接池中,不会关闭这个连接,继续等待下一个客户请求,如果数据库连接池中的所有连接都被占用了,再来一个客户会进行等待,并且连接池中会对当前正在进行的连接进行筛查,一旦发现某一个连接处于静止或者睡眠(后台)状态,就会强制断开这个连接,并归还到连接池,处理下一个请求的客户,避免数据库连接遗漏。
2、Druid数据库连接池
public class DruidDemo1 {
//使用数据库连接池
public static void main(String[] args) throws Exception {
//1、导入jar包
//2、修改配置文件
//3、加载配置文件
Properties prop = new Properties();
prop.load(new FileInputStream("D:\\2ProgramTool\\JavaWebTest\\jdbc\\jdbc-demo\\src\\druid.properties"));
//4、获取连接池对象
DataSource ds = DruidDataSourceFactory.createDataSource(prop);
//5、获取数据库连接
Connection conn = ds.getConnection();
System.out.println(conn);
}
}
#配置文件
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/student?useSSL=false&useServerPrepStmts=true
username=root
password=12345
#初始化连接数量
initialSize=5
#最大连接数
maxActive=10
#最大等待时间
maxWait=3000
五、JDBC增删改查练习
/**
* 由于使用int类型默认为0会对结果造成影响,改用包装类Integer默认为null
* 在实体类中建议基本信息类型使用包装类
*/
public class Brand {
//主键
private Integer id;
//品牌名称
private String brandName;
//公司名称
private String companyName;
//排名
private Integer ordered;
//公司口号
private String description ;
//状态 0表示禁用 1表示启用
private Integer status;
1、JDBC查询
public class JdbcSelectAll {
private List<Brand> brandList = new ArrayList<>();
//查询数据库中的所有用户
@Test
public void BrandTest() {
try {
Properties pop = new Properties();
//修改配置文件
pop.load(new FileInputStream("D:\\2ProgramTool\\JavaWebTest\\jdbc\\jdbc-demo\\src\\druid.properties"));
//创建连接池
DataSource dataSource = DruidDataSourceFactory.createDataSource(pop);
//获取数据库连接
Connection con = dataSource.getConnection();
//定义sql语句
String sql ="select * from tb_brand";
//防止SQL注入获取PreparedStatement
PreparedStatement pstmt = con.prepareStatement(sql);
//执行sql,返回结果集集合
ResultSet resultSet = pstmt.executeQuery(sql);
while (resultSet.next()){
//获取遍历到每一行的数据
int id = resultSet.getInt("id");
String brandName = resultSet.getString("brand_name");
String companyName = resultSet.getString("company_name");
int ordered = resultSet.getInt("ordered");
String description = resultSet.getString("description");
int status = resultSet.getInt("status");
//封装成 品牌对象
Brand brand = new Brand(id,brandName,companyName,ordered,description,status);
//添加到品牌集合中
brandList.add(brand);
}
for (Brand brand : brandList) {
System.out.println("主键\t品牌名称\t企业名称\t企业排名\t公司描述\t状态");
System.out.println(brand.getId() + "\t" + brand.getBrandName() + "\t" + brand.getCompanyName() + "\t"
+ brand.getOrdered() + "\t" + brand.getDescription() + "\t" + brand.getStatus());
System.out.println("------------------------------------");
}
resultSet.close();
pstmt.close();
con.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
2、JDBC添加
public class JdbcAddBrand {
//品牌数据的增加
@Test
public void testAdd() throws Exception {
//1、修改配置文件
Properties pro = new Properties();
pro.load(new FileInputStream("D:\\2ProgramTool\\JavaWebTest\\jdbc\\jdbc-demo\\src\\druid.properties"));
//2、创建数据库连接池
DataSource dataSource = DruidDataSourceFactory.createDataSource(pro);
//3、创建连接
Connection conn = dataSource.getConnection();
//4、创建sql语句
String sql = "insert into tb_brand(brand_name,company_name,ordered,description,status)" +
"values(?,?,?,?,?)";
//5、创建PrepareStatement
PreparedStatement psmt = conn.prepareStatement(sql);
//6、设置参数
psmt.setString(1,"微软");
psmt.setString(2,"美国微软国际公司");
psmt.setInt(3,10);
psmt.setString(4,"微软微软微软");
psmt.setInt(5,1);
//7、执行sql
int i = psmt.executeUpdate();
//8、判断是否添加成功
if (i > 0){
System.out.println("添加成功!");
}else {
System.out.println("添加失败!");
}
//9、释放资源
psmt.close();
conn.close();
}
}
3、JDBC修改
public class JdbcUpdate {
//根据id修改数据
@Test
public void testUpdate() throws Exception {
//1、获取配置文件
Properties pop = new Properties();
pop.load(new FileInputStream("D:\\2ProgramTool\\JavaWebTest\\jdbc\\jdbc-demo\\src\\druid.properties"));
//2、创建数据库连接池
DataSource dataSource = DruidDataSourceFactory.createDataSource(pop);
//3、创建数据库连接
Connection conn = dataSource.getConnection();
//4、创建sql语句
String sql = "update tb_brand set brand_name=?,company_name=?,ordered=?,description=?,status=? " +
"where id=?";
//5、创建PrepareStatement
PreparedStatement pstmt = conn.prepareStatement(sql);
//6、设置参数
pstmt.setInt(6,4);
pstmt.setString(1,"谷歌");
pstmt.setString(2,"微软");
pstmt.setInt(3,34);
pstmt.setString(4,"谷歌公司谷歌谷歌");
pstmt.setInt(5,0);
//7、执行sql
int i = pstmt.executeUpdate();
//8、处理结果
if (i>0){
System.out.println("修改成功!");
}else {
System.out.println("修改失败!");
}
//9、释放资源
pstmt.close();
conn.close();
}
}
4、JDBC删除
public class JdbcDelete {
//根据id删除
@Test
public void testDelete() throws Exception {
//1、获取配置文件
Properties pop = new Properties();
pop.load(new FileInputStream("D:\\2ProgramTool\\JavaWebTest\\jdbc\\jdbc-demo\\src\\druid.properties"));
//2、创建数据库连接池
DataSource dataSource = DruidDataSourceFactory.createDataSource(pop);
//3、创建数据库连接
Connection conn = dataSource.getConnection();
//4、创建sql语句
String sql = "delete from tb_brand where id=?";
//5、创建PrepareStatement
PreparedStatement pstmt = conn.prepareStatement(sql);
//6、设置参数
pstmt.setInt(1,5);
//7、执行sql
int i = pstmt.executeUpdate();
if (i>0){
System.out.println("删除成功!");
}else {
System.out.println("删除失败!");
}
}
}