写在前面:JDBC是sun公司(已被Oracle收购)制定一系列接口标准,由不同厂商(Oracle、MySQL等)实现接口方法并封装成驱动文件,供开发人员操作数据库。也就是说,开发人员可采用统一的代码来操作不同的数据库,而无需关注驱动文件的内部实现。想探究这一原理的设计思想,看这里:《JDBC模型—深入理解JDBC设计思想(探究Class.forName("DBDriver"))》
一、三个重要对象:
a.Connection
代表着Java程序与数据库建立的连接。
b.Statement
代表SQL发送器,用于发送和执行SQL语句。
c.ResultSet
代表封装的数据库返回的结果集,用于获取查询结果。
二、编程步骤:
1、加载驱动(需要事先将驱动程序对应的jar文件放到classpath对应的路径)
驱动:就是不同的数据库厂商实现的API。Class.forName(驱动类名);
2、获得连接。Connection conn = DriverManager.getConnection(url,user,pwd);
3、获得Statement。Statment stat = conn.creatStatement();
4、执行SQL。
a.执行查询:ResultSet rst = stat.executeQuery(SQL);
b.执行删除、更新、插入:int = stat.executeUpdate(SQL);
5、如果是查询,需要遍历ResultSet
遍历:将查询的结果一条条取出来,获取其中的数据
6、关闭连接
三、示例:
mysql简单使用:
(1)登录MySQL(使用root用户):mysql -uroot;
(2)查看数据库:show databases;
(3)创建数据库(设置缺省字符集utf-8):create database test1 default character set utf8;
(4)使用某个数据库:use test1;
(5)查看当前数据库有哪些表:show tables;
(6)建表:
create table t_user(
id int primary key auto_increment,
username varchar(50),
pwd varchar(30),
age int
)type=innodb;
insert into t_user(username,pwd,age)values('jetty','test',23);
注意:
auto_increment:自增长列,该列由数据库自动赋值,一般用于主键生成
type=innodb;表示该表支持事务(常用于大型数据库)
程序访问:
public class TestJdbc {
static String driver = "com.mysql.jdbc.Driver";
static String url = "jdbc:mysql://localhost:3306/test1";
static String dbUser = "root";
static String dbPwd = "111111";
public static void main(String[] args) throws Exception {
// findUsers1("jetty", "test");
findUsers1("sadfas", "1' or '1'='1");//错误验证依然可以获取用户信息,出现SQL注入
findUsers2("tom", "tompwd");
}
/**
* 使用原始Statement(容易出现SQL注入)
*
* @param username
* @param pwd
* @throws Exception
*/
public static void findUsers1(String username, String pwd) throws Exception {
// 1.加载类
Class.forName(driver);
// 2.获取连接
Connection conn = DriverManager.getConnection(url, dbUser, dbPwd);
System.out.println(conn);
// 3.获得Statement
Statement state = conn.createStatement();
// 4.调用Statement的方法执行SQL
String sql = "select * from t_user where username = " + "'" + username
+ "'" + " and pwd = '" + pwd + "'";
// 5.execute()将SQL语句发送给数据库,数据库执行查询,数据库执行相应查询,查询的结果会封装到ResultSet对象。
ResultSet rst = state.executeQuery(sql);
// 可以将ResultSet看成一张表,next()含义是,将指针向下移动一位,如果返回值为true,表示当前有记录可以读取
while (rst.next()) {
int id = rst.getInt("id");
String name = rst.getString("username");
String realPwd = rst.getString("pwd");
int age = rst.getInt("age");
System.out.println("id:" + id + ",username:" + name + ",realPwd:"
+ realPwd + ",age:" + age);
}
// 6.关闭资源,一般只需关闭连接即可
if (rst != null) {
rst.close();
}
if (state != null) {
state.close();
}
if (conn != null) {
conn.close();
}
}
/**
* 使用PreparedStatement
*
* @param username
* @param pwd
* @throws Exception
*/
public static void findUsers2(String username, String pwd) throws Exception {
Class.forName(driver);
Connection conn = DriverManager.getConnection(url, dbUser, dbPwd);
// sql表示一个占位符
String sql = "select * from t_user where username=? and pwd=?";
PreparedStatement prep = conn.prepareStatement(sql);
prep.setString(1, username);
prep.setString(2, pwd);
ResultSet rst = prep.executeQuery();
while (rst.next()) {
int id = rst.getInt("id");
int age = rst.getInt("age");
System.out.println("id:" + id + ",age:" + age);
}
// 6.关闭资源,一般只需关闭连接即可
if (rst != null) {
rst.close();
}
if (prep != null) {
prep.close();
}
if (conn != null) {
conn.close();
}
}
}
运行结果:
com.mysql.jdbc.JDBC4Connection@c2e1f26
id:1,username:jetty,realPwd:test,age:23
id:2,username:tom,realPwd:tompwd,age:26
id:2,age:26
四、Statement和PreparedStatement
PrepareStatement和Statement区别和联系
--PrepareStatement从Statement继承
--都是用于发送和执行SQL语句的
--PrepareStatement是一种预编译的Statement对象。
Statement对象是在executeUpdate或executeQuery方法时指定sql,此时将sql语句发送和执行。
PrepareStatement对象是在创建时指定并发送sql,在executeUpdate或executeQuery方法时触发sql执行。
使用原有Statement有以下问题:
--容易遭受注入式攻击
--拼写SQL繁琐和麻烦
通过PrepareStatement可以解决上述问题
PrepareStatement使用步骤:
--编写带?号的sql
--利用con.prepareStatement(sql);方法获取PrepareStatement对象
--利用setXXX()方法给sql的?设置参数值
--调用无参的executeUpdate()或executeQuery()执行sql.
图示:
总结:如图所示,PrepareStatement是一个预编译的Statement,将带占位符?的SQL语句发送给数据库后,SQL语句不会立即执行,数据库会生成一个执行计划,此时SQL语句结构已确定,不可更改注入,然后利用setXXX()方法给sql的?设置参数值,传参后即执行计划,返回结果集。另外,由于执行计划已生成,只要传入参数就可执行计划,这在大批量存入数据时,编码更简单,效率更高。
五、JDBC批处理的使用
用于处理批量的增删改操作。可一次向数据库端发送多条SQL命令,数据库可以对这些SQL命令批量编译执行。
从而提升了批量操作的性能。
1)Statement
Statement stat = ...;
//将sql放入当前的SQL批次中
stat.addBatch(sql);
stat.addBatch(sql1);
....
//发送和执行batch中的SQL
stat.executeBatch();
*2)PrepareStatement
//发送指定sql语句给数据库
//数据库进行预编译
PrepareStatement pst = ...;
pst.setxxx();//设置?参数值
//将当前一组参数放入batch缓存
pst.addBatch();
pst.setxxx();
pst.addBatch();//将参数放入batch
//执行批处理
pst.executeBatch();
提示:batch中存放的sql语句或操作数不要太多,需要根据机器性能决定,一般采用20个即可。
示例:
public void saveUsers(List<User> users) throws Exception {
try {
conn = DBUtil.getConnection();
stat = conn
.prepareStatement("insert into t_user(username,pwd,age)values(?,?,?)");
for (int i = 0; i < users.size(); i++) {
User user = users.get(i);
stat.setString(1, user.getUsername());
stat.setString(2, user.getPwd());
stat.setInt(3, user.getAge());
// stat.executeUpdate();
stat.addBatch();// 参数先不发送,先保存下来
}
stat.executeBatch();// 一次性发送所有保存的参数到数据库执行
} catch (Exception e) {
e.printStackTrace();
} finally {
DBUtil.close(conn);
}
}
常用方法:
addBatch():添加一条要执行的sql。
executeBatch():执行之前添加的所有sql。
clearBatch():清空之前缓存过的sql内容。(可不写,会自动清空)
转载请注明出处:http://blog.csdn.net/daijin888888/article/details/50965232