JDBC:java与数据库交互的技术
API:接口,类 (来自于Java.Sql包)
类
- DriverManager:管理JDBC驱动程序,提供方法获取与数据库的连接
- SqlException:数据库操作相关的异常
接口:
- Connection:与数据库特定的连接(会话)--对象,在连接上下文中执行SQL语句并返回结果
- PreparedStatement:
预编译
的Sql语句对象 - Statement:执行
静态
的Sql语句对象 - ResultSet:数据库结果集的数据表(接数据库数据返回的结果)
- CollableStatement:执行存储过程
JDBC程序开发步骤
- 引入驱动jar
- 加载驱动
//加载驱动 Mysql版本不变 这条语句不变
Class.forName("驱动名称");
Class.forName("com.mysql.jdbc.Driver");
- 建立与数据库的连接
- 方法:getConnection(String url, String user, String password)
- url:连接路径
- 语法:jdbc:mysql://ip地址(域名):端口号/数据库名称
- 例子:jdbc:mysql://localhost:3306/scott
细节问题:
如果连接的是本机mysql服务器,并且mysql服务器默认端口是3306,则url可写为:jdbc:mysql:///数据库名称
- user:数据库的用户名
- password:密码
//连接 dbc:mysql:// 不变
//DriverManager.getConnection("url","用户名","密码")
//url:jdbc:mysql://主机名或IP地址(localhost):端口号/连接名
conn = DriverManager.getConnection("jdbc:mysql://主机名或IP地址:端口号/连接名", "用户名", "用户密码");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/scott", "root", "123456");
- 构建Sql语句
//st = conn.createStatement();
//为防止发生SQL注入问题
ps = conn.preparedStatement();
- 执行Sql语句
- 在查询时,连接字符串时用
' '
//查询功能并接收
rs = st.executeQuery("select * from dept where deptno = 10");
为防止发生SQL注入问题:使用prepareStatement()方法
- 使用PreparedStatement 在查询时用
?
代替 - 给参数赋值
setXxx(要赋值的参数的索引(索引从1开始),要赋值的数据):方法名称由数据类型决定
//使用PreparedStatement 在查询时用?代替
ps = conn.prepareStatement(" select * from emp where ename like ? ");
//给参数赋值
//setXxx(要赋值的参数的索引(索引从1开始),要赋值的数据):方法名称由数据类型决定
String ename = new Scanner(System.in).nextLine();
ps.setString(1,ename);
//执行Sql数据,返回接收的数据
rs = ps.executeQuery();
注意:
进行数据的
增删改
时,调用ps.executeUpdate();
,不需要写 rs
- 获取查询结果(遍历)
//遍历 调用next方法:移动结果集的指针
//getXxx:参数是结果集的列名,根据结果列的数据类型对应的方法(结果列的索引值从1开始)
if(rs.next()) {
System.out.println(rs.getInt("deptno")+" "+rs.getString("dname")+" "+rs.getString("loc"));
}else {
System.out.println("没有数据");
}
Statement 栗子:
public static void main(String[] args) {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
//加载驱动 Mysql版本不变 这条语句不变
Class.forName("com.mysql.jdbc.Driver");
//连接 dbc:mysql:// 不变
//DriverManager.getConnection("url","用户名","密码")
//url:dbc:mysql://主机名或IP地址:端口号/连接名
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/scott", "root", "123456");
//根据部门编号查询部门数据
st = conn.createStatement();
//查询功能并接收
rs = st.executeQuery("select * from dept where deptno = 10");
//遍历 调用next方法:移动结果集的指针
//getXxx:参数是结果集的列名,根据结果列的数据类型对应的方法(结果列的索引值从1开始)
if(rs.next()) {
System.out.println(rs.getInt("deptno")+" "+rs.getString("dname")+" "+rs.getString("loc"));
}else {
System.out.println("没有数据");
}
} catch (ClassNotFoundException e) { //编译异常
e.printStackTrace();
} catch (SQLException e) {//数据库操作相关的异常
e.printStackTrace();
}finally {
try {
//关闭资源
conn.close();
st.close();
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
- 依次关闭资源
//关闭资源(连接--接收)
conn.close();
st.close();
rs.close();
SQL注入问题
当JDBC数据库交互时,用户传入的条件导致SQL语句发生变更,从而得到的结果不是用户想要的
问题的产生:
因为使用的是Statement接口执行静态的SQL语句
问题的解决
使用 PreparedStatement (
预编译
)代替 Statement
注意事项
- 使用PreparedStatement 在查询时用 ?代替
ps = conn.prepareStatement("select * from dept where dname = ?");
2.给参数赋值
- setXxx(要赋值的参数的索引(索引从1开始),要赋值的数据):方法名称由数据类型决定
ps.setString(1, dname);
- 接收数据
rs = ps.executeQuery();
PreparedStatement :查询的
栗子:
public static void main(String[] args) {
// 根据部门名称查询部门数据,根据 部门名称从控制台输入
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/scott", "root", "123456");
//使用PreparedStatement 在查询时用?代替
ps = conn.prepareStatement("select * from dept where dname = ?");
//从控制台输入部门编号
System.out.println("请输入一个要查询的部门名称:");
String dname = new Scanner(System.in).nextLine();
//给参数赋值
//setXxx(要赋值的参数的索引(索引从1开始),要赋值的数据):方法名称由数据类型决定
ps.setString(1, dname);
rs = ps.executeQuery();
//遍历 调用next方法:移动结果集的指针
//getXxx:参数是结果集的列名,根据结果列的数据类型对应的方法(结果列的索引值从1开始)
if(rs.next()) {
System.out.println(rs.getInt("deptno")+" "+rs.getString("dname")+" "+rs.getString("loc"));
}else {
System.out.println("没有数据");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally {
//关闭资源
try {
conn.close();
ps.close();
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
PreparedStatement :增删改
的 栗子:
public static void main(String[] args) {
// 根据员工编号,修改员工的 工资和奖金,参数从控制台输入
Connection conn = null;
PreparedStatement ps = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/scott", "root", "123456");
ps = conn.prepareStatement("update emp set sal = ?,comm = ? where empno = ?");
System.out.println("请输入员工工资:");
double sal = new Scanner(System.in).nextDouble();
System.out.println("请输入员工奖金: ");
double comm = new Scanner(System.in).nextDouble();
System.out.println("请输入员工编号: ");
int empno = new Scanner(System.in).nextInt();
ps.setDouble(1, sal);
ps.setDouble(2, comm);
ps.setInt(3, empno);
ps.executeUpdate();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally {
//关闭资源
try {
conn.close();
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
将Util包的Date转换成Sql包的Date
//将字符串转换成Date型日期
String strDate = "1985-01-01";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date utilDate = sdf.parse(strDate);
//导入util包日期
Date now = new Date();
//将util包的日期转换成sql包日期
//getTime():返回毫秒数
java.sql.Date sqlDate = new java.sql.Date(now.getTime());
//将sql包的日期传入
ps.setDate(4,sqlDate );
完整栗子
public static void main(String[] args) {
//自增的方式
Connection conn = null;
PreparedStatement ps = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/scott", "root", "123456");
ps = conn.prepareStatement("insert into emp(ename,job,mgr,hiredate,sal,comm,deptno) "
+ " values(?,?,?,?,?,?,?)");
ps.setString(1, "test7");
ps.setString(2, "MANAGER");
ps.setInt(3, 7369);
//将字符串转换成Date型日期
String strDate = "1985-01-01";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date utilDate = sdf.parse(strDate);
//导入util包日期
Date now = new Date();
//将util包的日期转换成sql包日期
//getTime():返回毫秒数
java.sql.Date sqlDate = new java.sql.Date(now.getTime());
//将sql包的日期传入
ps.setDate(4,sqlDate );
ps.setDouble(5, 5600);
ps.setDouble(6, 8000);
ps.setInt(7, 10);
//执行SQL
ps.executeUpdate();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}finally {
//关闭资源
try {
conn.close();
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}