JDBC概述
- JDBC:提拱了一种与平台无关的用于执行Sql语句的标准JAVA API,可以方便的实现多种关系型数据库的统一操作,它由一组用JAVA编写的类和接口组成
- 在实际开发中可以直接使用JDBC进行各个数据库的连接与操作,而且可以方便的向数据库中发送各种SQL语句,。在JDBC中提拱的是一套标准的接口,这样各个支持JAVA的数据库生产商只要按照此接口提拱相应的实现,则就可以使用JDBC进行操作,极大的体现了JAVA的可移植性
MySql的安装和配置和基本命令
链接:Mac安装mysql:https://www.jianshu.com/p/07a9826898c0
- 基本使用
登陆:终端--> mysql -u 用户名 -p 回车输入密码
输入?号:表示MySql有哪些命令可拱我们使用
创建数据库: CREATE DATAVASE 数据库名;
删除数据库:DROP DATABASE 数据库名;
使用数据库:USE 数据库名;
创建表: CREATE TABLE mytab(
id INT AUTO_INCREMENT PRIMARY KEY, //自动增长,主键
name VARCHAR(30) NOT NULL, //非空
password VARCHAR(32) NOT NULL, //非空
age INT NOT NULL //非空
) ;
删除表:DROP TABLE 表名;
查看表结构:DESC 表名;
显示所有数据库:SHOW DATABASES;
显示所有表:SHOW TABLES;
SQL的语法基础
-
SQL是一门结构化查询语言,SQL是关系型数据库管理系统的标准语言,在现在的开发中基本都支持标准的SQL语法.
-
MySQL里的数据类型
-
增加
insert into 表名(列名) values(值 );
insert into user(name,password) values(‘Fhvk’,‘LCW’); -
删除
delete from 表名 where 列名=值;
//表示删除name为LCW的记录
delete from user where name=‘LCW’;
//表示删除所有记录
delete from user; -
查询
简单查询:
select * from 表名; //查询所有记录
select 列名 from 表名; //查询所有记录的指定列
select * from 表名 where 列名=值; //表示查询该列名为该值的记录
模糊查询
//查询所有记录中name列带’m’的记录,或password列带’m’的记录
select * from user where name like ‘%m%’ OR passwrod like ‘%m%’;
分页查询
//查询0开始的5条记录
select * from user limit 0,5; -
修改
update 表名 set 列名=值,列名=值… where 列名=值;
update user set nam=‘FHVK’ where id=1;
JDBC的操作步骤
- JDBC本身是一个固定的标准,所以其操作督也是固定的,以后只需修改很少的一部分代码就可以达到不同数据库间的连接转换功能;
1、加载数据库驱动
2、连接数据库
3、使用语句进行数据库操作
4、关闭数据库连接 - 数据库驱动程序都是各个厂商提拱的,都是以.jar或.zip导入到程序中
方法请看:https://www.jianshu.com/p/3cae846b8a91 - 加载\连接\关闭
执行数据库更新操作
- 使用Connction对象取得Statement实例
- 插入案例
ResultSet接口
- 使用Sql中的select语句可以将数据库的全部结果查询出来,在JDBC的操作中数据库所有查询记录次使用ResultSet进行接收,并使用ResultSet显示内容
- 在操作的时候使用Statement中的executeQuery()方法进行数据库的查询操作,此方法返回值就是ResultSet
- 查表中所有数据(列名)
- 查询表中所有数据(编号)
- 综合比较上面两种,直接使用编号取值会更加方便。
- 问题如果现在查询的时候直接使用“select * from user”,不是更加简单吗?
- 但是,在开发中是不能直接使用“*”的,因为这样在查询的时候并不能明确的表示要取的内容是什么,所以在开发中查询时肯定要明确的写出需要查找的列
- ResultSet查询时是将全部结果以ResultSet返回
- 通过ResultSet接口依次取出里面的全部内容
所有结果实际上最终保存在内存中,所以对于数据库的查询来讲,不要查询全部
PreparedStatement接口
- PreparedsStatement是Statement的子接口,属于预处理操作,与直接使用Statement不同的是,PreparedStatement在操作时,是先在数据表之中准备好了一条SQL语句,但是此SQL语句的具体内容暂时不设置,而是之后再进行设置,以插入数据为例,使用PreparedStatement插入数据时,数据表中的指针先指向最后一条数据之后,但是里面的内容是不知道的,而是等待用户分别设置。
- 此接口的实例通过Connection的之preparedStatement()获取,之后使用一系列的setXX()方法设置内容,根据位置,如果执行更新语句的话,则会返回更新数据的记录数。
- 注意:日期的输入问题,在正常情况下都使用java.util.Date表示日期,但是在PreparedStatement中如果要想使用日期必须使用java.sql.Date类型
- 插入一条数据
package com.lichaowu.jdbc;
import java.sql.DriverManager;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.PreparedStatement;
import com.mysql.jdbc.Statement;
public class Demo05_Jdbc {
static {
try {
Class.forName("org.gjt.mm.mysql.Driver");
}catch (ClassNotFoundException e){
e.printStackTrace();
}
}
//定义mysql的数据库驱动程序
//public static final String DBDRIEVER = "org.gjt.mm.mysql.Driver";
//定义数据库的连接地址
public static final String DBURL = "jdbc:mysql://localhost:3306/mldn?useSSL=true";
//定义数据库用户名
public static final String DBUSER = "root";
//定义数据库密码
public static final String DBPASS = "123456";
//所有异常抛了
public static void main(String[] agrs) throws Exception{
String name = "陈清香"; //定义姓名
String password = "1234"; //定义密码
int age = 19; //定义年龄
String sex = "女"; //定义性别
//定义生日
Date d = new SimpleDateFormat("yyyy-MM-dd").parse("1998-03-21");
java.sql.Date birthday = new java.sql.Date(d.getTime());
//定义sql语句
String sql = "insert into user(name,password,age,sex,birthday) values(?,?,?,?,?)";
//数据库的连接
Connection conn = (Connection)DriverManager.getConnection(DBURL,DBUSER,DBPASS);
//实例化PreparedStatement对象
PreparedStatement pstmt = (PreparedStatement)conn.prepareStatement(sql);
pstmt.setString(1, name); //从1开始
pstmt.setString(2, password);
pstmt.setInt(3, age);
pstmt.setString(4, sex);
pstmt.setDate(5, birthday);
int index = pstmt.executeUpdate();
System.out.println(index + "条记录受影响!");
pstmt.close();
conn.close();
}
}
- 查询操作(模糊查询)
package com.lichaowu.jdbc;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.text.ParseException;
import java.util.Date;
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.PreparedStatement;
public class Demo06_Jdbc {
static {
try {
Class.forName("org.gjt.mm.mysql.Driver");
}catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//定义数据库连接地址
public static final String DBURL = "jdbc:mysql://localhost:3306/mldn?useSSL";
//定义数据库用户名
public static final String DBUSER = "root";
//定义数据库密码
public static final String DBPASS = "123456";
public static void main(String[] agrs) throws Exception{
//定义模糊查询关键字
String keyWord = "F";
String sql = "select id,name,password,age,sex,birthday from user where password like ?";
//连接数据库
Connection conn = (Connection)DriverManager.getConnection(DBURL, DBUSER, DBPASS);
//操作数据库
PreparedStatement ps = (PreparedStatement) conn.prepareStatement(sql);
ps.setString(1, "%" + keyWord + "%");
ResultSet rs = ps.executeQuery();
while(rs.next()) {
int id = rs.getInt(1);
String name = rs.getString(2);
String password = rs.getString(3);
int age = rs.getInt(4);
String sex = rs.getString(5);
Date d = rs.getDate(6);
System.out.println(id + ", " + name + ", " + password + ", " + age + ", " + sex + ", " + d);
}
rs.close();
ps.close();
conn.close();
}
}
- 查询所有
package com.lichaowu.jdbc;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.util.Date;
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.PreparedStatement;
public class Demo07_JDbc {
static {
try {
Class.forName("org.gjt.mm.mysql.Driver");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//定义数据库连接地址
public static final String DBURL = "jdbc:mysql://localhost:3306/mldn?useSSL=true";
//定义数据库用户名
public static final String DBUSER = "root";
//定义数据库密码
public static final String DBPASS = "123456";
public static void main(String[] agrs) throws Exception{
//连接数据库
Connection conn = (Connection)DriverManager.getConnection(DBURL, DBUSER, DBPASS);
//操作数据库
PreparedStatement ps = (PreparedStatement)conn.prepareStatement("select id,name,password,age,sex,birthday from user");
ResultSet rs = ps.executeQuery();
while(rs.next()) {
int id = rs.getInt(1);
String name = rs.getString(2);
String password = rs.getString(3);
int age = rs.getInt(4);
String sex = rs.getString(5);
Date d = rs.getDate(6);
System.out.println(id + ", " + name + ", " + password + ", " + age + ", " + sex + ", " + d);
}
}
}
- 在开发中到底使用PereapredStatement还是使用Statement接口呢?在实际开发中不会有人使用Statement接口的,因为其使用的是拼凑的Sql语句形式,那么这样一来就有可能造成Sql注入漏洞。
处理CLOB数据
cretae table userclob(
id int auto_increment primary key,
name varchar(30) not null,
note longtext --存储大文本数据最大为4G
);
- 大对象处理主要指的是CLOB和BLOB两种类型,在CLOB中可以存储海量文字,例如:存储一部《红楼梦》。在BLOB中可以存储图片、视频、音频等。如果在程序中要想处理这样的大对象操作,则必须使用PreparedStatement完成,所有的内容要通过IO流的方式从大文本中保存和读取
- 大文本写入到数据库中
public class Demo08_Jdbc {
static {
try {
Class.forName("org.gjt.mm.mysql.Driver");
}catch (Exception e) {
e.printStackTrace();
}
}
//数据库连接地址
public static final String DBURL = "jdbc:mysql://localhost:3306/mldn?useSSL=true";
//数据库用户名
public static final String DBUSER = "root";
//数据库密码
public static final String DBPASS = "123456";
public static void main(String[] agrs) throws Exception{
//定义名称
String name = "李超武";
//定义备注
File f = new File("Text.text");
FileInputStream fis = new FileInputStream(f);
//连接数据库
Connection conn = (Connection)DriverManager.getConnection(DBURL,DBUSER,DBPASS);
//Sql语句
String sql = "insert into userclob(name,note) values(?,?)";
//操作数据库
PreparedStatement ps = (PreparedStatement)conn.prepareStatement(sql);
//设置
ps.setString(1, name);
ps.setAsciiStream(2, fis, (int)f.length());
int index = ps.executeUpdate();
System.out.println(index + "条插入成功!");
ps.close();
conn.close();
}
}
- 大文本读取到内存中
public class Demo09_Jdbc {
static {
try {
Class.forName("org.gjt.mm.mysql.Driver");
}catch (Exception e) {
e.printStackTrace();
}
}
//数据库连接地址
public static final String DBURL = "jdbc:mysql://localhost:3306/mldn?useSSL=true";
//数据库用户名
public static final String DBUSER = "root";
//数据库密码
public static final String DBPASS = "123456";
public static void main(String[] agrs) throws Exception{
int id = 1;
String sql = "select id,name,note from userclob where id = ?";
//连接数据库
Connection conn = (Connection)DriverManager.getConnection(DBURL,DBUSER,DBPASS);
//操作数据库
PreparedStatement ps = (PreparedStatement)conn.prepareStatement(sql);
ps.setInt(1, id);
ResultSet rs = ps.executeQuery();
if(rs.next()) {
int iud = rs.getInt(1);
String naem = rs.getString(2);
InputStream is = rs.getAsciiStream(3);
StringBuffer note = new StringBuffer();
Scanner snote = new Scanner(is);
snote.useDelimiter("\r\n");
while(snote.hasNextLine()) {
note.append(snote.next()).append("\n");
}
System.out.println("内容: " + note);
is.close();
}
rs.close();
ps.close();
conn.close();
}
}
Clob类
- 以上的做法是将大文本数据内容直接通过ReultSet读取进来的,当然也可以使用ResultSet中提拱的getClob()方法,将全部的内容变为Clob对象的内容,直接使用Clob可以方便的取得大文本的数据,也可以对这些数据进行简单的操作,如获取指定长度的文本等;
- 理解大对象的含义
- 理解MYSQL中 LONGTEXT 的长度 为4个G
- 如果想完成大文本的读写可以使用IO也可以使用CLOB类完成
BLOB
create table userblob(
id int auto_increment primary key,
name varchar(30) not null,
photo longblob. -- 存放二进制文件如图片,最大为4G
);
- Clob主要是保存海量文字的,而Blob是专门保存二进制数据,包括图片、音乐、电影等;
- 存
package com.lichaowu.jdbc;
import java.io.File;
import java.io.FileInputStream;
import java.sql.DriverManager;
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.PreparedStatement;
public class Demo11_JDbc {
//加载驱动
static {
try {
Class.forName("org.gjt.mm.mysql.Driver");
}catch (Exception e) {
e.printStackTrace();
}
}
//数据库连接地址
public static final String DBURL = "jdbc:mysql://localhost:3306/mldn?useSSL=true";
//数据库用户名
public static final String DBUSER = "root";
//数据库密码
public static final String DBPASS = "123456";
public static void main(String[] agrs) throws Exception{
String name = "李超武";
String sql = "insert into userbolb(name,photo) values(?,?)";
Connection conn = (Connection)DriverManager.getConnection(DBURL,DBUSER,DBPASS);
PreparedStatement ps = (PreparedStatement)conn.prepareStatement(sql);
ps.setString(1, name);
File f = new File("BLOB.jpg");
FileInputStream fis = new FileInputStream(f);
ps.setBinaryStream(2, fis, (int)f.length());
ps.executeLargeUpdate();
ps.close();
conn.close();
}
}
- 取
public class Demo12_Jdbc {
static {
try {
Class.forName("org.gjt.mm.mysql.Driver");
}catch (Exception e) {
e.printStackTrace();
}
}
public static final String DBURL = "jdbc:mysql://localhost:3306/mldn?useSSL=true";
public static final String DBUSER = "root";
public static final String DBPASS = "123456";
public static void main(String[] agrs) throws Exception{
int id = 1;
String sql = "select name,photo from userbolb";
Connection conn = (Connection)DriverManager.getConnection(DBURL,DBUSER,DBPASS);
PreparedStatement ps = (PreparedStatement)conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
if(rs.next()) {
String name = rs.getString(1);
System.out.println("姓名: " + name);
InputStream is = rs.getBinaryStream(2);
File f = new File("QQ.jpg");
FileOutputStream fos = new FileOutputStream(f);
byte[] arr = new byte[1024];
int len = 0;
while((len = is.read(arr)) != -1) {
fos.write(arr, 0, len);
}
is.close();
fos.close();
}
rs.close();
ps.close();
conn.close();
}
}
Blob类取
package com.lichaowu.jdbc;
import java.io.File;
import java.io.FileOutputStream;
import java.sql.DriverManager;
import java.sql.ResultSet;
import com.mysql.jdbc.Blob;
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.PreparedStatement;
public class Demo13_Jdbc {
static {
try {
Class.forName("org.gjt.mm.mysql.Driver");
}catch (Exception e) {
e.printStackTrace();
}
}
public static final String DBURL = "jdbc:mysql://localhost:3306/mldn?useSSL=true";
public static final String DBUSER = "root";
public static final String DBPASS = "123456";
public static void main(String[] agrs) throws Exception{
int id = 1;
String sql = "select name,photo from userbolb where id = ?";
Connection conn = (Connection)DriverManager.getConnection(DBURL, DBUSER, DBPASS);
PreparedStatement ps = (PreparedStatement)conn.prepareStatement(sql);
ps.setInt(1, id);
ResultSet rs = ps.executeQuery();
if(rs.next()) {
String name = rs.getString(1);
Blob b = (Blob)rs.getBlob(2);
File f = new File("QQ1.jpg");
FileOutputStream fos = new FileOutputStream(f);
fos.write(b.getBytes(1, (int)b.length()));
fos.close();
}
rs.close();
ps.close();
conn.close();
}
}
- 使用Blob读取会简单一些。
- 但是从实际角度来看,把一个过大的文件存放在数据库中是一个很不明智的选择。因为数据过大。往往使用映射路径的方式进行写入。
- Blob是专门用于读取大对象数据使用的,主要是操作二进制数据的。
- 使用Blob可以简化输出操作。
JDBC 2.0
- 在jdbc2.0中,增强了结果集ResultSet功能,可以直接使用ResultSet执行更新操作的操作,或者实现双向滚动。在jdbc2.0中有一个最重要的概念就是批处理操作,可以一次性完成多个语句的执行
- 可滚动的结果集操作
如果想要创建可滚动的结果集,则在创建的PreaparedStatement/Statement的时候必须指定了创建的类型。
通过方法beforeFirst()将记录定位到第一条数据之前,然后通过next()方法向下移动一次,就达到了第一条记录的效果(同理还有移动到最后一条记录之后的方法afterLast())
next()方法指针都是由前向后移动,通过previous()方法正好和next()方法相反由后向前
如果程序真的使用这种方式开发的话,那么内存的损耗将非常之大。所以开发以中不会有=使用这种可滚动的结果集. - 使用结果集插入操作
- 使用结果集更新数据
如果想使用结果集更新操作,则先用id查询
如果在更新之前取消更新的话,则是不会执行更新的,如果在updateRow()之前调用cancelRowUpdates(),则会取消更新。 - 使用结果集完成删除操作
以上的操作不经常使用不如直接通过PreparedStatement
- 批处理(重点)
批处理操作就是指一次性向数据库中执行多条语句,一次提交,例如向数据库中插入的10条记录
- 了解JDBC2.0中结果集的功能提升:可滚动select,可insert,可update,可delete
- 如果要想创建灵活的结果集,则在创建数据库操作时就必须指定类型
- 批处理可以一次提交多条记录到数据库表中
数据库的事务处理
- 事务:就是保证操作的一致性,所有的操作要么全部成功,要么全部失败。事务本身具有:原子性(Atomicity)、一致性(Consistency)、隔离性或独立性(Isolation)、持久性(Durabilily)四个特征。也称为ACID
- 如果要想操作事务的话,则必须按照以下的步骤完成
1、取出掉自动提交,每次执行数据库更新的时候实际上发出SQL命令之后就已经提交上去了
2、开始事务
3、进行一系列操作
4、如果操作全部合格,则提交事务
5、如果发现一个地方有问题,则可以进行回滚。
6、或者设置一个SAVEPOINT保存事务的提交点
以上是mysql的操作支持
JDBC事务处理
- 在JDBC中,如果想要进行事务处理,也需要按照指定的步骤完成
1、取消掉Connection中设置的自动提交方式:conn.setAutoCommit(false);
2、如果批处理操作成功,则执行提交事务;conn.commit();
3、如果操作失败,则肯定会引发异常,在异常处理中让事务回滚。conn.rollback();
如果需要可以设置回滚位置,Savepoint sp = conn.setSavepoint();
-
标准操作代码
-
在正常情况下,可以通过SAVEPOINT保存事务的操作点,因为默认情况下所有的回滚,就是将全部的操作取消掉,而通过Savepoint可以设置回滚的位置。
-
一个session的操作(每一个连接到数据库上的用户都称为一个session)
操作1
操作2
Savepoint 记录点
操作3
操作4
操作5
rollback 记录点 -
下面用代实现
总结:1、事务的基本概念:如何在数据库中处理事务。
2、JDBC操作事务的步骤:取消自动提交,执行多条sql语句,如果没有异常,则提交事务,如果有异常,则回滚操作
使用元数据来分析数据库
- DatabaseMetaData:可以得到数据库的基本信息,包括数据库的名称、版本、以及表的信息
- 实现
- ResultSetMetaData可获取关于ResultSet对象中列的类型和属性信息的对象,ResultSetMetaData存储了ResultSet的MetaData,可以通过以下方法取得一些ResultSet的信息.
- 实现
以上的两个操作在数据的开发底层上比较常用,实际也是类似反射的操作机制,取得一些基本的信息,在正常开发不会使用;
使用JDBC连接Oracle
略。。。。。