JDBC概述
Java DataBase Connectivity java数据库连接
组成包:java.sql. * .javax.sql.* 在JDK中包含这两个包
添加数据库驱动,该驱动相当于对JDBC规范的实现
JDBC编码步骤
1 把数据库的驱动添加到lib中
[dbutils的jar包](http://download.csdn.net/detail/qq_29856871/9891887)
[mysql驱动jar包](http://download.csdn.net/detail/qq_29856871/9891880)
2 开发步骤:
1:注册驱动
第一种方式
DriverManager.registerDriver(new Driver());
第二种方式
Class.forName("com.mysql.jdbc.Driver");
2:获取与数据库的链接 jdbc:mysql://127.0.0.1:3306/
Connection connection = DriverManager.getConnection(
"jdbc:mysql://127.0.0.1:3306/mydb1", "root", "123456");(链接数据库的url地址只值,mysql账号,mysql密码)
3:得到代表发送和执行的sql语句的对象 statement
Statement statement = connection.createStatement();
4:执行语句
statement.executeUpdate("delete from customer where name ='张晨'");
5:释放占用资源
JDBCUtils工具类封装
public class JDBCUtils {
public static String JDBCURL;
public static String USERNAME;
public static String PASSWORD;
// 提供注册方法
static {
try {
// DriverManager.registerDriver(new Driver());
// 字节码文件对象
Class.forName("com.mysql.jdbc.Driver");
// 创建properties对象
Properties properties = new Properties();
// 加载文件
properties.load(new FileReader(new File("jdbc.properties")));
JDBCURL = properties.getProperty("url");
USERNAME = properties.getProperty("username");
PASSWORD = properties.getProperty("password");
} catch (Exception e) {
e.printStackTrace();
}
}
// 提供连接方法 properties IO 键值对方式进行配置 url=dddddd user=ddddd password=assss
public static Connection connect() throws SQLException {
return DriverManager.getConnection(JDBCURL, USERNAME, PASSWORD);
}
// 提供释放的方法
public static void release(Statement statement, ResultSet resultSet,
Connection connection) {
// 释放 statement resultSet connection
try {
if (statement != null) {
statement.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if (resultSet != null) {
resultSet.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
SQL注入
用户登录:用户名或者密码
zhangsan 123
'' or 1=1
'' or 1=1
select * from user where name=? and password=?;
?=zhanggsan
?=123
select * from user where name='' or 1=1 and password='' or 1=1;
这样的sql语句竟然能够将所有的数据查询出来,为了防止sql注入,避免不安全操作。使用预编译机制。
JDBC中的PreparedStatement
优点
1:指示SQL语句进行预编译,提高数据库的执行效率
2:防止SQL注入,提高安全性
3:语句中参数使用占位符(?) 提高代码编写效率
总结
能使用PreparedStatement就不使用Statement
代码示例-添加
// ctrl + 1 助手
@Test
public void test1() {
// user 数据库中添加一个叫 lisi 12345的人
// 注册jdbc驱动
// 获取连接
Connection connection = null;
PreparedStatement prepareStatement = null;
try {
connection = JDBCUtils.connect();
String sql = "insert into user (name,password) values(?,?)";
// 获取PrepareStatement
prepareStatement = connection.prepareStatement(sql);
// 往sql中添加参数信息 参数的索引值
prepareStatement.setString(1, "lisi");
prepareStatement.setString(2, "12345");
// 执行sql语句
prepareStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 释放资源
JDBCUtils.release(prepareStatement, null, connection);
}
}
代码示例-查询
/**
* 查询数据
*/
@Test
public void test3() {
// user 数据库中添加一个叫 lisi 的人改成 汉字的李四
// 注册jdbc驱动
// 获取连接
Connection connection = null;
PreparedStatement prepareStatement = null;
try {
connection = JDBCUtils.connect();
prepareStatement = connection
.prepareStatement("select * from user where name=?");
prepareStatement.setString(1, "李四");
// 进行查询--获取结果集
ResultSet resultSet = prepareStatement.executeQuery();
// while (resultSet.next()) {
// System.out.println(resultSet.getString("name") + "---"
// + resultSet.getString("password"));
// }
// resultSet.first();
//跑到最前边之前
// resultSet.beforeFirst();
resultSet.afterLast();
//直接跳到某个位置
// resultSet.absolute(2);
//往前边一个个遍历 previous 向前
while(resultSet.previous()){
System.out.println(resultSet.getString("name") + "---"
+ resultSet.getString("password"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 释放资源
JDBCUtils.release(prepareStatement, null, connection);
}
}
SQL事务处理
概念:
事务是指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要不全部不成功。
ACID特性:
原子性
指整个数据库事务是不可分割的工作单位。只有使据库中所有的操作执行成功,才算整个事务成功;事务中任何一个SQL语句执行失败,那么已经执行成功的SQL语句也必须撤销,数据库状态应该退回到执行事务前的状态。
一致性
指数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。
隔离性
指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间
持久性
指的是只要事务成功结束,它对数据库所做的更新就必须永久保存下来。
转账案例演示:
create table account(id int primary key auto_increment,name varchar(20) unique not null,money float);
insert into account (name,money) values('谢霆锋',10000);
insert into account (name,money) values('王菲',10000);
public class JDBCTest2 {
@Test
public void transMoney() {
Connection connection = null;
PreparedStatement prepareStatement1 = null;
PreparedStatement prepareStatement2=null;
try {
connection = JDBCUtils.connect();
//开启事务 beginTransaction();
connection.setAutoCommit(false);
String sql1 = "update account set money=money-100 where name=?";
// 谢霆锋转出100元
prepareStatement1 = connection.prepareStatement(sql1);
prepareStatement1.setString(1, "谢霆锋");
prepareStatement1.executeUpdate();
//银行断点
int i=1/0;
// 王菲收到100元
String sql2 = "update account set money=money+100 where name=?";
prepareStatement2 = connection.prepareStatement(sql2);
prepareStatement2.setString(1, "王菲");
prepareStatement2.executeUpdate();
//提交事务 commit
connection.commit();
} catch (Exception e) {
e.printStackTrace();
//回滚事务
try {
System.out.println("----事务回滚啦-----");
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
} finally {
try {
prepareStatement2.close();
} catch (SQLException e) {
e.printStackTrace();
}
JDBCUtils.release(prepareStatement1, null, connection);
}
}
}
事务隔离级别
脏读 :读到另一个事务的未提交更新数据
不可重复读:对同一个记录两次读取不一致,因为另外一个事务对该记录做了修改
虚读:对同一张表的两次查询不一致,因为另一个事务插入了一条记录。
四种隔离级别:
1:READ UNCOMMITTED 三种都不能处理
2:READ COMMITTED 只能处理脏读,不能处理不可重复读和虚读 Orical的默认隔离级别
3:REPEATABLE READ 可以处理脏读和不可重复读 MySQL默认的隔离级别
4:SERIALIZABLE 串行化 三种读问题都能够处理 效率低
select @@tx_isolation; 查看当前数据库的隔离级别
set transaction isolation level 四个级别之一;更改当前事务的隔离级别
大文本
//创建一个数据库表
create table testclob( id int primary key,content longtext);
/**
*
* @throws SQLException
*/
public void writeClobText() {
Connection connect = null;
PreparedStatement prepareStatement = null;
try {
connect = JDBCUtils.connect();
prepareStatement = connect
.prepareStatement("insert into testclob(id,content) values(?,?)");
prepareStatement.setInt(1, 1);
File file = new File("src/com/example/jdbc/JDBCTest1.java");
FileReader fileReader = new FileReader(file);
prepareStatement.setCharacterStream(2, fileReader,
(int) file.length());
prepareStatement.executeUpdate();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
JDBCUtils.release(null, prepareStatement, connect);
}
}
public void readClobText() {
Connection connect = null;
PreparedStatement prepareStatement = null;
try {
connect = JDBCUtils.connect();
prepareStatement = connect
.prepareStatement("select * from testClob");
prepareStatement.executeQuery();
ResultSet resultSet = prepareStatement.getResultSet();
if (resultSet.next()) {
Reader reader = resultSet.getCharacterStream("content");
FileWriter fileWriter = new FileWriter(new File(
"/Users/zhiyuan/file.text"));
char[] buffer = new char[1024];
int len = 0;
while ((len = reader.read(buffer)) != -1) {
fileWriter.write(buffer, 0, len);
}
reader.close();
fileWriter.close();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
JDBCUtils.release(null, prepareStatement, connect);
}
}
大二进制
创建大二进制的表结构
create table testblob(id int primary key,content longblob);
/**
*
* @throws SQLException
*/
public void writeBlob() {
Connection connect = null;
PreparedStatement prepareStatement = null;
try {
connect = JDBCUtils.connect();
prepareStatement = connect
.prepareStatement("insert into testblob(id,content) values(?,?)");
prepareStatement.setInt(1, 1);
File file = new File("ab.jpg");
FileInputStream fileInputStream = new FileInputStream(file);
prepareStatement.setBinaryStream(2, fileInputStream,
(int)fileInputStream.available());
prepareStatement.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.release(null, prepareStatement, connect);
}
}
public void readBlob() {
Connection connect = null;
PreparedStatement prepareStatement = null;
try {
connect = JDBCUtils.connect();
prepareStatement = connect
.prepareStatement("select * from testblob");
prepareStatement.executeQuery();
ResultSet resultSet = prepareStatement.getResultSet();
if (resultSet.next()) {
InputStream inputStream = resultSet.getBinaryStream("content");
FileOutputStream fileOutputStream = new FileOutputStream(new File(
"/Users/zhiyuan/aa.jpg"));
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, len);
}
inputStream.close();
fileOutputStream.close();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
JDBCUtils.release(null, prepareStatement, connect);
}
}
批处理-一次执行多条sql
Statement
1.sql语句不固定
2.可以一次性执行不同的sql
@Test
public void batchStatement() {
Connection connect = null;
PreparedStatement prepareStatement = null;
try {
connect = JDBCUtils.connect();
Statement statement = connect.createStatement();
String sql1 = "insert into testbatch(name) values('张三')";
String sql2 = "update testbatch set name='李四' where name='张三'";
statement.addBatch(sql1);
statement.addBatch(sql2);
statement.executeBatch();
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.release(null, prepareStatement, connect);
}
}
//PreparedStatement
1.sql语句的参数是不确定的,sql固定
2.一次性批量执行相同的sql
@Test
public void batchPreparedStatement() {
Connection connect = null;
PreparedStatement prepareStatement = null;
try {
connect = JDBCUtils.connect();
String sql = "insert into testbatch(name) values(?)";
prepareStatement=connect.prepareStatement(sql);
for (int i = 0; i < 1002; i++) {
prepareStatement.setString(1, "zhangsan"+i);
//添加到批处理中去
prepareStatement.addBatch();
if(i%100==0){
//没100个数据执行一次批处理任务
prepareStatement.executeBatch();
//清除批处理,避免内存溢出
prepareStatement.clearBatch();
}
}
//最后执行和清除批处理任务
prepareStatement.executeBatch();
prepareStatement.clearBatch();
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.release(null, prepareStatement, connect);
}
}
一、MVC开发模式
实际生活中
MVC原理
1.服务员-----------服务台-----------厨师----------------采购---------原材料
2.页面-------------控制器-----------业务逻辑------------数据访问------数据库
总结结论:
1.各层之间按一定顺序进行调用 ,不能跨层调用
2.上一层能调用下一层,但是下一层不能调用上一层
3. 各司其职,互不干涉
4.适合中大型项目
M:Model(模型)
一般由jvaBean充当
包括:
业务模型(对应三层结构业务逻辑层)
com.baidu.servcie 业务接口
com.baidu.service.impl 业务实现类
数据模型(对应三层结构的数据访问层) Data Access Object
com.baidu.dao 数据访问接口
com.baidu.dao.impl 数据访问实现类
实体模型(域模型)
com.baidu.domain
V:View(视图)
一般由jsp/html来充当
C:Controller(控制器)
一般由Servlet/Filter/Action(由struts框架提供)来充当
com.itheima.web.controller
com.itheima.web.form(主要作用是用于接收页面上输入的数据并进行验证,UserFormBean)
三层结构
表示层(View)
业务逻辑层(Model)
数据访问层(Model)
业务实体层(Model)
控制层 (Controller)
工具类(cn.itcast.util)
结论:MVC不等于三层结构,一个基于MVC思想进行架构的应用程序,可能是一个N层结构