JDBC全称为:Java Data Base Connectivity(java数据库链接),它主要由接口组成java
JDBC原理:其实就是一组规范(就是对类的规范,也就是接口),各大数据库厂商对其实现
这些所说的驱动类也就是JDBC的实现
可是官方的实现并非特别完整(毕竟免费),存在第三方的实现mysql
查看链接的几句代码,彷佛并无什么紧密联系。第一句的Class.forName() 注册驱动
看下面的另外的相同效果的代码
com.mysql.jdbc.Driver driver = new com.mysql.jdbc.Driver()
DriverManager.registerDriver(driver);sql
看源码能够清晰发现原理再去源码里面的静态块(在类加载的时候执行)
JDBC4.0以后DriverManager.getCoonection()会自动加载驱动类,
但为了兼容老版本,建议写Class.forName();数据库
对于链接JDBC我也只是略懂而已,如下是我写的代码,顺便告诉你一个小窍门:apache
“贾琏欲执事”,数组
意思就是加载驱动,链接数据库,建立须要的SQL语句,执行语句,释放连接。服务器
package com.mysql.test; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import org.junit.Test; public class Demo01 { @Test public void test1() throws SQLException, ClassNotFoundException{ //加载驱动类,新特性已经免去此特性 //Class.forName("com.mysql.jdbc.Driver");严重不建议使用registerDriver
String url = "jdbc:mysql://localhost:3306/mydb"; String username = "root"; String password = "root"; Connection con = DriverManager.getConnection(url,username,password); Statement stmt =con.createStatement(); String sql = "INSERT INTO ab VALUES(6,'测试JDBC')";//语句不要加分号
int i =stmt.executeUpdate(sql);//完成DML,即增删改操做
System.out.println(i); } @Test public void test2() throws SQLException, ClassNotFoundException{ //加载驱动类,新特性已经免去此特性,固然不建议省略 //Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/mydb"; String username = "root"; String password = "root"; Connection con = DriverManager.getConnection(url,username,password); Statement stmt =con.createStatement(); String sql = "SELECT * FROM stu";//语句不要加分号
ResultSet rs = stmt.executeQuery(sql); int count = rs.getMetaData().getColumnCount(); while(rs.next()){ for(int i=1;i<=count;i++){ System.out.print(rs.getString(i)); } System.out.println(); } //不关各类软病(时好时坏)
rs.close(); stmt.close(); con.close(); } }
结果集的操做:
默认的结果集是不可滚动的,不能执行上一行,下N行等操做,即forward_only(小卒只能向前拱)
光标有第0行和结果集最后一行后一行的位置。
【!】默认返回的结果集的光标在beforeFirst上,须要用next()方法来进行移动
相关滚动的方法查看SE的ResultSet()里的滚动方法
获取结果集元数据
re.getMetaData(),返回ResultMetaData(),使用相关get方法,获得多少行,多少列等
int count = rs.getMetaData().getColumnCount();
while(rs.next()){
for(int i = 1;i<=count;i++){
syso(rs.getString(i));//均可以转为String ,固然这里写getObject()也是能够得
}
}函数
ResultSet还提供了对结果集进行滚动的方法:(更详尽的方法请查阅API)工具
结果集的特性:【了解】 平时用的多的都是相似于照片,拿完就走
*是否可滚动
*是否敏感[通常不敏感]
*是否可更新测试
在createStatement获得Statement的时候就已经决定
默认空参数(整型参数)时三特性为否,详细看SE文档,
!固然【MySQL特性有可滚动】,正常都是forward_only
最后,咱们提取出一个工具类 JdbcUtils:
前提工具是驱动包以及配置文件:
配置文件信息较简单:
而后就能够提取出这个类:
package com.jdbc.utils; import java.io.IOException; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; /** * 链接数据库工具类 * 考虑到换别的数据库,使用四大参数进行传递 * 注意在配置文件中更改参数再加载便可链接其它数据库 * @author jiangbei01 * */
public class JdbcUtils { //有错,待改进 //改进后配置文件只加载一次
private static Properties props = null; static { try{ //加载配置文件中的四大参数
InputStream in = JdbcUtils.class.getClassLoader() .getResourceAsStream("dbconfig.properties"); props = new Properties(); props.load(in); }catch(IOException e){ throw new RuntimeException(e); } try { //加载驱动类,经过键获得值得方式
Class.forName(props.getProperty("driverClassName")); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } public static Connection getConnection() throws SQLException{ /* String url = "jdbc:mysql://localhost:3306/mydb"; String username = "root"; String password = "root";*/
//获得conn
return DriverManager.getConnection(props.getProperty("url"), props.getProperty("username"), props.getProperty("password")); } }
是Statement的子接口。
前提是都支持PreparedStatement:固然主流数据库都支持
使用方法:
1.给出SQL模板(参数有?给出,?只能做为参数不参与SQL语句的构成)
2.使用con的preparedStatement()方法
3.使用pstmt.setXXX方法为参数幅值
更增强大:
1.防SQL攻击
' a' or 'a'='a'等SQL语句(打出来便可知道,能够知道)
固然,这不是PreparedStatement的主要功能,能够简单简单校验等便可防止非法语句
2.提升代码的可读性,可维护性
3.效率更高
(加``避开关键字)
原理:
服务器的工做: 校验SQL语句的语法(工做量大!吃鱼的时候挑刺的时间多)
编译:一个与函数类似的东西
执行:相似调用函数
每一个pstmt都与一个SQL模板校验,先校验,把SQL模板给服务器,编译,执行时把参数给他
二次执行时直接给参数就行
【注意】MySQL预编译默认是关闭的
给出一个连接的小例子:
package com.mysql.test; import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import org.junit.Test; import com.jdbc.utils.JdbcUtils; /** * 测试PreparedStatement * @author jiangbei01 * */
public class Demo02 { @Test public void fun1(){ //准备四大参数
String driverclassName = "com.mysql.jdbc.Driver"; String url = "jdbc:mysql://localhost:3306/mydb"; String username = "root"; String password = "root"; Connection con = null; PreparedStatement pstmt = null; ResultSet rs = null; try { //加载驱动,(能够省略,可是不建议省略)
Class.forName(driverclassName); //获得链接
con = DriverManager.getConnection(url, username, password); //给出SQL模板,得到preparedStatement
String sql = "SELECT * FROM ab WHERE aid=?"; pstmt = con.prepareStatement(sql); //调用方法,执行查询语句
pstmt.setInt(1, 1); rs = pstmt.executeQuery();//方法都无参,前面都给过了
System.out.println(sql); if(rs.next()){ System.out.println(rs.getString(2));} } catch (SQLException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } finally{ //关闭资源
if(rs != null) try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } if(pstmt != null) try { pstmt.close(); } catch (SQLException e) { e.printStackTrace(); } if(con != null) try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } } /** * 测试本身写的工具类JdbcUtils * @throws SQLException * @throws IOException * @throws ClassNotFoundException */ @Test public void fun2() throws SQLException{ Connection con = JdbcUtils.getConnection(); System.out.println(con); } }
大数据也称之为LOB(Large Objects),LOB又分为:clob和blob,clob用于存储大文本,blob用于存储二进制数据,例如图像、声音、二进制文等。
在实际开发中,有时是须要用程序把大文本或二进制数据直接保存到数据库中进行储存的。
对MySQL而言只有blob,而没有clob,mysql存储大文本采用的是Text,Text和blob分别又分为:
TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT
TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB
给出一个小例子:
package com.mysql.test; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.sql.Blob; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import javax.sql.rowset.serial.SerialBlob; import org.apache.commons.io.IOUtils; import org.junit.Test; import com.jdbc.utils.JdbcUtils; public class Demo03 { /** * 测试存储大数据 * @throws SQLException * @throws IOException * @throws FileNotFoundException */ @Test public void fun1() throws Exception{ //获得链接
Connection con = JdbcUtils.getConnection(); //准备模板
String sql = "INSERT INTO file VALUES(?,?,?)"; //获得pstmt
PreparedStatement pstmt = con.prepareStatement(sql); //设置模板中的参数,进行执行
pstmt.setInt(1, 1); pstmt.setString(2, "晴天.mp3"); //问题是变blob,思路是文件变字节数组bytes[] 注意使用IO包
byte[] bytes = IOUtils.toByteArray(new FileInputStream("F:/晴天.mp3")); Blob blob = new SerialBlob(bytes); pstmt.setBlob(3, blob); pstmt.executeUpdate(); } /** * 从数据库中读取mp3 * @throws Exception */ @Test public void fun2() throws Exception{ //获得链接
Connection con = JdbcUtils.getConnection(); //给出模板
String sql = "SELECT * FROM file"; //获得pstmt
PreparedStatement pstmt = con.prepareStatement(sql); //无参数,不设置
ResultSet rs = pstmt.executeQuery(); //移动光标,查询数据
if(rs.next()){ Blob blob = rs.getBlob(3); //转为输入流,再利用文件复制
InputStream in = blob.getBinaryStream(); OutputStream out = new FileOutputStream("F:/1.mp3"); IOUtils.copy(in, out); } } }