技术之博大精深 2020-06-10
JDBC
是用于在Java
语言编程中与数据库连接的API
.JDBC
是一个规范,它提供了一整套接口,允许以一种可移植的访问底层数据库API
。使用JDBC驱动程序
来访问数据库,并用于存储数据到数据库中.
解释上面两幅图:
java应用程序通过JDBC API首先连接到JDBC Driver,这些JDBC驱动器都是由各大数据库厂家针对JDBC提供的,我们可以在网上下载jar包来使用,然后通过JDBC驱动器就能连接到我们的数据库了。
第一步 添加驱动
1.在项目当中创建一个文件夹为lib 2.把Mysql驱动包复制到该文件夹下 3.builder path 编译路径 复制代码
第二步 连接到数据库
package con.meils.jdbc.conn; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class ConnectionClass { public static void main(String[] args) throws ClassNotFoundException, SQLException { // TODO Auto-generated method stub // 1、加载驱动 // 把com.mysql.jdbc.Driver这份字节码加载进JVM // 当一份字节码加载进JVM的时候,就会执行字节码文件中的静态代码块 // 这里加载该字节码之后会实例化一个驱动器 Class.forName(<span class="hljs-string">"com.mysql.jdbc.Driver"</span>); // 2、连接 String url = <span class="hljs-string">"jdbc:mysql://localhost:3306/mytest"</span>; String username = <span class="hljs-string">"root"</span>; String password = <span class="hljs-string">"zjj19970517"</span>; Connection connection = DriverManager.getConnection(url, username, password); // 3、验证连接 System.out.println(connection); // 如果有输出,表明连接成功 }
}
复制代码
第三步 操作数据库创建表
package con.meils.jdbc.ddl; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; public class CreateTable { public static void main(String[] args) throws Exception { // TODO Auto-generated method stub // 1\加载驱动 // 把com.mysql.jdbc.Driver这份字节码加载进JVM // 当一份字节码加载进JVM的时候,就会执行字节码文件中的静态代码块 // 这里加载该字节码之后会实例化一个驱动器 Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/jdbc_db"; String username = "root"; String password = "zjj19970517"; // 2\ 连接数据库 Connection connection = DriverManager.getConnection(url, username, password); // 3\创建sql语句 String sql = "create table stu (id int , name varchar(20), age int)"; // 4\执行sql语句 Statement st = connection.createStatement(); int row = st.executeUpdate(sql); // 5\释放 st.close(); connection.close(); } } 复制代码
为什么要释放资源呢?
第四步 插入数据
package con.meils.jdbc.dml; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; public class InsertClass { public static void main(String[] args) { // TODO Auto-generated method stub // ================ 插入数据 ================ Connection conn = null; Statement st = null; try { // 1、加载驱动 Class.forName(<span class="hljs-string">"com.mysql.jdbc.Driver"</span>); // 2、创建连接 String url = <span class="hljs-string">"jdbc:mysql://localhost:3306/mytest"</span>; String user = <span class="hljs-string">"root"</span>; String password = <span class="hljs-string">"zjj19970517"</span>; conn = DriverManager.getConnection(url, user, password); // 3、创建sql语句 String sql = <span class="hljs-string">"insert into stu values(1, ‘zjj‘, 20)"</span>; st = conn.createStatement(); // 4、执行语句 int row = st.executeUpdate(sql); System.out.println(row); }catch (Exception e) { e.printStackTrace(); } finally { // 5、释放 <span class="hljs-keyword">if</span>(st!=null) { try { st.close(); }catch (Exception e) { e.printStackTrace(); } } <span class="hljs-keyword">if</span>(conn!=null) { try { conn.close(); }catch (Exception e) { e.printStackTrace(); } } } }
}
复制代码
第五步 查询操作
package con.meils.jdbc.dql; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class QueryClass { public static void main(String[] args) throws SQLException, ClassNotFoundException { // TODO Auto-generated method stub // ================ 查询数据 ================ // 1\加载驱动 // 把com.mysql.jdbc.Driver这份字节码加载进JVM // 当一份字节码加载进JVM的时候,就会执行字节码文件中的静态代码块 // 这里加载该字节码之后会实例化一个驱动器 Class.forName(<span class="hljs-string">"com.mysql.jdbc.Driver"</span>); String url = <span class="hljs-string">"jdbc:mysql://localhost:3306/mytest"</span>; String username = <span class="hljs-string">"root"</span>; String password = <span class="hljs-string">"zjj19970517"</span>; // 2\ 连接数据库 Connection connection = DriverManager.getConnection(url, username, password); // 3\创建sql语句 String sql = <span class="hljs-string">"select count(*) as total from stu"</span>; // 查询一共有几行数据 // 4\执行sql语句 Statement st = connection.createStatement(); ResultSet rs = st.executeQuery(sql); <span class="hljs-keyword">if</span>(rs.next()) { int count = rs.getInt(<span class="hljs-string">"total"</span>); System.out.println(count); // 1 } // 5\释放 st.close(); connection.close(); }
}
复制代码
数据类型对照表:
上面我们基本学会了如何与数据库打交道,但是这样使用存在许多的弊端,比如:每一步操作都进行一次数据库连接,造成浪费,所以我们在实际中要使用DAO思想来处理。
DAO(Data Access Object)数据存储对象,介于业务逻辑层和持久层之间,实现持久化数据访问。
不使用DAO的时候:
使用DAO的情况:
案例
我们可以编写一个DAO接口,定义了常用的数据库操作方法,这时候我们同时会连接多个数据库,比如是mysql 和 oracle ,我们可以分别实现oracleDao和mysqlDao两个类,不同类里面定义不同的操作数据库的代码,实现的功能确实相同的。
所以面向接口编程是很重要的,也是一个很好的方式。
目录如下
内容实现:
接口实现类的具体内容:
package com.meils.jdbc.dao.impl; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; import java.util.ArrayList; import java.util.List; import com.meils.jdbc.dao.IStudentDao; import com.meils.jdbc.domain.Student; import com.meils.jdbc.utils.JdbcUtil; /** 实现DAO接口的类 @author apple */ public class StudentDaoImpl implements IStudentDao{ @Override /** * 存储学生 * @param stu */ public void save(Student stu) { // TODO Auto-generated method stub Connection conn = null; PreparedStatement ps = null; try { // 连接数据库 conn = JdbcUtil.getConnection(); String sql = <span class="hljs-string">"insert into student (name, age) values (? , ?)"</span>; // 创建预编译 ps = conn.prepareStatement(sql); ps.setString(1, stu.getName()); ps.setInt(2, stu.getAge()); // 执行更新 ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } finally { JdbcUtil.close(conn, ps, null); } } @Override public void delete(int id) { Connection conn = null; PreparedStatement ps = null; try { // 连接数据库 conn = JdbcUtil.getConnection(); String sql = <span class="hljs-string">"delete from student where id = ?"</span>; // 创建预编译 ps = conn.prepareStatement(sql); ps.setInt(1, id); // 执行更新 ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } finally { JdbcUtil.close(conn, ps, null); } } @Override public void update(int id, Student stu) { Connection conn = null; PreparedStatement ps = null; try { conn = JdbcUtil.getConnection(); String sql = <span class="hljs-string">"update student set name=?, age=? where id = ? "</span>; ps = conn.prepareStatement(sql); ps.setString(1, stu.getName()); ps.setInt(2, stu.getAge()); ps.setInt(3, id); // 执行 ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } finally { JdbcUtil.close(conn, ps, null); } } @Override public Student findOne(int id) { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = JdbcUtil.getConnection(); // sql语句 String sql = <span class="hljs-string">"select * from student where id = ?"</span>; ps = conn.prepareStatement(sql); ps.setInt(1, id); // 执行 rs = ps.executeQuery(); <span class="hljs-keyword">if</span> (rs.next()) { // 保存数据 Student stu = new Student(); stu.setName(rs.getString(<span class="hljs-string">"name"</span>)); stu.setAge(rs.getInt(<span class="hljs-string">"age"</span>)); stu.setId(rs.getInt(<span class="hljs-string">"id"</span>)); <span class="hljs-built_in">return</span> stu; } } catch (Exception e) { e.printStackTrace(); } finally { // 销毁 JdbcUtil.close(conn, ps, rs); } <span class="hljs-built_in">return</span> null; } @Override public List<Student> <span class="hljs-function"><span class="hljs-title">findAll</span></span>() { Connection conn = null; Statement st = null; ResultSet rs = null; try { conn = JdbcUtil.getConnection(); st = conn.createStatement(); String sql = <span class="hljs-string">"select * from student "</span>; rs = st.executeQuery(sql); List<Student> list = new ArrayList<Student>(); <span class="hljs-keyword">while</span> (rs.next()) { Student stu = new Student(); stu.setName(rs.getString(<span class="hljs-string">"name"</span>)); stu.setAge(rs.getInt(<span class="hljs-string">"age"</span>)); stu.setId(rs.getInt(<span class="hljs-string">"id"</span>)); list.add(stu); } <span class="hljs-built_in">return</span> list; } catch (Exception e) { e.printStackTrace(); } finally { JdbcUtil.close(conn, st, rs); } <span class="hljs-built_in">return</span> null; }
}
复制代码
编写测试类:
package com.meils.jdbc.dao.test; import java.util.List; import org.junit.Test; import com.meils.jdbc.dao.IStudentDao; import com.meils.jdbc.dao.impl.StudentDaoImpl; import com.meils.jdbc.domain.Student; /** * StudentDao测试类 * @author apple */ public class StudentDaoTest { public static void main(String[] args) { // TODO Auto-generated method stub } @Test public void save() { Student stu = new Student(); stu.setName("张伟"); stu.setAge(21); IStudentDao dao = new StudentDaoImpl(); dao.save(stu); } @Test public void delete() { IStudentDao dao = new StudentDaoImpl(); dao.delete(4); } @Test public void update () { Student stu = new Student(); stu.setName("mmmmm"); stu.setAge(16); IStudentDao dao = new StudentDaoImpl(); dao.update(5, stu); } @Test public void findOne() { IStudentDao dao = new StudentDaoImpl(); Student stu = dao.findOne(5); System.out.println(stu); } @Test public void findAll() { IStudentDao dao = new StudentDaoImpl(); List<Student> allStu = dao.findAll(); System.out.println(allStu); } } 复制代码
JDBC工具类:
package com.meils.jdbc.utils; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; /** * JDBC 工具类 * @author apple * */ public class JdbcUtil { // 配置信息 public static String driverName = "com.mysql.jdbc.Driver"; public static String url = "jdbc:mysql://localhost:3306/mytest"; public static String userName = "root"; public static String password = "zjj19970517"; static { try { // 加载驱动,因为是在static块中,所以只会加载一次 Class.forName(JdbcUtil.driverName); }catch (Exception e) { e.printStackTrace(); } } /** * 连接数据库 * @return 返回连接对象 */ public static Connection getConnection() { try { return DriverManager.getConnection(JdbcUtil.url, JdbcUtil.userName, JdbcUtil.password); } catch (Exception e) { e.printStackTrace(); } return null; } /** * 关闭连接,并释放资源 * @param conn * @param st * @param rs */ public static void close(Connection conn, Statement st, ResultSet rs) { if(conn!=null) { try { conn.close(); }catch(Exception e) { e.printStackTrace(); } } if(st!=null) { try { st.close(); }catch(Exception e) { e.printStackTrace(); } } if(rs!=null) { try { rs.close(); }catch(Exception e) { e.printStackTrace(); } } } } 复制代码
Statement 是父接口,PreparedStatement 和 CallableStatement 是子接口。 Statement 用于java应用程序与数据库之间的传送数据,比如传送sql语句过去,到数据库执行操作。 Statement 用于通用的访问,使用静态sql,其实并不好,容易SQL注入 PreparedStatement 用于预编译模版SQL语句,可以在运行的时候传入参数 CallableStatement 访问存储过程的时候使用复制代码
防止SQL注入:
JDBC的另一种封装方法:
package com.meils.jdbc.db; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class MysqlDB { Connection conn = null; // 创建连接对象 Statement st = null; // 创建编译语句对象 PreparedStatement ps = null; // 创建预编译语句对象 ResultSet rs1 = null; // 结果集 // 配置信息 // 驱动名称 private static final String driverName = <span class="hljs-string">"com.mysql.jdbc.Driver"</span>; // 数据库的地址 private static final String URL = <span class="hljs-string">"jdbc:mysql://localhost:3306/mytest"</span>; // 数据库登录用户名 private static final String userName = <span class="hljs-string">"root"</span>; // 数据库登录密码 private static final String <span class="hljs-built_in">pwd</span> = <span class="hljs-string">"zjj19970517"</span>; /** * 连接数据库 * @<span class="hljs-built_in">return</span> */ public Connection <span class="hljs-function"><span class="hljs-title">getConnection</span></span>() { try { Class.forName(driverName); this.conn = DriverManager.getConnection(URL, userName, <span class="hljs-built_in">pwd</span>); System.out.println(<span class="hljs-string">"连接成功"</span>); <span class="hljs-built_in">return</span> conn; } catch (Exception e) { e.printStackTrace(); } <span class="hljs-built_in">return</span> null; } // 构造函数 public <span class="hljs-function"><span class="hljs-title">MysqlDB</span></span>() { this.getConnection(); } /** * 查询 * @param sql sql语句,完整的语句,查询一般比较安全 * @<span class="hljs-built_in">return</span> */ public ResultSet query(String sql) { try { this.st = this.conn.createStatement(); this.rs1 = this.st.executeQuery(sql); <span class="hljs-built_in">return</span> rs1; } catch (SQLException e) { e.printStackTrace(); } <span class="hljs-built_in">return</span> null; } /** * 更新 * @param sql // 预编译sql语句 * @param args // 参数数组 */ public void update(String sql, String [] args) { try { this.ps = this.conn.prepareStatement(sql); <span class="hljs-keyword">for</span> (int i = 0 ; i < args.length ; i++) { this.ps.setString(i+1, args[i]); } this.ps.executeUpdate(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { this.close(); } } /** * 删除 * @param sql * @<span class="hljs-built_in">return</span> */ public int delete(String sql){ try { this.st = this.conn.createStatement(); int num = this.st.executeUpdate(sql); <span class="hljs-built_in">return</span> num; } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { this.close(); } <span class="hljs-built_in">return</span> 0; } /** * 释放资源 */ public void <span class="hljs-function"><span class="hljs-title">close</span></span> () { try { <span class="hljs-keyword">if</span>(rs1!=null) { rs1.close(); } <span class="hljs-keyword">if</span>(st!=null) { st.close(); } <span class="hljs-keyword">if</span>(ps!=null) { ps.close(); } <span class="hljs-keyword">if</span>(conn!=null) { conn.close(); } } catch (SQLException e) { // TODO: handle exception e.printStackTrace(); } }
}
复制代码
测试以下:
package com.meils.jdbc.db; import java.sql.ResultSet; import java.sql.SQLException; public class Test { public static void main(String[] args) { // TODO Auto-generated method stub // Conn(); delete(); } // 测试连接 public static void Conn() { MysqlDB m = new MysqlDB(); } // 测试查询 public static void queryTest() { MysqlDB m = new MysqlDB(); String sql = "select * from student"; ResultSet result = m.query(sql); System.out.println(result); try { while (result.next()) { System.out.println(result.getString("name")); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { m.close(); } } // 更新 public static void update() { MysqlDB m = new MysqlDB(); String sql = "update student set name = ? where id = ?"; String [] args = {"梅子111", "7"}; m.update(sql, args); } // 删除 public static void delete() { MysqlDB m = new MysqlDB(); String sql = "delete from student where id = 8"; System.out.println(m.delete(sql)); } } 复制代码
首先我们熟悉一下存储过程
// 新建存储过程 DELIMITER // create PROCEDURE getStudent1(in n varchar(20)) BEGIN select * from student <span class="hljs-built_in">where</span> name = n;
END //
DELIMITER ;
// 执行
call getStudent1(‘张锦杰‘);
复制代码
package com.meils.jdbc.dao.test; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import com.meils.jdbc.domain.Student; import com.meils.jdbc.utils.JdbcUtil; public class ProductTest { public static void main(String[] args) { CallableStatement cstmt = null; try { //1.连接 Connection conn = JdbcUtil.getConnection(); //2. CallableStatement cs = conn.prepareCall("{ call getStu(?)}"); //3.设置参数 cs.setString(1, "张锦杰"); //4.执行 ResultSet rs = cs.executeQuery(); if(rs.next()) { Student stu = new Student(); stu.setId(rs.getInt("id")); stu.setName(rs.getString("name")); stu.setAge(rs.getInt("age")); System.out.println(stu); } } catch (Exception e) { e.printStackTrace(); } } } 复制代码
带有参数和输出的存储过程
// 带有参数和输出的存储过程 DELIMITER // CREATE PROCEDURE getName ( IN i INT, OUT n VARCHAR ( 50 ) ) BEGIN SELECT NAME INTO n FROM student WHERE id = i; END // DELIMITER; call getName(1, @name); select @name; 复制代码
测试一下:
package com.meils.jdbc.dao.test; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import com.meils.jdbc.domain.Student; import com.meils.jdbc.utils.JdbcUtil; public class ProductTest { public static void main(String[] args) { CallableStatement cstmt = null; try { //1.创建连接 Connection conn = JdbcUtil.getConnection(); //2.创建预编译语句 CallableStatement cs = conn.prepareCall("{ call getName(?,?)}"); //3.设置参数 cs.setInt(1, 1); //4.设置输出参数 cs.registerOutParameter(2, Types.VARCHAR); //5.执行 cs.execute(); //6.获取到输出的参数 String name = cs.getString(2); System.out.println(name); // 张锦杰 } catch (Exception e) { e.printStackTrace(); } } } 复制代码
首先在减少钱之前关闭自动提交事务,期间可以进行多个操作,此时的事务提交必须手动了,需要使用conn.commit();
。如果在中间发生了异常,那么就进行回滚,释放资源。
通常情况下如果我们想要一次性执行许多条sql语句,我们都是一条执行完毕再执行下一条,当我们使用了批处理之后,我们就可以一次性执行多条语句,话费的事件将大大缩短。
通常我们不会这么做的,因为数据库的空间是非常宝贵的,文件较大,占用的空间也较大,成本也就高了,假如我们需要存文件,那么就要选择blob类型了,它是以二进制的形式来存取的,可以存视频、图片、等多媒体信息。
首先需要设置数据库中的字段类型为blob。 复制代码
存储文件到数据库:
将数据库中的文件取出来:
需求分析:
我们可能回遇到这样的情景,我们首先注册信息,填入用户明和密码后,注册成功,此时的数据库中的id是自动添加进去的,接下来回让自己去完善自己的信息,这就要需要我们刚才创建的id了,那么如何返回id给我们下次使用呢?
两种方式获取:
1:
2: