一、JDBC概念
Java Database connecitivity:java连接访问关系型数据库技术。
SUN公司提供的一套执行SQL语句的API,主要由接口组成,可以为多种关系型数据库提供统一访问。
Sun公司为简化数据库开发,定义了一套JDBC接口,这套接口由数据库厂商去实现,开发人员只需要学习JDBC接口,并通过JDBC加载具体的驱动,就可以操作数据库。
二、JDBC开发条件
1.JDBC接口:
- java.sql包
- javax.sql包
三、JDBC开发原理![这里写图片描述](https://img-blog.csdn.net/20180611225900805?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2dlZ2V5YW54aW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
四.JDBC开发步骤
- 1)通过DriverManager 实现对驱动的注册
- 2) 建立连接,
- 3)发送sql指令。
- 4)接收请求并处理
- 5)释放资源
数据库的连接数是有限的,比如200个,必须释放完了才能给后面用。
五.入门案例
1)创建java程序,导入mysql的驱动jar包(jar包就是很多.class文件。可以直接运行).
- 协议 IP 端口 其他参数
- jdbc:mysql://localhost(127.0.0.1):3306/bd1804
- 以前的url都是http,现在是https,s指的是ssl
ResultSet rs = null;
Statement stmt = null;
Connection conn = null;
try {
//1.使用DriverManager实现对驱动的注册
//com.mysql.jdbc.Driver是java.sql.Driver的实现类
//DriverManager.registerDriver(new Driver()); //加载两次
//获取Dirver的class对象
//1.实现驱动注册只有一个方法DriverManager.registerDriver()
//2.在加载Driver类调用registerDriver()
//3.静态代码块
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/bd1804?useSSL=true",
"root",
"root");
//获取connection的元数据信息(元数据:解释数据的数据)
//封装了与连接相关的所有信息(数据库类型 版本 用户 ip等)
/*DatabaseMetaData md = conn.getMetaData();
System.out.println(md.getDatabaseProductName());
System.out.println(md.getDatabaseProductVersion());
System.out.println(md.getURL());
System.out.println(md.getUserName());
System.out.println(md.getSchemas());*/
//3.发送请求
String sql = "select * from stu";
//创建stmt对象用于发送sql指令
stmt = conn.createStatement();
//rs底层维护的是一个指向结果集的游标
rs = stmt.executeQuery(sql);
//4.处理结果
//逐行获取
//rs的元数据
//ResultSetMetaData m = rs.getMetaData();
while(rs.next()){
//获取当前行的数据
int sid = rs.getInt("sid");
String sname = rs.getString("sname");
System.out.println("sid:"+sid+"\tsname:"+sname);
}
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
if(rs!=null){
rs.close();
}
if(stmt!=null){
stmt.close();
}
if(conn!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
六.JDBC详解
(A)DriverManager类(驱动管理器):
- 实现具体的驱动的注册管理;
- 获取连接
//1.实现驱动注册只有一个方法DriverManager.registerDriver()
//2.在加载Driver类调用registerDriver()
//3.静态代码块
Class.forName("com.mysql.jdbc.Driver");
不建议:
DriverManager.registerDriver(new Driver()); //加载两次
(B)Connection接口(java.sql):
由DriverManager创建。可以用于创建发送Sql命令的Statement对象。
DriverManager.getConnection("jdbc:mysql://localhost:3306/bd1804?useSSL=true", "root", "root");
//url:统一资源定位符 协议:子协议://ip:port/dbname
//获取connection的元数据信息(元数据:解释数据的数据)
//封装了与连接相关的所有信息(数据库类型 版本 用户 ip等)
DatabaseMetaData md = conn.getMetaData();
System.out.println(md.getDatabaseProductName());
System.out.println(md.getDatabaseProductVersion());
System.out.println(md.getURL());
System.out.println(md.getUserName());
System.out.println(md.getSchemas());
(C)Statement:用于发送sql命令
- execute方法:用于发送任意一条sql命令,返回resultSet时返回ture,其他返回false;
- executeQuery()方法:发送insert/update/delte/ddl语句,返回int
- addBatch()以及executeBatch()执行批处理命令。
(D)ResultSet :接口集
底层维护一个指向结果集的游标。封装了跟结果相关的信息。
while(rs.next()){
//获取当前行的数据
int sid = rs.getInt("sid");
String sname = rs.getString("sname");
System.out.println("sid:"+sid+"\tsname:"+sname);
}
//rs的元数据
//封装和结果相关的信息。
ResultSetMetaData m = rs.getMetaData();
七、登陆问题
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/bd1804?useSSL=true",
"root",
"root");
//3.借助于stmt发送sql
String sql = "select * from userinfo where sname = '"
+name+"' and password = '"+password+"'";
stmt = conn.createStatement();
//4.接收响应并处理
rs = stmt.executeQuery(sql);
if(rs.next()){
System.out.println("登录成功");
}else{
System.out.println("登录失败");
}
} 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注入攻击:对于输入参数判断不完全,导致输入参数改变原本的sql,实现对数据库恶意攻击方式;
- 根本原因:输入参数改变原本的sql格式(参数拼接字符串方式);
八、PreparedStatement
- 接口:statement的子接口;
- 能够实现对Sql的发送。
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/bd1804?useSSL=true",
"root",
"root");
//3.借助于ps发送sql
//?代表占位符
String sql = "select * from userinfo where sname = ? and password = ?";
//创建ps对象(预编译)
ps = conn.prepareStatement(sql);
//给占位符位置进行赋值
ps.setString(1, name);
ps.setString(2, password);
//4.接收响应并处理
rs = ps.executeQuery();
if(rs.next()){
System.out.println("登录成功");
}else{
System.out.println("登录失败");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally{
try {
if(rs!=null){
rs.close();
}
if(ps!=null){
ps.close();
}
if(conn!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
statement 和 PreparedStatement的区别
- 1.PreparedStatement使用占位符能够防止sql的注入攻击,安全性较高
- 2.PreparedStatement编写简单;
- 3.PreparedStatement有预编译。将语句先拿到缓存,提升查询效率。
- (sql语句到mysql里查找内容会有语法检查和语义检查。正确后才去查找。PreparedStatement预编译也是这个作用)
- 4.但是在批处理中,statement能够实现不同的sql的批量处理,但是PreparedStatement不行。
- (还是由于预编译)。
九、增删改
Connection conn = null;
PreparedStatement ps = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql:///bd1804?useSSL=true", "root", "root");
//阻止默认提交
conn.setAutoCommit(false);
String sql = "insert into userinfo(sname,password) values(?,?)";
ps = conn.prepareStatement(sql);
ps.setString(1, sname);
ps.setString(2, password);
int rows = ps.executeUpdate();
//提交事务
conn.commit();
System.out.println(rows);
} catch (Exception e) {
e.printStackTrace();
//事务回滚
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
}finally{
try {
if(ps!=null){
ps.close();
}
if(conn!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
十、其他操作
//分页查询(根据传入页码不同展示相应的数据)
//select * from emp limit index,length
public static void queryByPage(int pageIndex,int size){
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql:///bd1804?useSSL=true", "root", "root");
String sql = "select * from emp limit ?,?";
ps = conn.prepareStatement(sql);
ps.setInt(1, (pageIndex-1)*size);
ps.setInt(2, size);
rs = ps.executeQuery();
while(rs.next()){
String ename = rs.getString("ename");
BigDecimal sal = rs.getBigDecimal("sal");
System.out.println("ename="+ename+"\tsal="+sal);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally{
try {
if(rs!=null){
rs.close();
}
if(ps!=null){
ps.close();
}
if(conn!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
//批量处理(增删改)
public static void batchStmt(){
Connection conn = null;
Statement stmt = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql:///bd1804?useSSL=true", "root", "root");
String sql1 = "insert into stu(sname,cid,sex) values('ww',1,'男')";
String sql2 = "update stu set sex = 'man' where sid = 4";
String sql3 = "delete from stu where sid = 5";
stmt = conn.createStatement();
stmt.addBatch(sql1);
stmt.addBatch(sql2);
stmt.addBatch(sql3);
int[] rows = stmt.executeBatch();
System.out.println(Arrays.toString(rows));
} 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();
}
}
}
//ps的批处理
public static void batchPs(){
Connection conn = null;
PreparedStatement ps = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql:///bd1804?useSSL=true", "root", "root");
String sql = "insert into stu(sname,cid,sex) values(?,?,?)";
ps = conn.prepareStatement(sql);
ps.setString(1, "ss");
ps.setInt(2, 1);
ps.setString(3, "man");
ps.addBatch();
ps.setString(1, "dd");
ps.setInt(2, 1);
ps.setString(3, "woman");
ps.addBatch();
int[] rows = ps.executeBatch();
System.out.println(Arrays.toString(rows));
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
if(ps!=null){
ps.close();
}
if(conn!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}