一、JDBC概述
1、JDBC:Java database connetivity sun公司提供的一套操作数据库的标准规范
JDBC与数据库驱动的关系:接口与实现的关系
2、JDBC规范(掌握四个核心对象)
- DriverManager 用于注册驱动 创建连接
- Connection 表示与数据库创建的连接 一个连接
- Statement 操作数据库sql语句的对象 操作sql语句,并返回相应结果的对象(小货车)
- ResultSet 结果集或一张虚拟表 (客户端存表数据的对象)
3、JDBC初体验
-
/*** 使用JDBC技术实现查询数据库数据,并显示在控制台中* @author Samuel**/public class Demo01 {public static void main(String[] args) throws Exception {//注册驱动DriverManager.registerDriver(new Driver());//获取连接ConnectionConnection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc", "root", "123456");//得到执行sql语句的对象StatementStatement stmt = conn.createStatement();//执行sql语句,并返回结果ResultSet rs = stmt.executeQuery("select * from users");//处理结果while(rs.next()){System.out.println(rs.getObject(1) + " " +rs.getObject(2) + " " +rs.getObject(3) + " "+rs.getObject(4) + " " +rs.getObject(5));}//关闭资源rs.close();stmt.close();conn.close();}}
二、JDBC常用的类和接口详解
1、java.sql.Drivermanager 类:创建连接
a、注册驱动
- DriverManager.registerDriver(new com.mysql.jdbc.Driver());不建议使用
- 导致驱动被注册2次
- 强烈依赖数据库的驱动jar
- 解决方法:Class.forName("com.mysql.jdbc.Driver")
b、与数据库建立连接
- static Connection getConnetion(String url,String user,String password);
- 试图建立到给定数据库URL的连接
- getConnetion("jdbc:mysql://localhost:3306/jdbc","root","123456");
- 协议 子协议 IP 端口号 数据库
-
mysql: jdbc:mysql://localhost:3306/day14 或者 jdbc:mysql:///day14(默认本机连接)
-
oracle: jdbc:oracle:thin:@localhost:1521:sid
-
//获取连接ConnectionProperties info = new Properties();info.setProperty("user", "root");info.setProperty("password", "123456");Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc", info);
-
//获取连接ConnectionConnection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc?user=root&password=123456");
2、JUnit
-
public class Cal {public static int add(int a,int b){return a+b;}public static int div(int a,int b){return a/b;}}
-
/*** 测试方法要求:不能有返回值,不能有参数,不能是静态方法* @author Samuel**/public class TestCalc {@SuppressWarnings("deprecation")@Testpublic void test(){
Assert.assertEquals(7, Cal.add(3, 4));}@SuppressWarnings("deprecation")@Testpublic void test2(){Assert.assertEquals(3, Cal.div(10, 3));}}
3、java.sql.Connection 接口:一个连接
- 接口的实现在数据库驱动中,所有与数据库交互都是基于连接对象的
- Statement createStatement();//创建操作sql语句的对象
4、java.sql.Statement 接口:操作sql语句,并返回相应结果的对象(小货车)
- 接口的实现在数据库驱动中,用于执行静态sql语句并返回它所生成结果的对象
- ResultSet executeQuery(String sql):根据查询语句返回结果集,只能执行select语句
- int executeUpdate(String sql):根据执行的DML(insert,update,delete)语句,返回受影响的行数
- boolean execute(String sql):此方法可以执行任意sql语句,返回Boolean值,表示是否返回ResultSet结果集,仅当执行select语句,且有返回结果时返回true,其他语句都返回false.
-
public void testInsert() throws Exception{//注册驱动Class.forName("com.mysql.jdbc.Driver");//获取连接ConnectionConnection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc?user=root&password=123456");//得到执行sql语句的对象StatementStatement stmt = conn.createStatement();//执行sql语句,并返回结果int i = stmt.executeUpdate("insert into users values(5,'wangwu','123456','wangwu@sina.com',now());");System.out.println(i);//关闭资源stmt.close();conn.close();}
5、java.sql.ResultSet接口:结果集(客户端存表数据的对象)
a、封装结果集
- 提供一个游标,默认游标指向结果集第一行之前
- 调用一次next(),游标向下移动一行
- 提供一些get方法
-
- Object getObject(int columnIndex) 根据序号取值,索引从1开始
- Object getObject(String ColumnName) 根据列名取值
- java中的数据类型与数据库中的类型的关系
-
- byte tityint
- short smallint
- int int
- long bigint
- float float
- double double
- String char varchar
- Date date
-
boolean next() 将光标从当前位置向下移动一行int getInt(int colIndex) 以int形式获取ResultSet结果集当前行指定列号值int getInt(String colLabel) 以int形式获取ResultSet结果集当前行指定列名值float getFloat(int colIndex) 以float形式获取ResultSet结果集当前行指定列号值float getFloat(String colLabel) 以float形式获取ResultSet结果集当前行指定列名值String getString(int colIndex) 以String 形式获取ResultSet结果集当前行指定列号值String getString(String colLabel)以String形式获取ResultSet结果集当前行指定列名值Date getDate(int columnIndex);Date getDate(String columnName);void close() 关闭ResultSet 对象
b、可移动游标的方法
- boolean next() 将光标从当前位置向前移一行。
- boolean previous()
将光标移动到此 ResultSet 对象的上一行。
-
boolean absolute(int row) 参数是当前行的索引,从1开始根据行的索引定位移动的指定索引行。
-
void afterLast()将光标移动到末尾,正好位于最后一行之后。
-
void beforeFirst()将光标移动到开头,正好位于第一行之前。
5、释放资源
- 资源有限,要正确关闭
三、使用JDBC实现CRUD操作
1、
public
class
DBUtils {
private
static
String
driverClass;
private
static
String
url;
private
static
String
username;
private
static
String
password;
static{
//此对象是用于加载properties文件数据的
ResourceBundle
rb
= ResourceBundle.getBundle("dbinfo");
driverClass
=
rb.getString("driverClass");
url
=
rb.getString("url");
username
=
rb.getString("username");
password
=
rb.getString("password");
try
{
Class.forName(driverClass);
}
catch
(ClassNotFoundException
e) {
e.printStackTrace();
}
}
//得到连接的方法
public
static
Connection getConnection()
throws
Exception{
return
DriverManager.getConnection(url,
username,
password);
}
//关闭资源的方法
public
static
void
closeAll(ResultSet
rs,Statement
stmt,Connection
conn){
//关闭资源
try
{
if(null
!=
rs){
rs.close();
}
}
catch
(Exception
e) {
e.printStackTrace();
}
try
{
if(null
!=
stmt){
stmt.close();
}
}
catch
(Exception
e) {
e.printStackTrace();
}
try
{
if(null
!=
conn){
conn.close();
}
}
catch
(Exception
e) {
e.printStackTrace();
}
}
}
2、
public
class
TestCRUD {
@Test
public
void
testSelect(){
Connection
conn
=
null;
Statement
stmt
=
null;
ResultSet
rs =
null;
try
{
conn
= DBUtils.getConnection();
stmt
=
conn.createStatement();
rs
=
stmt.executeQuery("select * from users;");
List<User>
list
=
new
ArrayList<User>();
while(rs.next()){
User
u
=
new
User();
u.setId(rs.getInt("id"));
u.setName(rs.getString("name"));
u.setPassword(rs.getString("password"));
u.setEmail(rs.getString("email"));
u.setBirthday(rs.getDate("birthday"));
list.add(u);
}
for
(User
user
:
list) {
System.out.println(user.toString());
}
}
catch
(Exception
e) {
e.printStackTrace();
}finally{
DBUtils.closeAll(rs,
stmt,
conn);
}
}
@Test
public
void
testInsert(){
Connection
conn
=
null;
Statement
stmt
=
null;
try
{
conn
= DBUtils.getConnection();
stmt
=
conn.createStatement();
int
i
=
stmt.executeUpdate("insert into users values(7,'Tom','123','tom@163.com','2015-09-09');");
if(i
> 0){
System.out.println("success");
}
}
catch
(Exception
e) {
e.printStackTrace();
}finally{
DBUtils.closeAll(null,
stmt,
conn);
}
}
@Test
public
void
testUpdate(){
Connection
conn
=
null;
Statement
stmt
=
null;
try
{
conn
= DBUtils.getConnection();
stmt
=
conn.createStatement();
int
i
=
stmt.executeUpdate("update users set name='jerry',password='123',email='jerry@163.com'
where id=2;");
if(i
> 0){
System.out.println("success");
}
}
catch
(Exception
e) {
e.printStackTrace();
}finally{
DBUtils.closeAll(null,
stmt,
conn);
}
}
@Test
public
void
testDelete(){
Connection
conn
=
null;
Statement
stmt
=
null;
try
{
conn
= DBUtils.getConnection();
stmt
=
conn.createStatement();
int
i
=
stmt.executeUpdate("delete from users where id=7;");
if(i
> 0){
System.out.println("success");
}
}
catch
(Exception
e) {
e.printStackTrace();
}finally{
DBUtils.closeAll(null,
stmt,
conn);
}
}
}
六、SQL注入问题:PreparedStatement
1、PreparedStatement:预编译对象,是Statement对象的子类
2、特点:
- 性能高
- 会把sql语句先编译
- sql语句中的参数会发生变化,过滤掉用户输入的关键字
3、
/**
* 根据用户名和密码查询用户对象信息
*
@param
name
*
@param
pwd
*
@return
*/
public
User findUser(String
name,String
pwd){
Connection
conn
=
null;
PreparedStatement
stmt
=
null;
ResultSet
rs
=
null;
User
u
=
null;
try
{
conn
= DBUtils.getConnection();
String
sql
=
"select * from users where name = ? and password = ?";
stmt
=
conn.prepareStatement(sql);
//给?赋值
stmt.setString(1,
name);
stmt.setString(2,
pwd);
rs
=
stmt.executeQuery();
if(rs.next()){
u
=
new
User();
u.setId(rs.getInt("id"));
u.setName(rs.getString("name"));
u.setPassword(rs.getString("password"));
u.setEmail(rs.getString("email"));
u.setBirthday(rs.getDate("birthday"));
}
}
catch
(Exception
e) {
e.printStackTrace();
}finally{
DBUtils.closeAll(rs,
stmt,
conn);
}
return
u;
}