jdbc1

ODBC

因为有市场需要,微软定义了一组用于数据库应用程序的编程接口ODBC(open database

connectivity)。这一套方案大大缩短了程序的开发周期,可以让开发人员只需要调用同一套

编程接口,无需考虑具体实现。

ODBC分为四个部分

\1. 应用程序:开发人员所写的代码,ODBC提供的调用接口

\2. 驱动程序管理器:用于管理驱动程序的。

\3. 驱动程序:对接口的实现部分,各个数据库厂商来完成的。

\4. 数据源:就是连接数据库的一些参数:url,username,password

JDBC

Sun公司参考了ODBC方案,制定了一组专门为java语言连接数据库的通用接口JDBC。方便了

java开发人员,开发人员不需要考虑特定的数据库的DBMS。JDBC不直接依赖于DBMS,而是通过

驱动程序将sql语句转发给DBMS,由DBMS进行解析并执行,处理结果返回。

JDBC的工作原理

第一步:注册驱动程序

第二步: 请求连接

第三步: 获取执行sql语句的对象,发送给DBMS

第四步:返回结果集,程序员进行处理

第五步: 关闭连接操作

JDBC中常用的接口和类

JDBC与数据库驱动的关系:

接口与实现的关系。

JDBC规范(掌握四个核心对象):

DriverManager:用于注册驱动

Connection: 表示与数据库创建的连接

Statement: 操作数据库sql语句的对象

ResultSet: 结果集或一张虚拟表

注册驱动

DriverManager.registerDriver(new com.mysql.jdbc.Driver());不建议使用

原因有2个:

> 导致驱动被注册2次。

> 强烈依赖数据库的驱动jar

解决办法:

Class.forName("com.mysql.jdbc.Driver");

与数据库建立连接

试图建立到给定数据库 URL 的连接。

url: 连接指定数据库的地址 jdbc:mysql://ip:port/dbname

user: 连接用户名

password:密码

getConnection("jdbc:mysql://localhost:3306/day06", "root", "root");

Statement createStatement();

作用:用于获取Statement对象

java.sql.Statement接口

作用:操作sql语句,并返回相应结果的对象(小货车)

查找执行的是executeQuery,增删改执行的是executeUpdate

execute(String sql):通常用于DDL

executeUpdate(String sql):通常用于DML

executeQuery(String sql):用于DQL

java.sql.ResultSet接口

表示结果集(客户端存表数据的对象)

提供一个游标,默认游标指向结果集第一行之前。

调用一次next(),游标向下移动一行。

提供一些get方法。

jdbc基本实现

//1.注册mysql的驱动

DriverManager.registerDriver(new com.mysql.jdbc.Driver());

//2.创建连接对象--connection对象

Connection connection =

DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb2","root","123

456");

//3.建立小车并绑定sql语句

Statement statement = connection.createStatement();

//绑定sql语句

String sql = "select empno,ename,job from emp";

ResultSet set = statement.executeQuery(sql);

//4.将数据放入箱子,拉回客户端,并完成卸货.

//原理:类似于迭代器,开始指针指向表头,调用next方法会使指针向下移动一行,判断

当前行是否有数据,如果有,返回true,没有返回false

