JDBC
概念
概念:Java DataBase Connectivity Java数据库连接, Java语言操作数据库
JDBC本质:其实是官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类
入门
步骤:
1.导入驱动jar包 mysql
-connector
-java
-8.0.19.jar
1.复制 mysql
-connector
-java
-8.0.19.jar到项目的libs目录下
2.右键
-> Add As Library
2.注册驱动
3.获取数据库的连接对象 Connection
4.定义sql
5.获取执行sql语句的对象 Statement
6.执行sql,接收返回结果
7.处理结果
8.释放资源
package cn
.JinKumg
.jdbc
;
import java
.sql
.Connection
;
import java
.sql
.DriverManager
;
import java
.sql
.Statement
;
public class JdbcDemo01 {
public static void main(String
[] args
) throws Exception
{
Connection conn
= DriverManager
.getConnection("jdbc:mysql:///db3?serverTimezone=GMT+8", "root", "0000");
String sql
= "update emp set salary = 500 where id = 1001";
Statement stmt
= conn
.createStatement();
int count
= stmt
.executeUpdate(sql
);
System
.out
.println(count
);
stmt
.close();
conn
.close();
}
}
详解各个对象
1.DriverManager:驱动管理对象
功能:
1.注册驱动:告诉程序该使用哪一个数据库驱动jar
static void registerDriver(Driver driver
):注册与给定的驱动程序 DriverManager
写代码使用:Class
.forName("com.mysql.cj.jdbc.Driver");
通过查看源码发现:在com
.mysql
.jdbc
.Driver类中存在静态代码块
static{
try{
java
.sql
.DriverManager
.registerDriver(new Driver());
}catch (SQLException){
throw new RuntimeException("Can't register driver!");
}
}
注意:mysql5之后的驱动jar包可以省略注册驱动的步骤
2.获取数据库连接:
方法:
static Connection
getConnection(String url
,String user
,String password
);
参数:
url
:指定连接的路径
语法:jdbc
:mysql
://ip地址
(域名
):端口号
/数据库名称
例子:jdbc
:mysql
://localhost
:3306/db3
细节:如果连接的是本机mysql服务器,并且mysql服务端默认端口是
3306,则url可以简写为:jdbc
:mysql
:/
user
:用户名
password
:密码
2.Connection:数据库连接对象
1.功能:
1.获取执行sql的对象
Statement
createStatement()
PreparedStatement
prepareStatement(String sql
)
2.管理事务
开启事务
:void setAutoCommit(boolean autoCommit
):调用该方法设置参数为
false,即开启事务
提交事务
:commit()
回滚事务
:rollback()
3.Statement:执行sql的对象
1.执行sql
1.boolean execute(String sql
):可以执行任意的sql
2.int executeUpdate(String sql
): 执行
DML(insert、update、delete
)语句、
DDL(create、alter、drop
)语句
返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功 返回值
>0则执行成功,反之则失败
3.ResultSet
executeQuery(String sql
):执行
DQL(select
)语句
2.练习:
1.dept表 添加一条记录
2.dept表 修改一条记录
3.dept表 删除一条记录
4.ResultSet:结果集对象
5.PreparedStatement:执行sql的对象
dept表 添加一条记录
package cn
.JinKumg
.jdbc
;
import java
.sql
.Connection
;
import java
.sql
.DriverManager
;
import java
.sql
.SQLException
;
import java
.sql
.Statement
;
public class JDBCDemo02 {
public static void main(String
[] args
) {
Statement stmt
= null
;
Connection conn
= null
;
try {
Class
.forName("com.mysql.cj.jdbc.Driver");
String sql
= "insert into dept values(1,'gogo','深圳')";
conn
= DriverManager
.getConnection("jdbc:mysql:///db3?serverTimezone=GMT+8", "root", "0000");
stmt
= conn
.createStatement();
int count
= stmt
.executeUpdate(sql
);
System
.out
.println(count
);
if (count
>0){
System
.out
.println("添加成功");
}else{
System
.out
.println("添加失败");
}
}catch (SQLException e
) {
e
.printStackTrace();
}catch (ClassNotFoundException e
) {
e
.printStackTrace();
}finally {
if(stmt
!= null
){
try {
stmt
.close();
} catch (SQLException e
) {
e
.printStackTrace();
}
}
if(conn
!= null
){
try {
conn
.close();
} catch (SQLException e
) {
e
.printStackTrace();
}
}
}
}
}
4.ResultSet:结果集对象,封装查询结果
boolean next():游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是,则返回
false,如果不是,则返回
true
getXxx(参数
):获取数据
Xxx
:代表数据类型 如:
getInt() getString()
参数:
1.Int
:代表列的编号,从
1开始 如:
getString(1)
2.String
:代表列名称 如:
getDouble("balance")
注意:
使用步骤:
1.游标向下移动一行
2.判断是否有数据
3.获取数据
练习:定义一个方法,查询emp表的数据,将其封装为对象,然后装载集合,返回
1.定义emp类
2.定义方法
5.PreparedStatement:执行sql的对象
抽取JDBC工具类:JDBCUtils
目的:简化书写
分析:
1.注册驱动也抽取
2.抽取一个方法获取连接对象
需求:不想传递参数(麻烦),还得保证工具类的通用性
解决:配置文件
jdbc
.properties
url
=
user
=
password
=
3.抽取一个方法释放资源
JDBCDemo08.java
package cn
.JinKumg
.domain
;
import cn
.JinKumg
.utils
.JDBCUtils
;
import java
.sql
.*
;
import java
.util
.ArrayList
;
import java
.util
.List
;
public class JDBCDemo08 {
public static void main(String
[] args
) {
List
<Emp> list
= new JDBCDemo08().findAll2();
System
.out
.println(list
);
System
.out
.println(list
.size());
}
public List
<Emp> findAll2(){
Connection conn
= null
;
Statement stmt
= null
;
ResultSet rs
= null
;
List
<Emp> list
= null
;
try {
conn
= JDBCUtils
.getConnection();
String sql
= "select * from emp";
stmt
= conn
.createStatement();
rs
= stmt
.executeQuery(sql
);
Emp emp
= null
;
list
= new ArrayList<Emp>();
while(rs
.next()){
int id
= rs
.getInt("id");
String ename
= rs
.getString("ename");
int job_id
= rs
.getInt("job_id");
int mgr
= rs
.getInt("mgr");
Date joindate
= rs
.getDate("joindate");
double salary
= rs
.getDouble("salary");
double bonus
= rs
.getDouble("bonus");
int dept_id
= rs
.getInt("dept_id");
emp
= new Emp();
emp
.setId(id
);
emp
.setEname(ename
);
emp
.setJob_id(job_id
);
emp
.setMgr(mgr
);
emp
.setJoindate(joindate
);
emp
.setSalary(salary
);
emp
.setBonus(bonus
);
emp
.setDept_id(dept_id
);
list
.add(emp
);
}
} catch (SQLException e
) {
e
.printStackTrace();
}finally {
JDBCUtils
.close(rs
,stmt
,conn
);
}
return list
;
}
}
jdbc.properties
url
=jdbc
:mysql
:/
user
=root
password
=0000
driver
=com
.mysql
.cj
.jdbc
.Driver
JDBCUtils.java
package cn
.JinKumg
.utils
;
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 pro
= new Properties();
pro
.load(new FileReader("F:\\JinKumg\\day04_jdbc\\src\\cn\\jdbc.properties"));
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练习——登陆用例
练习:
需求:
1.通过键盘录入用户名和密码
2.判断用户是否登录成功
select
* from
步骤:
1.创建数据库表 user
CREATE TABLE
USER(
id INT PRIMARY KEY auto_increment
,
username
VARCHAR(32),
PASSWORD
VARCHAR(32)
);
SELECT
* FROM user
;
INSERT INTO USER
VALUES(NULL
,'zhangsan','123');
INSERT INTO USER
VALUES(NULL
,'lisi','234');
package cn
.JinKumg
.jdbc
;
import cn
.JinKumg
.utils
.JDBCUtils
;
import java
.sql
.*
;
import java
.util
.Scanner
;
public class JDBCDemo09 {
public static void main(String
[] args
) {
Scanner sc
= new Scanner(System
.in
);
System
.out
.println("请输入用户名:");
String username
= sc
.nextLine();
System
.out
.println("请输入密码:");
String password
= sc
.nextLine();
boolean flag
= new JDBCDemo09().login(username
,password
);
if(flag
){
System
.out
.println("登录成功");
}else{
System
.out
.println("用户名或密码错误");
}
}
public boolean login(String username
,String password
){
if(username
== null
|| password
== null
){
return false;
}
Connection conn
= null
;
Statement stmt
= null
;
ResultSet rs
= null
;
try {
conn
= JDBCUtils
.getConnection();
String sql
= "select * from user where username = '"+username
+"' and password = '"+password
+"'";
stmt
= conn
.createStatement();
rs
= stmt
.executeQuery(sql
);
return rs
.next();
} catch (SQLException e
) {
e
.printStackTrace();
}finally {
JDBCUtils
.close(rs
,stmt
,conn
);
}
return false;
}
}
5.PreparedStatement
:执行sql的对象
1.SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接,会造成安全性问题
1.输入用户随便,输入密码:a
' or 'a
' = 'a
2.sql
: select
* from user where username
= 'sadqwr' and password
= 'a' or
'a' = 'a'
2. 解决sql注入问题:使用PreparedStatement对象来解决
3. 预编译的SQL:参数使用?作为占位符
4. 步骤:
1.导入驱动jar包 mysql
-connector
-java
-8.0.19.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:
?的位置编号 从
1开始
参数
2:
?的值
7.执行sql,接收返回结果,不需要传递sql参数
8.处理结果
9.释放资源
注意:后期都会使用PreparedStatment来完成增删改查的所有操作
1.可以防止SQL注入
2.效率更高
public boolean login2(String username
,String password
){
if(username
== null
|| password
== null
){
return false;
}
Connection conn
= null
;
PreparedStatement pstmt
= null
;
ResultSet rs
= null
;
try {
conn
= JDBCUtils
.getConnection();
String sql
= "select * from user where username = ? and password = ?";
pstmt
= conn
.prepareStatement(sql
);
pstmt
.setString(1,username
);
pstmt
.setString(2,password
);
rs
= pstmt
.executeQuery();
return rs
.next();
} catch (SQLException e
) {
e
.printStackTrace();
}finally {
JDBCUtils
.close(rs
,pstmt
,conn
);
}
return false;
}
JDBC控制事务
1.事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败
2.操作:
1.开启事务
2.提交事务
3.回滚事务
3.使用Connection对象来管理事务
开启事务:
setAutoCommit(boolean autoCommit
): 调用该方法设置参数为
false,即开启事务
在执行sql之前开启事务
提交事务:
commit()
当所有sql都执行完提交事务
回滚事务:
rollback()
在
catch中回滚事务
数据库连接池
1.概念:其实就是一个容器(集合),存放数据库连接的容器
当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时候,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器
2.好处:
1.节约资源
2.用户访问高效
3.实现:
1.标准接口:DataSource javax
.sql包下的
1.方法:
获取连接
:getConnection()
归还连接:Connection
.close() 如果连接对象Connetion是从连接池中获取的,那么调用Connection
.close()方法,则不会再关闭连接了,而是归还连接
2.一般我们不去实现它,有数据库厂商来实现
1.CP30:数据库连接池技术
2.Druid:数据库连接池实现技术,由阿里巴巴提供的
4.C3P0:数据库连接池技术
步骤:
1.导入jar包(两个)c3p0
-0.9.5.2.jar mchange
-commons
-java
-0.2.12.jar
不要忘记导入mysql
-connector
-java
-8.0.19.jar 数据库驱动包
2.定义配置文件:
名称:c3p0
.properties或者c3p0
-config
.xml
路径:直接将文件放在src目录下即可
3.创建核心对象 数据库连接池对象 ComboPoolDataSource
4.获取连接:getConnection
5.Druid:数据库连接池实现技术:由阿里巴巴提供的
1.步骤:
1.导入jar包 druid
-1.0.9.jar
2.定义配置文件:
是propertiies形式的
可以叫任意名称,可以放在任意目录下
3.加载配置文件 Properties
4.获取数据库连接池对象:通过工厂类来获取 DruidDataSourceFactory
5.获取连接:getConnection
2.定义工具类
1.定义一个类 JDBCUtils
2.提供静态代码块加载配置文件
3.提供方法
1.获取连接方法:通过数据库连接池获取连接
2.释放资源
3.获取连接池的方法
Spring JDBC
Spring框架对JDBC的简单封装,提供了一个JDBCTemplate对象简化JDBC的开发
步骤:
1.导入jar包
2.创建JdbcTemplate对象,依赖于数据源DataSource
JdbcTemplate template
= new JdbcTemplate(ds
);
3.调用JdbcTemplate的方法来完成CRUD的操作
update():执行DML语句 增、删、改语句
queryForMap():查询结果将结果集封装为map集合,将列名作为key,将值作为value 将这条记录封装为一个map集合
注意:这个方法查询的结果集长度只能是
1
queryForList():查询结果将结果集封装为list集合
注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中
query():查询结果,将结果封装为JavaBean对象
query的参数:RowMapper
一般我们使用BeanPropertyRowMapper实现类 可以完成数据到JavaBean的自动封装
new BeanPropertyRowMapper<Emp>(Emp
.class)
queryForObject():查询结果,将结果封装为对象
一般用于聚合函数的查询
4.练习:
需求:
1.修改
1号数据的salary为
10000
2.添加一条记录
3.删除刚才添加的记录
4.查询id为
1的记录,将其封装为Map集合
5.查询所有记录,将其封装为List
6.查询所有记录,将其封装为Emp对象的List集合
7.查询总记录数
package cn
.JinKumg
.jdbctemplate
;
import cn
.JinKumg
.dataSource
.utils
.JDBCUtils
;
import cn
.JinKumg
.domain
.Emp
;
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
.Date
;
import java
.sql
.ResultSet
;
import java
.sql
.SQLException
;
import java
.util
.List
;
import java
.util
.Map
;
public class JdbcTemplateDemo02 {
JdbcTemplate template
= new JdbcTemplate(JDBCUtils
.getDataSource());
@Test
public void test1() {
String sql
= "update emp set salary = 10000 where id = 1001";
int count
= template
.update(sql
);
System
.out
.println(count
);
}
@Test
public void test2() {
String sql
= "insert into emp(id,ename,dept_id) values(?,?,?)";
int count
= template
.update(sql
, 1015, "郭靖", 10);
System
.out
.println(count
);
}
@Test
public void test3() {
String sql
= "delete from emp where id = ?";
int count
= template
.update(sql
, 1015);
System
.out
.println(count
);
}
@Test
public void test5(){
String sql
= "select id,ename from emp";
List
<Map
<String, Object>> list
= template
.queryForList(sql
);
System
.out
.println(list
);
}
@Test
public void test6(){
String sql
="select * from emp";
List
<Emp> list
= template
.query(sql
, new RowMapper<Emp>() {
@Override
public Emp
mapRow(ResultSet rs
, int i
) throws SQLException
{
Emp emp
= new Emp();
int id
= rs
.getInt("id");
String ename
= rs
.getString("ename");
int job_id
= rs
.getInt("job_id");
int mgr
= rs
.getInt("mgr");
Date joindate
= rs
.getDate("joindate");
double salary
= rs
.getDouble("salary");
double bonus
= rs
.getDouble("bonus");
int dept_id
= rs
.getInt("dept_id");
emp
.setId(id
);
emp
.setEname(ename
);
emp
.setJob_id(job_id
);
emp
.setMgr(mgr
);
emp
.setJoindate(joindate
);
emp
.setSalary(salary
);
emp
.setBonus(bonus
);
emp
.setDept_id(dept_id
);
return emp
;
}
});
for (Emp emp
: list
) {
System
.out
.println(list
);
}
}
@Test
public void test6_2(){
String sql
= "select * from emp";
List
<Emp> list
= template
.query(sql
, new BeanPropertyRowMapper<Emp>(Emp
.class));
for (Emp emp
: list
) {
System
.out
.println(emp
);
}
}
}