1.用JDBC于数据库交互
1.1JDBC简介
JDBC(Java Data Base Connectivity)是一种用于执行SQL语句的JavaAPI,它由一组用于Java语言编写的类和接口组成。JDBC为数据库开发人员提供了一个标准的API,使用这套API可以跨平台运行,并且不受数据库供应商的限制。 跨平台运行继承了Java语言“一次编译,到处运行”的特点。 不受数据库供应商的限制:JDBC设有两种接口;一个是面向应用程序员,使得开发人员通过SQL调用数据库; 另一个是驱动程序员,JDBC驱动程序可以利用JDBCAPI是的Java可以方便地操作数据库底层。应用程序只需要编写一次,便可以移到各种驱动程序上运行。
1.2JDBC驱动程序原理
为了是客户端程序独立于特定的数据库驱动程序,JDBC规范建议开发者使用基于接连的编程方式,即尽量使应用仅依赖Java.sql及Javax.sql中的接口和类。
上图是Java访问数据库的原理,可以看出,客户端程序调用Java.sql包下面的API,Java.sql下的API调用相应驱动程序,而相应的驱动程序调用相应的数据库,从而完成数据库的操作。
2.Java与MySQL数据库的连接
Java连接MySQL数据库可以用如下几大步骤:
- 加载驱动程序——在开发环境中加载指定数据库的驱动程序
- 创建数据连接对象——通过DriverManager类创建数据库连接对象Connection。DriverManager类作用于加Java程序和JDBC驱动之间,用于检查所加载的驱动程序是否可以连接,然后通过它的getConnection方法,根据数据库的URL、用户名和密码,创建一个JDBCConnection对象:
其中,URL=协议名+IP地址(域名)+端口+数据库名称;例如:Connection connection = DriverManager.getConnection("URL","用户名","密码");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhonst:3306/mytest", "root", "123456");
- 创建Statement对象
Statement类的主要是用于执行静态SQL语句并返回它所生产结果的对象。通过Connection对象的createStatement()方法可以创建一个Statement对象。
Statement statement = conn.createStatement();
- 调用Statement对象的相关方法执行相应的SQL语句。
通过executeUpdate()方法用来数据更新,包括插入和登出等。
通过调用Statement对象的executeQuery()方法进行数据的查询,而查询结果会得到ResulSet对象,ResulSet表示执行查询数据库后返回的集合,ResulSet对象具有可以指向当前数据行的指针。通过该对象的next()方法,是的指针指向下一行,然后将数据以列号或字段名取出,如果当前next()方法返回null,则表示下一行中没有数据存在。例如:statement.executeUpdate("insert into t_person(name,age)values('sss',28)");
ResultSet resultSet = statement.executeQuery("select * from t_person");
- 关闭数据库连接
使用完数据库或不需要访问数据库时,通过Connection的close()方法及时关闭数据连接。
3.查询数据库和结果集
ResultSet类的常见方法见API
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
public class QueryTest {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
//连接数据库的url
String url = "jdbc:mysql://localhost:3306/mytest";
//数据库用户名
String user = "root";
//数据库密码
String password = "mysql1991";
//1加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2创建数据连接对象
Connection conn = DriverManager.getConnection(url, user, password);
//3.创建Statement对象
Statement statement = conn.createStatement();
//4.获取ResultSet对象
String sql = "select name,age from t_person";
ResultSet rs = statement.executeQuery(sql);
while (rs.next()) {//判断是否有下一个
//获取字段name数据
String name = rs.getString("name");
//获取字段age数据
int age = rs.getInt("age");
System.out.println("姓名:"+name+" 年龄:"+age+"岁");
}
//5.关闭数据库
//注意关闭顺序
rs.close();
statement.cancel();
conn.close();
}
通常在实际开发中,都会建立一个类将表中的字段封装到该类的属性中,通常类名即表名,类的各属性代表表中的各字段。
对于数据库关闭,最好先关闭ResultSet对象,然后关闭Statement对象,最好才是Connection对象,并且建议关闭操作放在finally块进行,在关闭前还应当进行非空判断。
*
* 封装类
*/
public class Person {
private int id;
private String name;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "序号:"+id+" 姓名:"+name+" 年龄:"+age+"岁";
}
}
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
public class QueryTest {
public static void main(String[] args) {
List<Person> lists = new QueryTest().findAll();
for (Person person : lists) {
System.out.println(person);
}
}
private List<Person> findAll() {
Connection conn = null;
Statement statement = null;
ResultSet rs = null;
List<Person> lists = new ArrayList<Person>();
// 连接数据库的url
String url = "jdbc:mysql://localhost:3306/mytest";
// 数据库用户名
String user = "root";
// 数据库密码
String password = "mysql1991";
try {
// 1加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 2创建数据连接对象
conn = DriverManager.getConnection(url, user, password);
// 3.创建Statement对象
statement = conn.createStatement();
// 4.获取ResultSet对象
String sql = "select * from t_person";
rs = statement.executeQuery(sql);
while (rs.next()) {// 判断是否有下一个
Person p = new Person();
// 获取字段name数据
String name = rs.getString("name");
p.setName(name);
// 获取字段age数据
int age = rs.getInt("age");
p.setAge(age);
p.setId(rs.getInt("id"));
lists.add(p);
// System.out.println("姓名:" + name + " 年龄:" + age + "岁");
}
} catch (ClassNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} finally {
// 5.关闭数据库
// 注意关闭顺序
try {
if (rs != null)
rs.close();
if (statement != null)
statement.cancel();
if (conn != null)
conn.close();
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
return lists;
}
}
4.更新删除数据
修改数据操作使用的的是Statement对象的executeUpdate(sql)方法,该方法返回的是一个整数,整数的大小意味着有多少条数据执行。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/*
* 更改数据库数据
*/
public class InsertTest {
public static void main(String[] args) {
InsertTest it = new InsertTest();
Person p = new Person();
p.setName("唐老鸭");
p.setAge(22);
it.insert(p);
}
private void insert(Person p) {
Connection conn = null;
Statement stmt = null;
// 连接数据库url
// String url =
// "jdbc:mysql://localhost:3306/mytest?useUnicode=true&characterEncoding=UTF-8";
String url = "jdbc:mysql://localhost:3306/mytest?useUnicode=true&characterEncoding=UTF-8";
// 数据库用户名
String user = "root";
// 数据库密码
String password = "mysql1991";
try {
// 1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.创建数据连接对象
conn = DriverManager.getConnection(url, user, password);
// 3.创建Statement对象
stmt = conn.createStatement();
// 对sql拼接
String sql = "insert into t_person(name,age)values('" + p.getName()
+ "','" + p.getAge() + "')";
// 执行增加操作
int c = stmt.executeUpdate(sql);
if (c > 0) {
System.out.println("增加了" + c + "条数据!");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {// 关闭数据库
if (stmt != null)
stmt.close();
if (conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
下面一段是摘抄自http://blog.csdn.net/wuzuyu365/article/details/51478063
连接MySQL数据库的时候一般都会在url后面添加useUnicode=true&characterEncoding=UTF-8 添加的作用是:指定字符的编码、解码格式。 例如:MySQL数据库用的是gbk编码,而项目数据库用的是utf-8编码。这时候如果添加了useUnicode=true&characterEncoding=UTF-8 ,那么作用有如下两个方面: 1. 存数据时: 数据库在存放项目数据的时候会先用UTF-8格式将数据解码成字节码,然后再将解码后的字节码重新使用GBK编码存放到数据库中。 2.取数据时: 在从数据库中取数据的时候,数据库会先将数据库中的数据按GBK格式解码成字节码,然后再将解码后的字节码重新按UTF-8格式编码数据,最后再将数据返回给客户端。 注意:在xml配置文件中配置数据库utl时,要使用&的转义字符也就是& 例如:<property name="url" value="jdbc:mysql://localhost:3306/email?useUnicode=true&characterEncoding=UTF-8" />
5.PreparedStatement对象的使用
preparedStatement的功能呢与Statement的功能类似,主要体现在:- 使用preparedStatement可以防止SQL注入
- 使用preparedStatement传入参数更简单
SQL注入是利用现有应用程序,将恶意的SQL命令注入到后台数据库引擎执行的能力,通常主要应用在某些用户不需要知道密码,就可以登录某系统。
SQL注入的命令代码:select *from t_user where name='sky'and password=' ' or 1='1';
从这段代码可以看出即使不知道密码,也能得到数据,这是因为关键字or起作用,只要满足一个条件就可以,而1=‘1’这个绝对满足,所以无论用户名和密码是什么,都会返回数据。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/*
* 简单模拟SQL注入
*/
public class SQLTest {
public static void main(String[] args) {
String name = "sky";
String password = " ' or 1='1'" ;//拼接,从而通过数据库的检查
new SQLTest().mysql(name, password);
}
private void mysql(String name, String password) {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
//用户名
String userName="root";
//密码
String psw = "mysql1991";
// 连接数据库的url
String url = "jdbc:mysql://localhost:3306/mytest";
try {// 1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.创建 数据库 连接对象
conn = DriverManager.getConnection(url,userName,psw);
// 3创建Statement对象
stmt = conn.createStatement();
// SQL语句
String sql = "select * from t_user where name='" + name
+ "'and password='" + password;
//4 获取ResultSet对象
rs = stmt.executeQuery(sql);
while (rs.next()) {
System.out.println("用户名:" + rs.getString("name") + " 密码:"
+ rs.getString("password"));
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (rs != null)
rs.close();
if (stmt != null)
stmt.close();
if (conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
sql = "select * from t_user where name=? and password=?";
PreparedStatement ps = conn.PreparedStatement(sql);
ps.setString(1,name);
ps.setString(2,password);
ResultSet rs = ps.executeQuery();
把上面的第3和4两部分改一下就好:
String sql2 = "select * from t_user where name=? and password=?";
PreparedStatement pstmt = conn.prepareStatement(sql2);
pstmt.setString(1, name);
pstmt.setString(2, password);
rs=pstmt.executeQuery();
if (rs.next()) {
System.out.println("用户名:" + rs.getString("name") + " 密码:"
+ rs.getString("password"));
System.out.println("登录成功");
}else {
System.out.println("登录失败");
}