while (set.next()){

//第一种:根据sql语句中字段的下标取值,默认从1开始

//set里对应的是虚拟表的数据,所以我们这里的顺序跟虚拟表中字段的顺序一

// Object obj1 = set.getObject(1);

//第二种:通过字段名字(key)取值

// Object obj2 = set.getObject("empno");

// System.out.println(obj1+" "+obj2);

//完全通过字段名字(key)取值

int empno = set.getInt("empno"); //取int型的值

String name = set.getString("ename"); //取string型的值

String job = set.getString("job");

//循环外

//5.关闭资源

connection.close();

statement.close();

set.close();

1.不再使用new,直接使用反射

new的缺点:导致驱动被注册2次;强烈依赖数据库的驱动jar

替代方案:使用反射实现

Class.forName("com.mysql.jdbc.Driver");

2.创建连接对象的方式有三种

3.4.前面实现的是查找(用executeQuery())

ResultSet set = statement.executeQuery(sql);

现在实现的是增删改(统一用executeUpdate()

int num = statement.executeUpdate(sql);

使用放射jdbc

//注册使用反射--节省空间,开发方便

Class.forName("com.mysql.jdbc.Driver");

jdbc三中创建连接对象的方法

1三个参数

//Connection connection =

DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb2","root","123

456");

2两个参数

Properties properties = new Properties();

properties.setProperty("user","root");

properties.setProperty("password","123456");

Connection connection =

DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb2",properties)

;

3一个参数

Connection connection =

DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb2?

user=root&password=123456");

绑定sql语句

Statement statement = connection.createStatement();

定义sql语句

String sql = "insert into emp(empno,ename,job)

values(100,'bing','演员')";

执行sql语句

int num = statement.executeUpdate(sql); //给一个返回值判断sql是否执行成功

//5.关闭资源

connection.close();

statement.close();

//set.close();

jdbc的模型封装

对于从数据库接收到数据,我们一般是需要保存到模型中,一个模型对应数据库中的一张表

Class.forName("com.mysql.jdbc.Driver");

Connection connection =

DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb2?

user=root&password=123456");

Statement statement = connection.createStatement();

String sql = "select empno,ename,job from emp";

ResultSet set = statement.executeQuery(sql);

List<Emp> list = new ArrayList<>();

while (set.next()){

Emp emp = new Emp(set.getInt("empno"),set.getString("ename"),set.getString("job"));

list.add(emp);

}

connection.close();

statement.close();

set.close();

emp实体

public Emp(int empno, String ename, String job) {

this.empno = empno;

this.ename = ename;

this.job = job;

}

jdbc的异常处理

这里异常不应该声明,而是使用trycatch

//1.注册mysql的驱动

//反射--节省空间,开发方便

try {

Class.forName("com.mysql.jdbc.Driver");

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

Connection connection = null;

Statement statement = null;

ResultSet set = null;

try {

connection =

DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb2?

user=root&password=123456");

//3.建立小车并绑定sql语句

statement = connection.createStatement();

//绑定sql语句

String sql = "select empno,ename,job from emp";

//查

set = statement.executeQuery(sql);

List<Emp> list = new ArrayList<>();

while (set.next()) {

Emp emp = new Emp(set.getInt("empno"),

set.getString("ename"), set.getString("job"));

list.add(emp);

}

System.out.println(list);

}

catch (SQLException e) {

e.printStackTrace();

} finally {

//5.关闭资源--可选

if (connection != null) {

try {

connection.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

if (statement != null) {

try {

statement.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

if (set != null) {

try {

set.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

}

}

}

DBUtil工具类的封装

1.编写代码时使用面向对象的思想,尽量将代码进行封装,这里将数据库的链接和关闭等共同的

操作放入了DBUtils工具类中

2.对于共享的DBUtils工具类,不能每次发生一些变动(比如:更换数据库或者修改密码等操作),都

去更改代码.所以我们又将变化的部分封装了配置文件DBConfifig.properties.

配置文件DBConfifig.properties

driver=com.mysql.jdbc.Driver

url=jdbc:mysql://localhost:3306/mydb2

user=root

pwd=123456

//读取DBConfig文件的内容

//默认识别的路径是当前的工程

ResourceBundle resourceBundle =

ResourceBundle.getBundle("DBConfig");

mydriver = resourceBundle.getString("driver");

myurl = resourceBundle.getString("url");

myuser = resourceBundle.getString("user");

mypwd = resourceBundle.getString("pwd");

//1.注册mysql的驱动

//反射--节省空间,开发方便

try {

Class.forName(mydriver);

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

//自定义dbutils工具类以方便直接调用

 

public static Connection getConnection() throws SQLException {

//2.创建连接对象--connection对象

return DriverManager.getConnection(myurl,myuser,mypwd);

}

jdbc的批处理

每一次的sql操作都会占用数据库的资源。如果将N条操作先存储到缓存区中,然后再一次性刷

到数据库中,这就减少了与数据库的交互次数。因此可以提高效率。

addBatch(String sql):将sql语句添加到缓存中

executeBatch():将缓存中的sql一次性刷到数据库中

 

代码

 

Connection conn = null;

Statement stat = null;

try{

conn = DBUtils.getConnection();

stat = conn.createStatement();

int num = 0;

while(num<1003){

String sql = "insert into testbatch values

(null,'zs"+num+"','f')";

stat.addBatch(sql);//将sql语句添加到缓存中,

if(num%50==0){

stat.executeBatch();//缓存中每有50条都刷新一次。

}

num++;

}

stat.executeBatch();//循环结束后,将缓存中剩余的不足50条的全都刷新出去

}catch (Exception e){

e.printStackTrace();

}finally {

DBUtils.closeAll(conn,stat,null);

}

}

SQL注入问题

Statament对象发送的语句可以被改变结构,即如果之前在where中设置的是两个条件,那么可

以通过一些参数 比如 添加or 后面再跟其他条件。此时,where子句中是三个条件。这种情况

就叫做SQL注入。有安全隐患问题。

PreparedStatement类 预编译

PreparedStatement是Statement的子类型

- 此类型可以确定SQL语句的结构,无法通过其它方式来增减条件。

- 此类型还通过占位符 "?"来提前占位,并确定语句的结构。

- 提供了相应的赋值方式:

ps.setInt(int index,int value)

ps.setString(int index,String value)

ps.setDouble(int index,double value)

ps.setDate(int index,Date value)

index:表示sql语句中占位符?的索引。从1开始

value:占位符所对应的要赋予的值

- 执行方法:

ps.execute() ;------用于DDL和DML

ps.executeUpdate();-----用于DML

ps.executeQuery();-----用于DQL

sql语句:select * from user where name='chen' and password='' or 1='1'"

当前的错误称为sql注入.

Connection connection = null;

PreparedStatement statement = null;

ResultSet set = null;

User user = null;

try {

connection = DBUtil.getConnection();

//statement = connection.createStatement();

String sql = "select * from user where name=? and

password=?";//?占位符

statement =connection.prepareStatement(sql);

statement.setString(1, name);//第一个参数是?在sql语句中的位置,默

认从1开始

statement.setString(2, pwd);

set = statement.executeQuery();

//遍历

if (set.next()) {

user = new User();

user.setId(set.getInt("id"));

user.setName(set.getString("name"));

user.setPassword(set.getString("password"));

}

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} finally {

DBUtil.closeAll(connection, statement, set);

}

return user;

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值