一、数据库编程的必备条件
编程语言: 如Java、C++、C、Python等 数据库: 如Oracle、MySQL、SQL Server等 数据库驱动包: 不同的数据库,要使用编程语言来操作时,就需要使用该数据库厂商提供的数据库驱动包。 如:MySQL提供了Java的驱动包mysql-connector-java,需要基于java操作MySQL即需要该驱动包。同样的,要基于java操作Oracle数据库则需要Oracle的数据库驱动包ojdbc。
二、Java的数据库编程:JDBC
JDBC,即Java Database Connectivity,java数据库连接,是一种用于执行SQL语句的Java API,它是Java中的数据库连接规范。 这个API由java.sql. *, javax.sql. * 包中的一些类和接口组成,它为java开发人员操作数据库提供了一个标准的API,可以为多种关系数据库提供统一访问。
三、JDBC工作原理
JDBC为多种关系数据库提供了统一访问方式。作为特定厂商数据库访问API的一种高级抽象,它主要包含一些通用的接口类。 JDBC访问数据库层次结构: 我们使用一套JDBC编码,在切换数据库之后,Java操作数据库的代码可以不动(几乎),数据库驱动包要调整,sql因为有标准sql的部分,还有数据库相关的关键字,如mysql中的limit等,这些也需要调整。
JDBC优势:
Java语言访问数据库操作完全面向抽象接口编程 开发数据库应用不用限定在特定的数据库厂商的API 为Java操作不同的数据库提供一种统一的规范,程序在不同数据库的可移植性大大增强
四、JDBC开发步骤
1.创建一个普通的Java项目 2.下载mysql的驱动包 下载驱动包网址 我用的是5.1.xx版本的,说明:不同版本的数据库驱动包,里边的类/接口可能不同
3.项目中添加数据库驱动包(依赖) 验证:写Java代码,可以使用mysql驱动包中的类/接口,才表示引入的依赖没有问题。 4.测试:连接数据库 注意:
1.一开始我们写入forName时会飘红,这里先不用管,直接抛出异常。 alt+enter出现以下的界面,点击第一个: 2.获取数据库连接:Connection接口,需要使用jdbc中的,不要使用mysql中的 3.MySQL数据连接的URL参数格式如下: jdbc:mysql://服务器地址:端口/数据库名?参数名=参数值
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/kang?" +
"user=root&password=010124&useUnicode=true&characterEncoding=UTF-8&useSSL=false");
五、JDBC操作步骤
1.获取数据库连接对象 Connection(jdbc中的接口) 2.使用数据库连接对象来创建一个操作命令对象Statement,该对象是进行sql操作的抽象出来的对象
Statement s=conn.createStatement();
3.调用操作命令对象的方法来执行sql 查询:executeQuery 更新操作(插入、修改、删除):executeUpdate,返回值int,表示执行成功了几条
int n=s.executeUpdate("update exam_result set math=60 where id=1");
System.out.println("修改成功的数量:"+n);
4.如果是查询操作,需要处理结果集对象 查询,返回ResultSet结果集对象,这个结果集对象类似于数据结构中List<Map<String,Object>>
ResultSet r=s.executeQuery("select id,name,chinese,math,english from exam_result where id>3");
while(r.next()){
int id=r.getInt("id");
String name=r.getString("name");
int chinese=r.getInt("chinese");
int math=r.getInt("math");
int english=r.getInt("english");
System.out.printf("id=%s,name=%s,chinese=%s,math=%s,english=%s\n"
,id,name,chinese,math,english);
}
运行结果: 注解: 5.释放资源 无论jdbc操作成功,还是出现异常,都需要释放资源,要考虑出现异常对象还没有完成初始化,还是null的情况,需要反向释放资源。
public class JDBC {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
Connection conn =null;
Statement s=null;
ResultSet r=null;
try{
}finally{
if(r!=null){
r.close();
}
if(s!=null){
s.close();
}
if(conn!=null){
conn.close();
}
}
}
}
六、优化JDBC的部分代码
1.获取数据库连接对象
Connection接口实现类由数据库提供,获取Connection对象通常有两种方式: 1.一种是通过DriverManager(驱动管理类)的静态方法获取 也就是上面我们提到的方法。 2.一种是通过DataSourse(数据源/数据库连接池)对象获取。实际应用中会使用DataSourse对象。
DataSource ds=new MysqlDataSource();
((MysqlDataSource)ds).setURL("jdbc:mysql://localhost:3306/kang");
((MysqlDataSource)ds).setUser("root");
((MysqlDataSource)ds).setPassword("010124");
((MysqlDataSource)ds).setUseUnicode(true);
((MysqlDataSource)ds).setCharacterEncoding("UTF-8");
((MysqlDataSource)ds).setUseSSL(false);
conn = ds.getConnection();
System.out.println(conn);
两者区别: 1.DriverManager类来获取的Connection连接,是无法重复利用的,每次使用完以后释放资源时,通过Connection.close()都是关闭物理连接 2.DataSourse提供连接池的支持。连接池在初始化时将创建一定数量的数据库连接,这些链接是可以复用的,每次使用完数据库连接,释放资源调用connection.close()都是将Connection连接对象回收。效率更高。
2.操作命令对象Statement
Statement对象主要是将SQL语句发送到数据库中,JDBC API中主要提供了三种Statement对象。
Statement: 用于执行不带参数的简单SQL语句(简单的操作命令对象) PreParedStatement:(预编译的操作命令对象)
用于执行带或者不带参数的SQL语句 SQL语句会预编译在数据库系统 执行速度快于Statement对象
CallableStatement: 用于执行数据库存储过程的调用(存储过程的操作命令对象) 存储过程:就是写一段sql代码,里边可以写变量,循环,条件判断等等。
查询操作:
s = conn.createStatement();
String queryName="孙权";
String sql="select id,name,chinese,math,english from exam_result where name='"+queryName+"'";
System.out.println(sql);
r = s.executeQuery(sql);
while (r.next()) {
int id = r.getInt("id");
String name = r.getString("name");
int chinese = r.getInt("chinese");
int math = r.getInt("math");
int english = r.getInt("english");
System.out.printf("id=%s,name=%s,chinese=%s,math=%s,english=%s\n", id, name, chinese, math, english);
}
输出结果: 但是这里有一个现象: 如果我们把这里的queryName改为“skdj’ or ‘1’='1”,在拼接sql字符串时,就可能出现安全问题。 输出结果为: 后面的‘1’=‘1’是一个恒为真的条件,所以就会造成整个or条件结果为真,输出所有成员。 要解决以上安全问题,需要调整以上操作命令对象那个为PreparedStatement,并且使用占位符。
String queryName="skeij' or '1'='1";
int queryId=6;
String sql="select id,name,chinese,math,english from exam_result where name=? or id=?";
ps=conn.prepareStatement(sql);
ps.setString(1,queryName);
ps.setInt(2,queryId);
r=ps.executeQuery();
输出结果为: 插入操作:
int queryId=7;
String queryName="图图";
int chinese=60;
int math=98;
int english=79;
String sql="insert into exam_result values(?,?,?,?,?)";
ps=conn.prepareStatement(sql);
ps.setInt(1,queryId);
ps.setString(2,queryName);
ps.setInt(3,chinese);
ps.setInt(4,math);
ps.setInt(5,english);
int ret=ps.executeUpdate();
System.out.println(ret);
其余的删除,更新操作都与上面类似,这里不再过多演示。
3.ResultSet对象
ResultSet对象它被成为结果集,他代表符合SQL语句条件的所有行,并且它通过一套getXXX方法提供了对这些行中数据的访问。 ResultSet里的数据一行一行排列,每行有多个字段,并且有一个记录指针,指针所指的数据叫做当前数据行,我们只能来操作当前的数据行。如果想要取得某一条记录,就要使用ResultSet的next()方法,如果我们想要得到ResultSet里的所有记录,就应该使用while循环。
while (r.next()) {
int id = r.getInt("id");
String name = r.getString("name");
int chinese = r.getInt("chinese");
int math = r.getInt("math");
int english = r.getInt("english");
System.out.printf("id=%s,name=%s,chinese=%s,math=%s,english=%s\n", id, name, chinese, math, english);
}
4.总结
主要掌握两种执行SQL的方法: 1.executeQuery()方法执行后返回单个结果集的,通常用于select语句。 2.executeUpdate()方法返回值是一个整数,指示受影响的行数,通常用于update、insert、delete语句。 PreparedStatement注意事项:
1.参数化SQL查询 2.占位符不能使用多值 3.占位符:?下标从1开始 4.阻止常见SQL注入攻击 5.SQL预编译 6.性能比Statement高
|