jdbc
概念
操作数据库有三种方式
- cmd 操作
- 工具操作(sqlYog ,navicate )
- 通过java的方式操作 数据库
jdbc :java中用来操作数据库的 一种技术 Java DataBase Connectivity (java的数据库连接)
JDBC由来
jdbc的含义 :接口概念
1.jdbc的接口中api是什么
2.导入驱动jar包
jdbc快速入门
1.数据库
CREATE DATABASE day06;
USE day06;
CREATE TABLE `user`(
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(32) ,
nickname VARCHAR(32) ,
money INT
);
2.java代码
public static void main(String[] args) throws Exception {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获得连接 Exception in thread "main" java.sql.SQLException: No database selected
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/day06", "root", "root");
//3.获得语句执行者
Statement statement = connection.createStatement();
//4.执行语句
String sql = " insert into user values(null , 'jack' , 'tom' , 1000)";
int count = statement.executeUpdate(sql);
//5.处理结果
System.out.println(count);
//6.释放资源
statement.close();
connection.close();
}
PreparedStatement预处理对象
登录的问题
#登录
#select * from t_user where username = 'jack' and password = '1234'
#select * from t_user where username = 'xxxx' and password = '1234'
# 在数据库有三种注释 # -- /**/
SELECT * FROM t_user WHERE username = '输入值' AND PASSWORD = '输入值';
#语法 or 条件只需要满足一个即可
# 1=1 恒等条件
SELECT * FROM t_user WHERE username='zhangsan' OR 1=1 ;
#当作用户名: ' or 1=1 --
SELECT * FROM t_user WHERE username = '' OR 1=1 -- ' AND PASSWORD = '输入值';
#当输入某些特殊值的时候 sql语句 发生了变化 源于 值和sql语句的语法组成新的内容
# 该过程我们称之为sql注入问题
当输入某些特殊值的时候,这些特殊值和 原本的sql语句一结合,修改了原sql的具体含义,这个过程就是sql语句注入问题。
问题的产生:
问题的解决:
在jdbc中 有一个新的对象来解决sql注入的问题 , 此对象叫预处理(预先处理sql)对象
PreparedStatement好处
- 解决了sql注入的问题
- 提高了sql语句的可读性 , 通过问号的方式 替代 参数(变量)
- PreparedStatement 会引用着预编译后的结果。可以多次传入不同的参数给PreparedStatement 对象并执行。减少SQL编译次数(编译一次 多次使用),提高效率(减少编译次数-> 提高效率)。
api部分:
PreparedStatement preparedStatement = connection.prepareStatement(sql); 获得预处理对象
executeUpdate() 增删改 此处不需要传入sql 因为 sql在之前就已经传入过了 (发送参数 通知数据库执行)
executeQuery() 查询 (发送参数 通知数据库执行)
execute() DDL 没用
/**
* 增
*/
@Test
public void testInsert() throws Exception {
//1.获得连接
Connection connection = JDBCUtils.getConnection();
//2.获得语句执行者 -> 预处理对象
String sql = " INSERT INTO USER VALUES(NULL , ? , ? , ?) ";
// 将sql语句发送给数据库进行预编译处理
PreparedStatement preparedStatement = connection.prepareStatement(sql); //发送sql
//添加数据(还没有发送数据) preparedStatement.set数据类型(sql语句中?所在的位置 , 传入的值);
preparedStatement.setString(1 , "张三");
preparedStatement.setString(2 , "zhangsan");
preparedStatement.setInt(3 , 1500);
/**
* preparedStatement
* executeUpdate() 增删改 此处不需要传入sql 因为 sql在之前就已经传入过了 (发送参数 通知数据库执行)
* executeQuery() 查询 (发送参数 通知数据库执行)
* execute() DDL 没用
*/
//3.执行语句
int count = preparedStatement.executeUpdate();
//4.处理结果
System.out.print(count);
//5.释放资源
JDBCUtils.close(preparedStatement , connection);
}
/**
* 修改
*/
@Test
public void testUpdate() throws Exception {
//1.获得连接
Connection connection = JDBCUtils.getConnection();
//2.获得预处理对象-发送sql
String sql = " update user set username =?,nickname = ? , money = ? where id = ? ";
PreparedStatement pst = connection.prepareStatement(sql);
//3.设置数据
pst.setObject(1 , "李四");
pst.setObject(2 , "lisi");
pst.setObject(3 , 5000);
pst.setObject(4 , 6);
//4.执行sql pst.executeUpdate(sql) 携带sql 使用的是statement对象(不支持问号的形式)
int count = pst.executeUpdate();//不能够有sql
//5.处理结果
System.out.println(count);
//6.释放资源
JDBCUtils.close(pst , connection);
}
/**
* 删除
*/
@Test
public void testDelete() throws Exception {
//1.获得连接
Connection connection = JDBCUtils.getConnection();
//2.获得预处理对象
String sql = " delete from user where id= ? ";
PreparedStatement pst = connection.prepareStatement(sql);
//3. 设置参数
pst.setObject(1 , 6);
//4.执行sql
int count = pst.executeUpdate();
//5.处理结果
System.out.println(count);
//6.释放资源
JDBCUtils.close(pst, connection);
}
连接池
定义:一个存放连接的位置
没有连接池遇到的问题
每一次操作CURD的时候 都要创建一个新的连接, 每一次使用完都关闭连接
创建之后 立马关闭-> 创建会消耗大量的资源, 销毁后 资源没了
连接池原理
操作连接池 : 核心动作
- 从池中获得连接
- 操作完以后归还连接
常见连接池
Druid连接池
/**
* 方式一
* 1.数据源是DataSource接口 别人提供jar(实现类)
* 2.new实现类
* 3.DataSource接口 提供获得连接的方法 getConnection()
*/
public class TestDemo1 {
public static void main(String[] args) throws SQLException {
//1.数据源的核心类 DruidDataSource
DruidDataSource dataSource = new DruidDataSource();
//1.1 基本四项设置: 连接任何数据库都需要基本四项
//设置 set
//1.1.1 驱动串 Driver 驱动 ClassName 全限定名称
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
//1.1.2 url连接地址
dataSource.setUrl("jdbc:mysql:///day06");
//1.1.3 用户名
dataSource.setUsername("root");
//1.1.4 密码
dataSource.setPassword("root");
//2.获得连接
Connection connection = dataSource.getConnection();
//是否有connection NullPointerException 此时没有connection 因为别人提供的数据 至少也需要知道用户名...
System.out.println(connection);
}
}
/**
* 方式二
* 测试Druid 数据源使用
*/
public class TestDemo3 {
public static void main(String[] args) throws Exception {
//定义map
Map map= new HashMap();
//ctrl + F12 查看当前类 及其父类中的方法 setDriverClassName setUrl ...
//在java中 取名 去掉set首字母小写
//dataSource.setDriverClassName("com.mysql.jdbc.Driver"); -> driverClassName
//dataSource.setUrl("jdbc:mysql:///day06"); -> url
//dataSource.setUsername("root"); -> username
//dataSource.setPassword("root"); -> password
//map用来放置参数 : 基本四项 或者其他设置
map.put( "driverClassName" , "com.mysql.jdbc.Driver");
map.put( "url" , "jdbc:mysql:///day06");
map.put( "username" , "root");
map.put( "password" , "root");
//需要核心类 数据源工厂对象 : 也可以帮助我们生产 数据源对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(map);
//打印连接
System.out.println(dataSource.getConnection());
}
}
简化操作:
public static void main(String[] args) throws Exception {
//properties 必须有基本四项设置
//ClassLoader() 类加载器 : 目的 加载文件 读取到内存中
//getResourceAsStream("只从src下开始读取数据") 加载文件的方法
//当前类名称.class.getClassLoader()
//加载properties即可
InputStream is = TestDemo4Important.class.getClassLoader().getResourceAsStream("db.properties");
//加载流 获得properties对象
Properties properties = new Properties();
//加载流
properties.load( is );
//1.核心类
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
//2.拿到连接
System.out.println(dataSource.getConnection());
}
db.properties文件
#db.properties 必须在src的根目录下
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///day06
username=root
password=root
#其他设置 查看底层
#初始化个数
initialSize=3
#最大个数
maxActive=10
#最大等待时间
maxWait=2000