第一天学习JDBC(1)-从创建到关闭

1.1 什么是JDBC

JDBC是JAVA的一个API,它的出现是为了规范统一对数据库的操作,简单来说,它可以让我们使用JAVA代码连接数据库,执行我们需要的SQL语句。使用JDBC前,我们需要导入相应数据库的驱动包。
包含JDBC的两个包:
java.sql
javax.sql

1.2 JDBC中的Connection

1.2.1 注册驱动程序并获得Connection

建立与数据库的连接之前,我们需要注册驱动程序,这里我们将用到DriverManager。

什么是DriverManager?
DriverManager是jdbc里管理和注册不同数据库driver的工具类,它的出现,是为了让我们可以通过加载配置文件加反射的方式来注册驱动,提高了代码的灵活性。

Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection(url,user,password);

当然,也可以用反射的方式来获得。

Driver driver=new com.mysql.jdbc.Driver();
DriverManager.registerDriver(driver);
Connection connection=DriverManager.getConnection(url,user,password);

查看com.mysql.jdbc.Driver源代码,我们发现以上的方法会重复注册两次驱动,结合以上,我们通常使用结合反射的方法来获取。
源码:

try {
    java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
    throw new RuntimeException("Can't register driver!");
}

1.2.2 Connection中的参数

user:数据库用户名
password:数据库密码
url:JDBC的URL,标记数据库位置,连接到那个数据库。
写法:
jdbc:mysql:[]//localhost:3306/test ?参数名:参数值

协议 :子协议 //:主机:端口号 /数据库名
可以简写为:jdbc:mysql:///sid
其他数据库的写法:

Oracle写法:jdbc:oracle:thin:@localhost:1521:sid
SqlServerjdbc:microsoft:sqlserver://localhost:1433; DatabaseName=sid

1.2.3 与Connection有关的方法

Connection:代表数据库的链接,与数据库的交互通过这个对象完成.
commit() :在链接上提交事务。
rollback() :在此链接上回滚事务。
setAutoCommit(boolean autoCommit):设置事务是否自动提交。
createStatement(sql):创建statement接口对象。
prepareStatement(sql) :创建PrepareSatement接口对象。
prepareCall(sql):创建CallableStatement接口对象。

1.3 Statement/PreparedStatement/CallableStatement

1.3.1 关于DQL、DDL和DML、DCL语句

DQL:与SELECT有关的语句,因此又称数据查询语言。
DML:与UPDATE、INSERT、DELETE有关的语句,因此又称数据操纵语言。
DDL:CREATE、ALTER、DROP与改变表的结构,表之间的关系有关的语句,因此又称数据定义语言。
DCL:与grant,deny,revoke等有关的语句,并且需要有一定用户权限,因此又称数据控制语言。

1.3.2 三者关系

CallableStatement接口继承自PreparedStatement,PreparedStatement又继承了Statement,Statement继承自Wrapper。
Statement和PreparedStatement都可以执行DDL和DML语句、DQL语句(对表进行变动以及查询表),CallableStatement只能执行DQL语句(查询sql语句)。
int executeUpdate(String sql):执行DDL和DML语句、DQL语句
ResultSet executeQuery(String sql) :执行DQL语句

1.3.3 什么是ResultSet

Resultset封装了executeQuery的执行结果,类似于迭代器,用游标标记当前指向第几行,默认指向第一行之前,因此每次想要获得数据之前,都要先使用ResultSet.next()方法,返回boolean类型,标记下一行是否还有数据。
同时,还提供如下方法:
previous():移动到前一行
absolute(int row):移动到指定行
beforeFirst():移动resultSet的最前面。
afterLast() :移动到resultSet的最后面。

Resultset有非常多的返回方法,例如getString,getInt….
其中我们可以根据索引号(当前数据位于返回数据中的第几列)或者返回的数据名来获取。比较常用的是后者,因为可以避免表修改列后发生的错误。
值得注意的是,当我们getBlob的时候,得到一个Blob对象后,blob要使用getBinaryStream()方法获得一个输出流,才能获得数据。

Blob blob = executeQuery.getBlob("file");
BufferedInputStream bufferedInputStream=new BufferedInputStream(blob.getBinaryStream());

1.3.4 Statement

Statement:用于执行静态 SQL 语句。
什么是静态语句呢?其实就是sql必须是写死的。在创建PreparedStatement 对象时就指定了SQL语句,该语句立即发送给数据库管理系统进行编译。
例如:

String sql="DELETE  FROM student WHERE id=4;";
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection(url,user,password);
Statement createStatement = connection.createStatement();
int count=createStatement.executeUpdate(sql);

其中sql可以修改我们需要的语句,但是我们需要修改参数的时候,只能重写sql语句。

1.3.5 PreparedStatement

PreparedStatement:用于执行预编译的 SQL 语句。
什么是预编译?
数据库管理系统直接运行编译后的SQL语句,而不是一开始才将它编译。
这样做的好处:
1.避免频繁编译SQL,造成数据库缓冲区溢出。
2.提高运行效率.
3.允许使用占位符,简化SQL的书写.
使用占位符实例代码如下:

PreparedStatement prepareStatement = connection.prepareStatement(sql);
prepareStatement.setString(1, user);
prepareStatement.setString(2, password);
ResultSet executeQuery = prepareStatement.executeQuery();

使用占位符有什么好处?当我们使用BeanUtil的时候可以简化书写.
PreparedStatement参数设置值,与ResultSet返回时获取值相同,只不过get改成set而已.
4.防止注入
什么是SQL注入?
简单点来说,将我们传入数据库的参数写成SQL命令,当这个参数进入数据库时,最后欺骗数据库,造成异常.

String user="ztf' OR 1=1 #";
String password="123";
String sql="SELECT * FROM loading WHERE user1=? AND password1=?;";
PreparedStatement prepareStatement = connection.prepareStatement(sql);
prepareStatement.setString(1, user);
prepareStatement.setString(2, password);
ResultSet executeQuery = prepareStatement.executeQuery();
if(executeQuery.next()){
System.out.println("登陆成功");
}
else{
System.out.println("登陆失败");
}

如上,如果使用Statement,user中的参数带 OR 1=1 #,将让SELECT * FROM loading WHERE user1=? AND password1=?;语句无条件返回一条或者多条数据.但是使用PreparedStatement不会有这样的情况.

1.3.6 CallableStatement接口

CallableStatement:用于执行存储过程的SQL语句。
值得注意的是,除了设置参数值之外,我们还可以获得返回参数.
使用的是CallableStatement中的getXX方法,与set方法相同.

CallableStatement prepareCall = connection.prepareCall("CALL pro_getDept(?,?);");
for(int i=1;i<=6;i++){
prepareCall.setInt(1, i);
prepareCall.registerOutParameter(2, java.sql.Types.VARCHAR);
prepareCall.executeQuery();
String name=prepareCall.getString(2);
System.out.println(i+":"+name);
}

1.4 记得关闭资源

提别注意的是,Connection是比较稀有的资源,Statement ,Resultset等也会占用大量内存资源。如果没有及时关闭,有可能导致宕机。
关闭原则:先创建后关,后创建先关,量晚的创建,尽量早的释放。

if(resultSet!=null){
    try {
        resultSet.close();
    } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
if(statement!=null){
    try {
        statement.close();
    } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
if(connection!=null){
    try {
        connection.close();
    } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值