JDBC学习笔记
目录
一、JDBC介绍
1、什么是JDBC
JDBC(JavaDataBase Connectivity)就是Java数据库连接,说白了就是用Java语言来操作数据库。原来我们操作数据库是在控制台使用SQL语句来操作数据库,JDBC是用Java语言向数据库发送SQL语句。简单地说,JDBC 可做三件事:与数据库建立连接、发送 操作数据库的语句并处理结果。
2、连接常用的接口
提供的接口包括:JAVA API:提供对JDBC的管理链接;JAVA Driver API:支持JDBC管理到驱动器连接。
- DriverManager :这个类管理数据库驱动程序的列表。内容是否符合从Java应用程序使用的通信子协议正确的数据库驱动程序的连接请求。识别JDBC在一定子协议的第一个驱动器被用来建立数据库连接。
- Driver :此接口处理与数据库服务器通信。很少直接与驱动程序对象。相反,使用DriverManager中的对象,它管理此类型的对象。它也抽象的与驱动程序对象工作相关的详细信息。
- Connection :此接口与接触数据库的所有方法。连接对象表示通信上下文,即,与数据库中的所有的通信是通过唯一的连接对象。
- Statement :可以使用这个接口创建的对象的SQL语句提交到数据库。一些派生的接口接受除执行存储过程的参数。
- ResultSet :这些对象保存从数据库后,执行使用Statement对象的SQL查询中检索数据。它作为一个迭代器,让你可以通过移动它的数据。
3、JDBC驱动
点击下载→mysql-connector-java-5.1.7.rar
解压后把jar文件添加到项中即可
二、使用JDBC的基本步骤
1. 注册驱动
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
2. 建立连接
//DriverManager.getConnection("jdbc:mysql://localhost/test?
user=monty&password=greatsqldb");
//2. 建立连接 参数一: 协议 + 访问的数据库 , 参数二: 用户名 , 参数三: 密码。
conn = DriverManager.getConnection("jdbc:mysql://localhost/student", "root", "root");
3. 创建statement
//3. 创建statement , 跟数据库打交道,一定需要这个对象
st = conn.createStatement();
4. 执行sql ,得到ResultSet
//4. 执行查询 , 得到结果集
String sql = "select * from t_stu";
rs = st.executeQuery(sql);
5. 遍历结果集
//5. 遍历查询每一条记录
while(rs.next()){
int id = rs.getInt("id");
String name = rs.getString("name");
int age = rs.getInt("age");
System.out.println("id="+id + "===name="+name+"==age="+age);
}
6. 释放资源
if (rs != null) {
try {
rs.close();
} catch (SQLException sqlEx) { } // ignore
rs = null;
}
三、JDBC 工具类构建
1、资源释放工作的整合
package com.qidishixun.JDBCTest;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
public class JDBCUtils {
public static void release(Connection conn,Statement st,ResultSet rs){
closeRs(rs);
closeSt(st);
closeConn(conn);
}
private static void closeConn(Connection conn){
if (conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}finally {
conn = null;
}
}
}
private static void closeSt(Statement st){
if (st != null){
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}finally {
st = null;
}
}
}
private static void closeRs(ResultSet rs){
if (rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}finally {
rs = null;
}
}
}
}
package com.qidishixun.JDBCTest;
import com.mysql.jdbc.Driver;
import java.sql.*;
public class JDBCDemo {
public static void main(String[] args) {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
Driver driver = new Driver();
//1、注册驱动
DriverManager.registerDriver(driver);
//2、获取数据库连接
conn = DriverManager.getConnection("jdbc:mysql://localhost/mydatabase","root","123456");
//3、通过连接对象创建 statement对象
st = conn.createStatement();
//4、执行 SQL 语句, 返回结果集对象
String sql = "select * from student";
rs = st.executeQuery(sql);
//5、处理结果集
while(rs.next()){
int sid = rs.getInt("sid");
String name = rs.getString("name");
int age = rs.getInt("age");
System.out.println("sid = " + sid + ", name = " + name + ", age = " + age);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCUtils.release(conn,st,rs);
}
}
}
2、驱动防二次注册
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
Driver 这个类里面有静态代码块,一上来就执行了,所以等同于我们注册了两次驱动。 其实没这个必要的。 //静态
代码块 ---> 类加载了,就执行。 java.sql.DriverManager.registerDriver(new Driver());最后形成以下代码即可。
Class.forName("com.mysql.jdbc.Driver");
3、使用properties配置文件
- 1)在src底下声明一个文件 xxx.properties ,里面的内容如下:
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost/mydatabase?useUnicode=true&characterEncoding=utf8
database=mydatabase
user=root
password=123456
- 2)在工具类里面,使用静态代码块,读取属性
package com.qidishixun.JDBCTest;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
public class JDBCUtils {
public static String driverClass = null;
public static String url = null;
public static String user = null;
public static String password = null;
public static String database = null;
static {
try {
Properties pro = new Properties();
pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties"));
driverClass = pro.getProperty("driverClass");
url = pro.getProperty("url");
user = pro.getProperty("user");
password = pro.getProperty("password");
database = pro.getProperty("database");
} catch (IOException e) {
e.printStackTrace();
}
}
public static Connection getConn(){
Connection conn = null;
try {
Class.forName(JDBCUtils.driverClass);
conn = DriverManager.getConnection(JDBCUtils.url,JDBCUtils.user,JDBCUtils.password);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
}
- 3)测试:
package com.qidishixun.JDBCTest;
import com.mysql.jdbc.Driver;
import java.sql.*;
public class JDBCDemo2 {
public static void main(String[] args) {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
//注册驱动并获取连接诶
conn = JDBCUtils.getConn();
//3、通过连接对象创建 statement对象
st = conn.createStatement();
//4、执行 SQL 语句, 返回结果集对象
String sql = "select * from student";
rs = st.executeQuery(sql);
//5、处理结果集
while(rs.next()){
int sid = rs.getInt("sid");
String name = rs.getString("name");
int age = rs.getInt("age");
System.out.println("sid = " + sid + ", name = " + name + ", age = " + age);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCUtils.release(conn,st,rs);
}
}
}
四、数据库的CRUD sql
CRUD即增加(Create)、查询(Retrieve)、更新(Update)、删除(Delete)四个单词的首字母缩写
- insert
INSERT INTO student(NAME , age, gender , birth) VALUES ('wangqiang',28 , '女', '1988-5-4')
INSERT INTO student VALUES (NULL,'wangqiang2',28)
// 1. 获取连接对象
conn = JDBCUtil.getConn();
// 2. 根据连接对象,得到statement
st = conn.createStatement();
//3. 执行添加
String sql = "insert into t_stu values(null , 'aobama' , 59)";
//影响的行数, ,如果大于0 表明操作成功。 否则失败
int result = st.executeUpdate(sql);
if(result >0 ){
System.out.println("添加成功");
}else{
System.out.println("添加失败");
}
- delete
DELETE FROM student WHERE sid = 6
// 1. 获取连接对象
conn = JDBCUtil.getConn();
// 2. 根据连接对象,得到statement
st = conn.createStatement();
//3. 执行添加
String sql = "delete from t_stu where name='aobama'";
//影响的行数, ,如果大于0 表明操作成功。 否则失败
int result = st.executeUpdate(sql);
if(result >0 ){
System.out.println("删除成功");
}else{
System.out.println("删除失败");
}
- query
SELECT * FROM student
// 1. 获取连接对象
conn = JDBCUtil.getConn();
// 2. 根据连接对象,得到statement
st = conn.createStatement();
// 3. 执行sql语句,返回ResultSet
String sql = "select * from t_stu";
rs = st.executeQuery(sql);
// 4. 遍历结果集
while (rs.next()) {
String name = rs.getString("name");
int age = rs.getInt("age");
System.out.println(name + " " + age);
}
- update
UPDATE t_stu SET age = 38 WHERE id = 1;
// 1. 获取连接对象
conn = JDBCUtil.getConn();
// 2. 根据连接对象,得到statement
st = conn.createStatement();
//3. 执行添加
String sql = "update t_stu set age = 26 where name ='qyq'";
//影响的行数, ,如果大于0 表明操作成功。 否则失败
int result = st.executeUpdate(sql);
if(result >0 ){
System.out.println("更新成功");
}else{
System.out.println("更新失败");
}
五、使用单元测试,测试代码
- 1、定义一个类, TestXXX , 里面定义方法 testXXX.
- 2、添加junit的支持。
右键工程 --- add Library --- Junit --- Junit4 - 3、在方法的上面加上注解 , 其实就是一个标记。
@Test
public void testQuery() {
...
}
-
- 光标选中方法名字,然后右键执行单元测试。 或者是打开outline视图, 然后选择方法右键执行。
六、Dao模式
Dao:Data Access Object 数据访问对象
- 1、新建一个dao的接口, 里面声明数据库访问规则
package com.qidishixun.JDBCTest;
import java.util.List;
/**
* @author Gui
* @description 定义数据库操作的规则
* @date 2021/6/27
*/
public interface UserDao {
public void findAll();
public List<User> findALL();
public User findByID(int id);
public void add(User user);
public void addPreparedStatement(User user);
public void update(User user);
public void delete(int id);
}
2、新建一个dao的实现类,具体实现早前定义的规则
package com.qidishixun.JDBCTest;
import java.sql.*;
import java.util.List;
public class UserDaoImpl implements UserDao {
@Override
public void findAll() {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
conn = JDBCUtils.getConn();
st = conn.createStatement();
rs = st.executeQuery("select * from student ");
while(rs.next()){
int sid = rs.getInt("sid");
String name = rs.getString("name");
int age = rs.getInt("age");
String gender = rs.getString("gender");
String birth = rs.getString("birth");
User user = new User();
user.setSid(sid);
user.setName(name);
user.setAge(age);
user.setGender(gender);
user.setBirth(birth);
System.out.println(user.toString());
}
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public List<User> findALL() {
return null;
}
@Override
public User findByID(int id) {
User user = null;
Connection conn = null;
// Statement st = null;
PreparedStatement pst = null;
ResultSet rs = null;
try {
conn = JDBCUtils.getConn();
// st = conn.createStatement();
// String sql = "select * from student where sid=" + id;
// rs = st.executeQuery(sql);
//使用占位符写法
String sql = "select * from student where sid=?";
pst = conn.prepareStatement(sql);
pst.setInt(1,id);
rs = pst.executeQuery();
if (rs.next()){
int sid = rs.getInt("sid");
String name = rs.getString("name");
int age = rs.getInt("age");
String gender = rs.getString("gender");
String birth = rs.getString("birth");
user = new User(sid,name,age,gender,birth);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.release(conn,pst,rs);
}
return user;
}
@Override
public void add(User user) {
Connection conn = null;
Statement st = null;
try {
conn = JDBCUtil.getConn();
st = conn.createStatement();
String sql = "insert into student(name,age,gender,birth) " +
"values('" + user.getName() +"','" + user.getAge() +
"','" + user.getGender() + "','" + user.getBirth() + "')";
System.out.println(sql);
int result = st.executeUpdate(sql);
if (result>0){
System.out.println("添加成功");
}else {
System.out.println("添加失败");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCUtils.release(conn,st);
}
}
@Override
public void addPreparedStatement(User user) {
Connection conn = null;
PreparedStatement pst = null;
try {
String sql = "insert into student(name,age,gender,birth) values(?,?,?,?)";
pst = conn.prepareStatement(sql);
pst.setString(1,user.getName());
pst.setInt(2,user.getAge());
pst.setString(3,user.getGender());
pst.setString(4,user.getBirth());
int result = pst.executeUpdate();
if (result>0){
System.out.println("添加成功");
}else {
System.out.println("添加失败");
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
JDBCUtils.release(conn,pst);
}
}
@Override
public void update(User user) {
Connection conn = null;
Statement st = null;
try {
conn = JDBCUtil.getConn();
st = conn.createStatement();
String sql = "update student set name='" +
user.getName() +"',age='" + user.getAge() +
"',gender='" + user.getGender() + "',birth='" + user.getBirth() + "' where sid='" + user.getSid() + "'";
System.out.println(sql);
int result = st.executeUpdate(sql);
if (result>0){
System.out.println("更新成功");
}else {
System.out.println("更新失败");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCUtils.release(conn,st);
}
}
@Override
public void delete(int id) {
Connection conn = null;
Statement st = null;
try {
conn = JDBCUtil.getConn();
st = conn.createStatement();
String sql = "delete from student where sid=" + id;
System.out.println(sql);
int result = st.executeUpdate(sql);
if (result>0){
System.out.println("删除成功");
}else {
System.out.println("删除失败");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.release(conn,st);
}
}
}
- 3、直接使用实现
package com.qidishixun.JDBCTest;
import org.junit.Test;
import java.util.Iterator;
import java.util.List;
/**
* UserDaoImpl Tester.
*
* @author <Authors Gui>
* @since <pre>6月 27, 2021</pre>
* @version 1.0
*/
public class UserDaoImplTest {
@Test
public void testFindAll(){
UserDao dao = new UserDaoImpl();
dao.findAll();
}
@Test
public void testFindByID(){
UserDao dao = new UserDaoImpl();
User user = dao.findByID(2);
if (user == null){
System.out.println("查询失败!");
}else{
System.out.println(user);
}
}
@Test
public void tsetAdd(){
User user = new User("晓晓", 12, "女", "2008-12-21");
UserDao dao = new UserDaoImpl();
dao.add(user);
}
@Test
public void testUpdate(){
User user = new User(5, "大大", 15, "男", "2015-1-2");
UserDao dao = new UserDaoImpl();
dao.update(user);
}
@Test
public void testDelete(){
UserDao dao = new UserDaoImpl();
dao.delete(9);
dao.findAll();
}
}
七、Statement安全问题
- 1、Statement执行 ,其实是拼接sql语句的。 先拼接sql语句,然后在一起执行。
Connection conn = null;
Statement st = null;
ResultSet rs = null;
conn = JDBCUtil.getConn();
st = conn.createStatement();PrepareStatement
String sql = "select * from user where username='" + username + "' and password='" + password + "' or 1=1";
rs = st.executeQuery(sql);
SELECT * FROM user WHERE username='admin' AND PASSWORD='12345644' or '1=1'
前面先拼接sql语句, 如果变量里面带有了 数据库的关键字,那么一并认为是关键字。 不认为是普通的字符
串。rs = st.executeQuery(sql);
1、PrepareStatement
该对象就是替换前面的statement对象。
相比较以前的statement, 预先处理给定的sql语句,对其执行语法检查。 在sql语句里面使用 ? 占位符来替代
后续要传递进来的变量。 后面进来的变量值,将会被看成是字符串,不会产生任何的关键字。
String sql = "insert into t_user values(null , ? , ?)";
ps = conn.prepareStatement(sql);
//给占位符赋值 从左到右数过来,1 代表第一个问号, 永远你是1开始。
ps.setString(1, userName);
ps.setString(2, password);
- UserDao
package com.qidishixun.JDBCTest;
import java.util.List;
/**
* @author Gui
* @description 定义数据库操作的规则
* @date 2021/6/27
*/
public interface UserDao {
public void findAll();
public List<User> findALL();
public User findByID(int id);
public void add(User user);
public void addPreparedStatement(User user);
public void update(User user);
public void delete(int id);
}
- UserDaoImpl1
package com.qidishixun.JDBCTest;
import java.sql.*;
import java.util.List;
public class UserDaoImpl implements UserDao {
@Override
public void findAll() {
}
@Override
public List<User> findALL() {
return null;
}
@Override
public User findByID(int id) {
User user = null;
Connection conn = null;
// Statement st = null;
PreparedStatement pst = null;
ResultSet rs = null;
try {
conn = JDBCUtils.getConn();
// st = conn.createStatement();
// String sql = "select * from student where sid=" + id;
// rs = st.executeQuery(sql);
//使用占位符写法
String sql = "select * from student where sid=?";
pst = conn.prepareStatement(sql);
pst.setInt(1,id);
rs = pst.executeQuery();
if (rs.next()){
int sid = rs.getInt("sid");
String name = rs.getString("name");
int age = rs.getInt("age");
String gender = rs.getString("gender");
String birth = rs.getString("birth");
user = new User(sid,name,age,gender,birth);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.release(conn,pst,rs);
}
return user;
}
@Override
public void add(User user) {
}
/**
* 使用占位符方法
*/
@Override
public void addPreparedStatement(User user) {
Connection conn = null;
PreparedStatement pst = null;
try {
String sql = "insert into student(name,age,gender,birth) values(?,?,?,?)";
pst = conn.prepareStatement(sql);
pst.setString(1,user.getName());
pst.setInt(2,user.getAge());
pst.setString(3,user.getGender());
pst.setString(4,user.getBirth());
int result = pst.executeUpdate();
if (result>0){
System.out.println("添加成功");
}else {
System.out.println("添加失败");
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
JDBCUtils.release(conn,pst);
}
}
@Override
public void update(User user) {
}
@Override
public void delete(int id) {
}
}
- 单元测试:
package com.qidishixun.JDBCTest;
import org.junit.Test;
import java.util.Iterator;
import java.util.List;
/**
* UserDaoImpl Tester.
*
* @author <Authors Gui>
* @since <pre>6月 27, 2021</pre>
* @version 1.0
*/
public class UserDaoImplTest {
@Test
public void testFindByID(){
UserDao dao = new UserDaoImpl();
User user = dao.findByID(2);
if (user == null){
System.out.println("查询失败!");
}else{
System.out.println(user);
}
}
@Test
public void tsetAddPreparedStatement(){
User user = new User("默默", 15, "女", "2006-12-21");
UserDao dao = new UserDaoImpl();
dao.add(user);
}
}
2、JDBC工具类的封装
- JDBCTemplete
package com.qidishixun.JDBCTest;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @ClassName: JDBCTemplete
* @Author Gui
* @Date 2021/6/27
* @Version 1.0
*/
public class JDBCTemplete {
public int update(String sql,Object...args){
Connection conn = null;
PreparedStatement pst = null;
try {
conn = JDBCUtils.getConn();
pst = conn.prepareStatement(sql);
//循环设置占位符
for (int i=0;i<args.length;i++){
pst.setObject(i+1,args[i]);
}
return pst.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCUtils.release(conn,pst);
}
return -1;
}
public Object query(String sql,ResultSetHandler resultSetHandler,Object...args){
Connection conn = null;
PreparedStatement pst = null;
ResultSet rs = null;
try {
conn = JDBCUtils.getConn();
pst = conn.prepareStatement(sql);
for (int i=0;i<args.length;i++){
pst.setObject(i+1,args[i]);
}
rs = pst.executeQuery();
return resultSetHandler.doHandler(rs);
} catch (SQLException e) {
e.printStackTrace();
return -1;
}finally {
JDBCUtils.release(conn,pst);
}
}
}
- ResultSetHandler
package com.qidishixun.JDBCTest;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @author Gui
* @description 抽象结果集的处理
* @date 2021/6/27
*/
public interface ResultSetHandler {
public Object doHandler(ResultSet rs)throws SQLException;
}
- 使用 JDBCTemplete
package com.qidishixun.JDBCTest;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class UserDaoImpl2 implements UserDao {
private JDBCTemplete jdbcTemplete;
public UserDaoImpl2(){
jdbcTemplete = new JDBCTemplete();
}
@Override
public void findAll() {
}
@Override
public List<User> findALL() {
String sql = "select * from student";
return (List<User>)jdbcTemplete.query(sql, new ResultSetHandler() {
@Override
public Object doHandler(ResultSet rs) throws SQLException {
List<User> users = new ArrayList<>();
while(rs.next()){
User user = new User();
user.setSid(rs.getInt("sid"));
user.setName(rs.getString("name"));
user.setAge(rs.getInt("age"));
user.setGender(rs.getString("gender"));
user.setBirth(rs.getString("birth"));
users.add(user);
}
return users;
}
});
}
@Override
public User findByID(int id) {
return null;
}
@Override
public void add(User user) {
}
@Override
public void addPreparedStatement(User user) {
}
@Override
public void update(User user) {
String sql = "update student set name=?,age=?,gender=? where sid=?";
jdbcTemplete.update(sql,user.getName(),user.getAge(),user.getGender(),user.getSid());
}
@Override
public void delete(int id) {
}
}
- UserDaoImplTest
package com.qidishixun.JDBCTest;
import org.junit.Test;
import java.util.Iterator;
import java.util.List;
/**
* UserDaoImpl Tester.
*
* @author <Authors Gui>
* @since <pre>6月 27, 2021</pre>
* @version 1.0
*/
public class UserDaoImplTest {
@Test
public void testFindAll(){
UserDao dao = new UserDaoImpl();
dao.findAll();
}
@Test
public void testFindAllHandler(){
UserDao dao = new UserDaoImpl2();
List<User> users = dao.findALL();
// Iterator<User> iterator = users.iterator();
// while(iterator.hasNext()){
// System.out.println(iterator.next());
// }
for (User user : users){
System.out.println(user);
}
}
@Test
public void testFindByID(){
UserDao dao = new UserDaoImpl();
User user = dao.findByID(2);
if (user == null){
System.out.println("查询失败!");
}else{
System.out.println(user);
}
}
@Test
public void tsetAdd(){
User user = new User("晓晓", 12, "女", "2008-12-21");
UserDao dao = new UserDaoImpl();
dao.add(user);
}
@Test
public void tsetAddPreparedStatement(){
User user = new User("默默", 15, "女", "2006-12-21");
UserDao dao = new UserDaoImpl();
dao.add(user);
}
@Test
public void testUpdate(){
User user = new User(5, "大大", 15, "男", "2015-1-2");
UserDao dao = new UserDaoImpl();
dao.update(user);
}
/**
* 循环设置占位符更新数据
*/
@Test
public void testUpdateForPreSatatement(){
User user = new User(8, "考卡", 15, "男", "2015-1-2");
UserDao dao = new UserDaoImpl2();
dao.update(user);
}
@Test
public void testDelete(){
UserDao dao = new UserDaoImpl();
dao.delete(9);
dao.findAll();
}
}
作者:落花桂
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。