一、JDBC的原理
1、概念
Java DataBase Connectivity:java数据库连接技术,简称JDBC.
它是使用java语言编写的一套API.为多种关系型数据库提供了统一接口。
同时,也是一个“低级”接口,在其之上可以使用“高级”接口,更方便的连接数据库。
2、目的
为了给程序员提供同一种方式连接不同的数据库(提供一个与任何数据库的java连接界面)
3、原理
JDBC负责提供接口
数据库厂商使用自己数据库的特点来实现接口。
程序员调用接口,实际上底层调用数据库厂商实现的部分
实际工作过程
(1)加载驱动,建立连接
(2)获取Sql语句执行对象
(3)执行SQl语句
(4)处理结果集
(5)关闭连接
4、接口与类型
(1)驱动管理类型:DriverManager
static Connection getConnection(url,user,password)
作用: 通过地址,数据库用户名,用户密码 获取连接对象
(2)连接接口:Connection
Statement createStatement()
作用:获取一个SQL语句编译对象
PreparedStatement prepareStatement(String sql)
作用:获取一个SQL语句预编译对象
(3)SQL语句对象接口:
Statement: 用于编译静态SQL语句(编译多次)。
boolean execute(String sql):用来执行DDL语言
ResultSet executeQuery(String sql):用于执行DQL语言
int executeUpdate(String sql):用于执行DML语言
void addBatch(String sql):添加批处理
int[] executeBatch(): 执行批处理
PreparedStatement:用于编译静态SQL语句,是Statement的一个子类型,执行效率比Statement要高(只编译一次)
boolean execute():用来执行DDL语言
ResultSet executeQuery():用来执行DQL语言
int executeUpdate():用于执行DML语言
void addBatch():添加批处理
int[] executeBatch():执行批处理
(4)结果集接口:ResultSet
在进行DQL操作时, 将查询的所有记录信息封装到ResultSet对象中 .
boolean next(): 询问结果集对象中是否有下一行记录。
如果返回true,光标会自动移到下一行。
还提供了一些数据库类型转java数据类型的方法:
int getInt(int columnIndex)/getInt(String columnName)
double getDouble(int columnIndex)/getDouble(String columnName)
String getString(int columnIndex)/getString(String columnName)
Date getDate(int columnIndex)/getDate(String columnName)
.........
5、驱动
Oracle
jar包:ojdbc5.jar/ojdbc14.jar
Class.forName("oracle.jdbc.driver.OracleDriver");
Mysql
jar包: mysql-connector-java-5.1.7-bin.jar
Class.forName("com.mysql.jdbc.Driver");
二、JDBC编程基础
实际开发中:
1、先将驱动包导入项目下(引用和复制到项目下两种方式)
2、加载驱动类
3、使用驱动管理类型获取连接对象
4、获取SQL语句执行对象
5、编写SQL语句,进行编译与执行
6、处理结果集
7、关闭连接
.......
三、工具类的封装DBUtil
从上述练习中发现,每次都需要加载驱动,建立链接。其中的参数我们书写的次数比较多。
方法1:
为了方便,为了节省资源,我们可以使用静态块来加载驱动,
将参数值当成类的静态属性进行封装。 (加载一次就可以)
方法2:
使用Properties 读取配置文件里的信息
(将可能需要改变的信息存储在配置文件中)(用#注释)
Mysql:
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/bd1802
user=root
password=123456
Oracle:
driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:xe
user=scott
password=tiger
通常情况下都会选择方法2
四、异常
jdbc发生的异常一般都是SQLException或者是其子类异常是检查性异常。使用try-catch机制处理一下。
finally里通常用来进行关闭数据库操作。
五、SQL注入:(injection)
在使用Statement时,因为Statement会对静态SQL语句进行编译。
有可能会改变SQL语句的结构。因此有注入安全隐患。
create table login_info(
login_id int primary key auto_increment,
login_user varchar(20) unique,
login_pwd varchar(50) not null,
login_phone varchar(11)
);
insert into login_info values(1001,'zhangsan123','111111','13100001111');
insert into login_info values(1002,'lisi123456','888888','13700001111');
select * from login_user='zhangsan123' and login_pwd='wang';
由上面两个条件的sql结构变成了下面的三个条件的结构,就是SQL注入现象。
select * from login_user='zhangsan123' and login_pwd='wang' or 'a' = 'a';
后来改用Statement的子类PreparedStatement来代替。PreparedStatement叫预编译sql语句类型,对静态sql语句编译一次。编译后无法再改变sql语句结构
六、PreparedStatement的用法
可以对静态SQL语句使用问号"?"充当占位符。
如:
select * from login_info where login_user = ? and login_pwd= ?
使用此类中提供的类型转换方法进行给问号赋值
ps.setInt(int parameterIndex,int value)
ps.setDouble(int parameterIndex,double value)
ps.setString(int parameterIndex,String value)
ps.setDate(int parameterIndex,Date value)
七、Junit:java方法的另外一种测试方式。
(1)导入Junit4的jar
(2)在非静态方法上添加注解@Test
(3)选中非静态方法的名称右键运行或者在类的树形结构中选中方法运行。
@Before:此注解的位置也是非静态方法上。
运行时机:在运行@Test注解方法前会自动执行。
@After: 位置是在非静态方法上。
运行时机:在运行@Test注解方法后会自动执行。
八、JDBC对事务的支持
事务要满足四个条件:ACID
原子性:一个事务,要么成功,要么回滚(撤回)
一致性:事务开始前的数据要和结束后的数据保持一致。
隔离性:一个事务正在进行,另外的事务要等待。
持久性:事务提交后,数据的改变是永久性的。
JDBC对DML语言的操作是默认提交的。当有多个DML操作时,我们应该取消自动提交 。改为手动提交
Connection接口提供了一个方法
void setAutoCommit(boolean flag):(在事务开始前)
true:表示自动提交
false:表示取消自动提交
void commit(): 提交事务(在事务完成后)
void rollback():事务回滚(通常放在catch中)
九、批处理
在进行插入数据操作时,有的时候,一条一条的操作,比较耗时。我们可以进行批量的插入操作。
Statement:
addBatch(String sql)
executeBatch():
PreparedStatement:
addBatch():
executeBatch():
十、
1、oracle学习版安装
(1)添加SYS和System用户的口令
(2)我们要启动数据库主页,使用System进行登录
(3)创建一个普通用户scott,密码tiger
2、 连接方式
(1)命令提示符界面
选择自带的运行SQl命令行界面
输入 conn username/password
(2)使用客户端sqldeveloper
连接名:(随意)
用户名:scott
口令:(密码)
主机名:ip
端口号: tcp/ip协议,1521 /http协议的端口号默认是8080/80
SID:oracle特有的唯一标识符 xe/orcl
(3)使用JDBC连接oralce数据库
3、使用
数据类型:
数字类型:number
number(m):表示最长m位整数
number(m,n):表示整数位最长m-n,小数点后保留n位。
字符串类型:
char(m):固定长度字符串类型
varchar(m)
varchar2(m):oracle独有的一个可变字符串类型
Blob
日期类型:date: 年月日时分秒
timestamp:可以精确到纳秒
十一、mysql自增序列的获取
有的时候,两张表中的字段可能有关系,当向一张表插入数据时,另外一张表可能需要这张表的数据。
直接获取序列的自增值:
preparedStatement(String sql,String[] columnNames)
将主键字段的名称设置为数组形式传入第二个参数上
例: String sql="insert into student values(null,?,?)";
PreparedStatement ps=conn.prepareStatement(sql,new String[] {"sid"});
调用获取自增主键的值的方法:
ps.getGeneratedKeys()
例:通过student的sid值向表sc中插入数据
student表
sid sname sage
1001 'zhangsan' 23
sc选课表
scid sid scname
1 1001 '高数'
思考:表、记录与类、对象有什么关系
十二、DAO思想(Data Access Object )数据访问对象
在开发时,我们一定会使用,数据库,编程语言的APP
存储
APP------------------->数据库
<-------------------
获取
ORM:对象关系映射(Object relation mapping)
表的一条记录映射成类的一个对象
类的一个对象映射成表的一条记录
开发思路:
现在主流开发模式:MVC架构思想
M:model,模型层--(业务层,持久层)
V:View, 视图层--(用户所能操作与看到的部分)
C:Controller,控制层--(控制用户操作与模型层的逻辑走向)
(1)程序与数据库交互的层次称之为持久层
第一步: 通过ORM设计实体类
第二步:设计一个接口,提供与数据库交互的各个功能
第三步:编写此接口的实现类,完善功能逻辑。
十三、在开发项目时需要注意的。
包的设计:
com.hyxy.jdbc.util(数据库连接,关闭的封装类)
com.hyxy.jdbc.entity(实体类)
com.hyxy.jdbc.dao(接口)
com.hyxy.jdbc.dao.impl(接口实现类)
com.hyxy.jdbc.test(测试类)
十四、
DAO思想的扩展:
(1)编写实体类型(orm)
(2)提供接口(持久层的各个功能)
(3)实现对应数据库的接口
(4)提供Dao工厂类型
当使用DAO工厂时,如果我们想移植到不同的数据库下。
需要改动的地方:
(1)jar包,配置文件
(2)工厂类中的静态方法里的实现类型对象
============================================
oracle的分页查询:
伪列:rownum. 给每一行记录添加序号。从1开始,不能直接用
查询第6条到第10条
select * from emp where rownum>=6 and rownum<=10
上述写法不正确:
使用子查询:
(1)第一步:按照排序规则
select * from emp order by deptno;
(2)第二步: 在分配行号
select rownum rn,e.* from (select * from emp order by deptno) e;
(3)第三步:分页查询,可以进行范围确定
select * from
(select rownum rn,e.* from (select * from emp order by deptno) e)
where rn between 6 and 10;
建表后修改约束:
mysql如下:
/*修改emp表中的empno字段为主键约束和自增*/
/*方法1*/
alter table emp change empno empno int primary key auto_increment;
/*方法2*/
alter table emp add constraint cons_empno primary key(empno);
alter table emp modify empno int auto_increment;
insert into emp (ename,job)values('batman','salesman');
select * from emp where ename='batman';
oracle如下:
1:为字段添加主键约束:
alter table emp add constraint cons_empno primary key(empno);
2:使用序列,
(1)创建序列对象
create sequence seq_emp start with 9000;
(2)序列的使用:
两个伪列
nextval:获取下一个值后,此值为当前值
currval:必须在使用一次nextval后才生效
用法:
select seq_emp.nextval from dual;
select seq_emp.currval from dual;