MySQL成长之路(006)
---恢复内容开始---
一、CURD操作:增删该查操作
junit单元测试的使用
- 让方法能脱离main方法直接运行.
- 主要是用来开发测试时使用,线上的生产场景不能使用!
- 线上的生产场景只能使用正常的方法调用!
package com.test1;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import org.junit.Test;
/*
* 增删改查
*
*/
public class CRUDDemo {
//可以自己运行的方法,不需要main方法调用!
//
@Test
public void insert() throws Exception{
//
Class.forName("com.mysql.jdbc.Driver");
//
Connection conn = DriverManager.getConnection("jdbc:mysql:///mydb1", "root", "123");
Statement st = conn.createStatement();//语义直通器
int res = st.executeUpdate("insert into stu2 values('Tyson','male','yes')");
//通过返回值是否是非0判断是否执行成功
if(res != 0){
System.out.println("插入数据成功");
}
//
st.close();
conn.close();
}
@Test
public void delete() throws Exception{
//
Class.forName("com.mysql.jdbc.Driver");
//
Connection conn = DriverManager.getConnection("jdbc:mysql:///mydb1", "root", "123");
Statement st = conn.createStatement();
int res = st.executeUpdate("delete from stu2 where name = 'Tyson'");
//通过返回值是否是非0判断是否执行成功
if(res != 0){
System.out.println("删除数据成功");
}
//
st.close();
conn.close();
}
@Test
public void update() throws Exception{
//
Class.forName("com.mysql.jdbc.Driver");
//
Connection conn = DriverManager.getConnection("jdbc:mysql:///mydb1", "root", "123");
Statement st = conn.createStatement();
int res = st.executeUpdate("update stu2 set zhuxiao = 'yes' where name = 'Frank'");
//通过返回值是否是非0判断是否执行成功
if(res != 0){
System.out.println("更新数据成功");
}
//
st.close();
conn.close();
}
@Test
public void search() throws Exception{
//
Class.forName("com.mysql.jdbc.Driver");
//
Connection conn = DriverManager.getConnection("jdbc:mysql:///day229", "root", "123");
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("select * from stu2");
while(rs.next()){
String name = rs.getString(1);
String gender = rs.getString(2);
String zhuxiao = rs.getString(3);
System.out.println(name+","+gender+","+zhuxiao);
}
//
rs.close();
st.close();
conn.close();
}
}
封装数据库操作工具类:
- 注册驱动和获取连接对象的操作是每种操作都需要进行的步骤!
- 所以考虑将相同的操作封装到工具类中以方便使用!
- 优化:由于数据库连接使用的四大参数有可能随时发生变化,最好放到配置文件中指定!防止硬编码!
public class Dbutils {
//构造方法私有化
private Dbutils(){}
//公共的静态方法,获取连接对象
public static Connection getConnection() throws Exception{
//通过配置文件获取参数
Properties p = new Properties();
p.load(new FileInputStream("dbconfig.txt"));
//
String driverName = p.getProperty("driverName");
String url = p.getProperty("url");
String userName = p.getProperty("userName");
String password = p.getProperty("password");
Class.forName(driverName);
//将连接对象返回
return DriverManager.getConnection(url,userName,password);
}
}
package com.utils;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties;
/*
* 数据库操作的工具类
* 主要用来获取连接对象!
* 通过连接对象有可能获取Statement对象,也有可能获取的是预编译的对象
*
* 共同的操作:
* 1.注册驱动
* 2.获取连接对象
*
*
*
* 优化:
* 将四大参数放到配置文件中!!!
*
*/
public class Dbutils {
private Dbutils(){
}
//公共的静态方法,获取连接对象
public static Connection getConnection() throws Exception{
//通过配置文件获取参数
Properties p = new Properties();
p.load(new FileInputStream("dbconfig.txt"));
//
String driverName = p.getProperty("driverName");
String url = p.getProperty("url");
String userName = p.getProperty("userName");
String password = p.getProperty("password");
Class.forName(driverName);
//
Connection conn = DriverManager.getConnection(url,userName,password);
return conn;
}
}
package com.test1;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import org.junit.Test;
import com.utils.Dbutils;
/*
* 使用工具类实现增删改查
*
*/
public class CRUDDemo2 {
//可以自己运行的方法,不需要main方法调用!
//
@Test
public void insert() throws Exception{
Connection conn = Dbutils.getConnection();
Statement st = conn.createStatement();
int res = st.executeUpdate("insert into stu2 values('Tyson','male','yes')");
//通过返回值是否是非0判断是否执行成功
if(res != 0){
System.out.println("插入数据成功");
}
//
st.close();
conn.close();
}
@Test
public void delete() throws Exception{
Connection conn = Dbutils.getConnection();
Statement st = conn.createStatement();
int res = st.executeUpdate("delete from stu2 where name = 'Tyson'");
//通过返回值是否是非0判断是否执行成功
if(res != 0){
System.out.println("删除数据成功");
}
//
st.close();
conn.close();
}
@Test
public void update() throws Exception{
Connection conn = Dbutils.getConnection();
Statement st = conn.createStatement();
int res = st.executeUpdate("update stu2 set zhuxiao = 'yes' where name = 'Frank'");
//通过返回值是否是非0判断是否执行成功
System.out.println(res);
if(res != 0){
System.out.println("更新数据成功");
}
//
st.close();
conn.close();
}
@Test
public void search() throws Exception{
//
Connection conn = Dbutils.getConnection();
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("select * from stu2");
while(rs.next()){
String name = rs.getString(1);
String gender = rs.getString(2);
String zhuxiao = rs.getString(3);
System.out.println(name+","+gender+","+zhuxiao);
}
//
rs.close();
st.close();
conn.close();
}
}
Statement接口详解:
是一个sql语句的执行器,可以执行sql语句.同时可以指定将来获取到的结果集的类型:
- statement语句执行的方法:
- DML:insert ,update ,delete
- DDL:create table
- DQL:select
- 如果是查询语句,建议使用executeQuery方法,直接得到结果集对象!
- 如果是更新类语句,建议使用executeUpdate方法,得到的结果是一个int值,通常用返回值是否非0来判断是否执行成功.
- 特例:execute方法可以执行任何类型的sql语句.返回值是boolean类型.
- 如果是true表示结果是一个结果集.
package com.test1;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
import org.junit.Test;
import com.utils.Dbutils;
/*
* Statement接口
*
* executeUpdate(String sql):增删改操作
* executeQuery(String sql):针对查询
* execute(String sql):执行任意的sql语句,返回的是个布尔类型
*
* 结果集的操作:
* 游标的移动:
* next():
* previous():
* void afterLast():
* void beforFirst():
* boolean first():
* boolean last():
*
* absolute(int row):
* relative(int count):count正数,往下移动,负数,往上移动
*
* getRow():获取当前行编号!
*
* 获取结果集的特性:
* 通过获取Statement语句时指定的参数指定!!!
*
*
* 结果集的元数据:描述数据的数据!
* 如果我不知道结果集有多少列!如何遍历结果集?
* 通过结果集的元数据!!
* 元数据里可以获取列的数量.
* 通过while循环遍历行,通过for循环遍历列.
*
*/
public class CRUDDemo3 {
@Test
public void search3() throws Exception{
//
Connection conn = Dbutils.getConnection();
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("select * from stu2");
//如果不知道结果集的列数,如果遍历?
ResultSetMetaData metaData = rs.getMetaData();
int count = metaData.getColumnCount();
//遍历结果集
while(rs.next()){
//遍历列:
for(int i = 1;i<=count;i++){
Object obj = rs.getObject(i);
System.out.print(obj);
if(i != count){
System.out.print(", ");
}
}
//
System.out.println();
}
//
st.close();
conn.close();
}
@Test
public void search() throws Exception{
//
Connection conn = Dbutils.getConnection();
Statement st = conn.createStatement();
// boolean b = st.execute("select * from stu2");
// if(b){
// //获取结果集
// ResultSet rs = st.getResultSet();
// while(rs.next()){
// String name = rs.getString(1);
// System.out.println(name);
// }
// rs.close();
// }
ResultSet rs = st.executeQuery("select * from stu2");
System.out.println(rs.getRow());
rs.absolute(5);
System.out.println(rs.getRow());
//获取结果集的行数
rs.afterLast();
rs.previous();
System.out.println(rs.getRow());
rs.close();
//
st.close();
conn.close();
}
@Test
public void search2() throws Exception{
//
Connection conn = Dbutils.getConnection();
Statement st = conn.createStatement();
/*
* 第一个参数:结果集的类型:可滚动,不敏感,不可更新
* ResultSet.TYPE_FORWARD_ONLY: 结果集的游标只能往下滚动
* ResultSet.TYPE_SCROLL_INSENSITIVE : 对数据库底层数据变化不敏感
* ResultSet.TYPE_SCROLL_SENSITIVE : 对数据库底层数据变化敏感
* MySQL只支持第二种!!!
*
* 第二个参数:结果集的变化是否能更新到底层数据库,
* ResultSet.CONCUR_READ_ONLY : 结果集的更改不更新到底层的数据库
* ResultSet.CONCUR_UPDATABLE : 结果集的更改更新到底层的数据库
* 目前,所有的数据库都只支持第一种!!!
*
* MySQL获取的Statement对象,默认是以下组合!!
* ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY
*
*/
ResultSet rs = st.executeQuery("select * from stu2");
System.out.println(rs.getRow());
rs.absolute(5);
System.out.println(rs.getRow());
//获取结果集的行数
rs.afterLast();
rs.previous();
System.out.println(rs.getRow());
rs.close();
//
st.close();
conn.close();
}
}
结果集游标操作:
绝对定位:
- boolean first():
- boolean last():
- void beforeFirst():
- void afterLast():
- boolean absolute(int row):
相对定位:从当前位置移动
- boolean next():
- boolean previous():
- boolean relative(int amount):正数表示往后移动,负数表示往前移动
判断操作:
- boolean isAfterLast():
- boolean isBeforeFirst():
- boolean isFirst():
- boolean isLast():
结果集的元数据操作:
若不知道具体的结果集有多少列,可以通过结果集的元数据获取结果集的描述信息,其中就包括列的数量.
通过列的数量就可以遍历一行数据的各个列.
通过游标的返回值就可以遍历行.
二者结合,就可以遍历一个不知道具体行数和列数的结果集!
ResultSetMetaData metaData = rs.getMetaData();
int count = metaData.getColumnCount();
//遍历结果集
while(rs.next()){
//遍历列:
for(int i = 1;i<=count;i++){
Object obj = rs.getObject(i);
System.out.print(obj);
if(i != count){
System.out.print(", ");
}
}
//
System.out.println();
}
加上异常处理的完整程序!
- 对非内存资源的释放一般是放在finally块中.就需要将资源的定义放在try块外.
- finally中需要对资源进行非空判断!!!
sql注入
- sql注入:sql语句中出现了一些sql中的关键字,导致整个sql语句的含义发生了变化.即为sql注入!
- 防止sql注入的主要方法是让sql语句中不能出现特殊的关键字.
- 使用预编译语句即可保证sql语句中只能填入指定类型的值!
PreparedStatement对象
- 连接对象通过prepareStatement方法,可以获取一个预编译的对象,在获取时需要传递一个需要预先编译的sql语句.
- SQL语句中一般都会包含占位符?
- 在得到预编译语句后,通过setXXX(占位符索引,值)方法对占位符进行赋值!
- 占位符索引从1开始.
- 优点:提高效率,防止sql注入
二进制大对象:blob:***
- binary large object:
- 使用流技术上传和下载数据!
二进制大文本:text:***
使用流技术上传和下载数据!
批处理:
Statement接口和PreparedStatement接口都可以实现批处理!
前者更适合多种sql语句混合使用的场景.
后者更适合同种sql语句一起执行的场景.
注意:不同的数据库驱动版本可能对批处理有不同的支持!
MySQL默认没有开启批处理功能!
需要在url后添加如下属性开启此功能!
url=jdbc:mysql:///day17?useServerPrepStmts=true&cachePrepStmts=true&rewriteBatchedStatements=true
更改的是客户端的配置,不需要重启.
事务操作:
事务的操作都是通过连接对象进行的:
- 手动开启事务:
- void setAutoCommit(boolean on):设置为false就是开启了手动事务!
- 事务回滚:
- void rooback():
- 事务提交:
- void commit():
回滚点:
回滚点也是通过连接对象进行的操作!savepoint是接口
- 设置回滚点:
- Savepoint setSavepoint():
- 回滚到回滚点:
- void rollback(Savepoint sp):
标准事务处理:
try中处理
final中释放资源
连接池(数据源)
dbcp连接池(数据源):apache开源的数据源.
需要导入两个包:
需要设置的数据:
- 数据库连接四大参数:
- 第一种方式:将数据库连接的四大参数在程序中直接提供(硬编码)
- 第二种方式:使用Properties类关联到一个配置文件.将四大参数用配置文件提供!
- 池参数:一般保持默认!
- 最大空闲连接数
- 最大活动连接数
- 初始连接数
装饰者模式:decorator Wrapper
- 需要被装饰的类装饰类有共同的父类或者是接口!
- 先创建一个底层被包装对象,
- 再创建包装类对象时,将底层对象通过构造方法传递!!!
- 是你还有你!(是你:装饰类和被装饰的类有共同的父类(接口),还是你:在成员变量位置保持一个被装饰对象的引用)
- 一切拜托你!!(不关心的方法,直接调用底层被包装的对象的相应方法)
- 增强点上增强!!!(在增强方法肾功能进行逻辑上的增强)
package com.test7;
/*
* 装饰器模式:
* 包装一个对象,绝大多数方法保持不变,只在少数方法上进行增强!
*
*
*
* 对象增强的手段:常用的是继承!
* A
* AA extends A{
* ///
* }
*
* 咖啡 :
* 加奶咖啡:
* 加糖咖啡:
* 加盐咖啡:
* 加糖,加奶咖啡:
* ...
* 随着需求的不断变化,会导致类的暴增!!!
*
* 使用装饰器模式:
* 咖啡 :
*
* 咖啡 a = new 咖啡();
* 加奶咖啡 b = 加奶咖啡(a);
* 加糖咖啡 c = 加糖咖啡(b);
*
*
* 连接池:
* getConnection
* createStatement.
* prepareStatement
*
*
* 连接池在close方法上进行了增强!!!
* close
*
* jdk中使用装饰者典型的是:io流
*
* BufferedReader(Reader r)
*
*
*
*/
abstract class Animal{
public abstract void test1();
public abstract void test2();
public abstract void test3();
public abstract void test4();
}
class Dog extends Animal{
@Override
public void test1() {
System.out.println("dog test1");
}
@Override
public void test2() {
System.out.println("dog test2");
}
@Override
public void test3() {
System.out.println("dog test3");
}
@Override
public void test4() {
System.out.println("dog test4");
}
}
//装饰器类:让装饰器类和被装饰的类有共同的父类(接口).
//在装饰类中保持一个父类(接口)的引用.在构造方法中对其进行赋值
//在增强点方法上进行修改,其余的非增强点方法保持原样!!!
class DogWrapper extends Animal{
//保持一个父类的引用
Animal an = null;
//构造方法中对其赋值
public DogWrapper(Animal an){
this.an = an;
}
@Override
public void test1() {
an.test1();
}
@Override
public void test2() {
an.test2();
}
@Override
public void test3() {
an.test3();
}
//增强点方法
@Override
public void test4() {
System.out.println("hello");
an.test4();
System.out.println("world");
}
}
public class WrapperDemo {
public static void main(String[] args) {
// Animal a = new Dog();
Animal an = new Dog();
Animal a = new DogWrapper(an);
a.test1();
a.test2();
a.test3();
a.test4();
}
}
package com.test1;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import org.junit.Test;
import com.utils.Dbutils;
/*
* 使用工具类实现增删改查
*
*/
public class CRUDDemo2 {
//可以自己运行的方法,不需要main方法调用!
//
@Test
public void insert() throws Exception{
Connection conn = Dbutils.getConnection();
Statement st = conn.createStatement();
int res = st.executeUpdate("insert into stu2 values('Tyson','male','yes')");
//通过返回值是否是非0判断是否执行成功
if(res != 0){
System.out.println("插入数据成功");
}
//
st.close();
conn.close();
}
@Test
public void delete() throws Exception{
Connection conn = Dbutils.getConnection();
Statement st = conn.createStatement();
int res = st.executeUpdate("delete from stu2 where name = 'Tyson'");
//通过返回值是否是非0判断是否执行成功
if(res != 0){
System.out.println("删除数据成功");
}
//
st.close();
conn.close();
}
@Test
public void update() throws Exception{
Connection conn = Dbutils.getConnection();
Statement st = conn.createStatement();
int res = st.executeUpdate("update stu2 set zhuxiao = 'yes' where name = 'Frank'");
//通过返回值是否是非0判断是否执行成功
System.out.println(res);
if(res != 0){
System.out.println("更新数据成功");
}
//
st.close();
conn.close();
}
@Test
public void search() throws Exception{
//
Connection conn = Dbutils.getConnection();
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("select * from stu2");
while(rs.next()){
String name = rs.getString(1);
String gender = rs.getString(2);
String zhuxiao = rs.getString(3);
System.out.println(name+","+gender+","+zhuxiao);
}
//
rs.close();
st.close();
conn.close();
}
}
package com.test1;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
import org.junit.Test;
import com.utils.Dbutils;
/*
* Statement接口
*
* executeUpdate(String sql):增删改操作
* executeQuery(String sql):针对查询
* execute(String sql):执行任意的sql语句
*
* 结果集的操作:
* 游标的移动:
* next():
* previous():
* void afterLast():
* void beforFirst():
* boolean first():
* boolean last():
*
* absolute(int row):
* relative(int count):count正数,往下移动,负数,往上移动
*
* getRow():获取当前行编号!
*
* 获取结果集的特性:
* 通过获取Statement语句时指定的参数指定!!!
*
*
* 结果集的元数据:描述数据的数据!
* 如果我不知道结果集有多少列!如何遍历结果集?
* 通过结果集的元数据!!
* 元数据里可以获取列的数量.
* 通过while循环遍历行,通过for循环遍历列.
*
*/
public class CRUDDemo3 {
@Test
public void search3() throws Exception{
//
Connection conn = Dbutils.getConnection();
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("select * from stu2");
//如果不知道结果集的列数,如果遍历?
ResultSetMetaData metaData = rs.getMetaData();
int count = metaData.getColumnCount();
//遍历结果集
while(rs.next()){
//遍历列:
for(int i = 1;i<=count;i++){
Object obj = rs.getObject(i);
System.out.print(obj);
if(i != count){
System.out.print(", ");
}
}
//
System.out.println();
}
//
st.close();
conn.close();
}
@Test
public void search() throws Exception{
//
Connection conn = Dbutils.getConnection();
Statement st = conn.createStatement();
// boolean b = st.execute("select * from stu2");
// if(b){
// //获取结果集
// ResultSet rs = st.getResultSet();
// while(rs.next()){
// String name = rs.getString(1);
// System.out.println(name);
// }
// rs.close();
// }
ResultSet rs = st.executeQuery("select * from stu2");
System.out.println(rs.getRow());
rs.absolute(5);
System.out.println(rs.getRow());
//获取结果集的行数
rs.afterLast();
rs.previous();
System.out.println(rs.getRow());
rs.close();
//
st.close();
conn.close();
}
@Test
public void search2() throws Exception{
//
Connection conn = Dbutils.getConnection();
Statement st = conn.createStatement();
/*
* 第一个参数:结果集的类型:可滚动,不敏感,不可更新
* ResultSet.TYPE_FORWARD_ONLY: 结果集的游标只能往下滚动
* ResultSet.TYPE_SCROLL_INSENSITIVE : 对数据库底层数据变化不敏感
* ResultSet.TYPE_SCROLL_SENSITIVE : 对数据库底层数据变化敏感
* MySQL只支持第二种!!!
*
* 第二个参数:结果集的变化是否能更新到底层数据库,
* ResultSet.CONCUR_READ_ONLY : 结果集的更改不更新到底层的数据库
* ResultSet.CONCUR_UPDATABLE : 结果集的更改更新到底层的数据库
* 目前,所有的数据库都只支持第一种!!!
*
* MySQL获取的Statement对象,默认是以下组合!!
* ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY
*
*/
ResultSet rs = st.executeQuery("select * from stu2");
System.out.println(rs.getRow());
rs.absolute(5);
System.out.println(rs.getRow());
//获取结果集的行数
rs.afterLast();
rs.previous();
System.out.println(rs.getRow());
rs.close();
//
st.close();
conn.close();
}
}
package com.test1;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import org.junit.Test;
import com.utils.Dbutils;
/*
* 加上异常处理的程序
* 资源的释放一般放在finally块中!!
*
*/
public class CRUDDemo4 {
@Test
public void search3(){
//作用域提升
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try{
conn = Dbutils.getConnection();
st = conn.createStatement();
rs = st.executeQuery("select * from stu2");
//如果不知道结果集的列数,如果遍历?
ResultSetMetaData metaData = rs.getMetaData();
int count = metaData.getColumnCount();
//遍历结果集
while(rs.next()){
//遍历列:
for(int i = 1;i<=count;i++){
Object obj = rs.getObject(i);
System.out.print(obj);
if(i != count){
System.out.print(", ");
}
}
//
System.out.println();
}
}catch(Exception e){
System.out.println(e.getMessage());
}finally{
//
try {
//非空判断
if(st != null){
st.close();
}
} catch (SQLException e) {
}
try {
if(conn != null){
conn.close();
}
} catch (SQLException e) {
}
try {
if(rs != null){
rs.close();
}
} catch (SQLException e) {
}
}
}
}
package com.test3;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import com.utils.Dbutils;
/*
* blob:
* binary large object
* 可执行程序,图片,视频,音频....
*
* 一般不会放到数据库中,效率低:
*
* 数据库存放的绝大多数都是字符串!
* 数据库中保存的是资源的路径!!!
*
* tinyblob:255字节
* blob:64K
* midumblob:16M
* longblob:4G
*
*/
public class BlobDemo {
public static void main(String[] args) throws Exception {
insert2();
}
// 往数据库中存图片
private static void insert2() throws Exception {
Connection conn = Dbutils.getConnection();
PreparedStatement pst = conn.prepareStatement("insert into my_blob values(null,?)");
// 对占位符进行赋值
pst.setBinaryStream(1, new FileInputStream("c:/dog.jpg"));
// 插入数据
int res = pst.executeUpdate();
if (res != 0) {
System.out.println("插入图片成功");
}
//
pst.close();
conn.close();
}
// 往数据库中存图片
private static void insert() throws Exception {
Connection conn = Dbutils.getConnection();
PreparedStatement pst = conn.prepareStatement("insert into my_blob values(null,?)");
// 对占位符进行赋值
pst.setBinaryStream(1, new FileInputStream("c:/PresionBreak.jpg"));
// 插入数据
int res = pst.executeUpdate();
if (res != 0) {
System.out.println("插入图片成功");
}
//
pst.close();
conn.close();
}
}
package com.test3;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import com.utils.Dbutils;
/*
* blob:
* binary large object
* 可执行程序,图片,视频,音频....
*
* 一般不会放到数据库中,效率低:
*
* 数据库存放的绝大多数都是字符串!
* 数据库中保存的是资源的路径!!!
*
* tinyblob:255字节
* blob:64K
* midumblob:16M
* longblob:4G
*
*/
public class BlobDemo {
public static void main(String[] args) throws Exception {
// insert2();
read();
}
//从数据库读取图片:底层使用的是流!!!
private static void read() throws Exception {
Connection conn = Dbutils.getConnection();
PreparedStatement pst = conn.prepareStatement("select data from my_blob where id = 2");
ResultSet rs = pst.executeQuery();
// while(rs.next()){
//
// }
rs.next();
//列的序号是结果集中的列的序号,而不是表设计时的序号!!
InputStream in = rs.getBinaryStream(1);
//创建输出流
FileOutputStream out = new FileOutputStream("c:/dog22.jpg");
byte[] buf = new byte[1024 * 8];
int len = 0;
while((len = in.read(buf)) != -1){
out.write(buf, 0, len);
}
//
out.close();
in.close();
rs.close();
pst.close();
conn.close();
}
// 往数据库中存图片
private static void insert2() throws Exception {
Connection conn = Dbutils.getConnection();
PreparedStatement pst = conn.prepareStatement("insert into my_blob values(null,?)");
// 对占位符进行赋值
pst.setBinaryStream(1, new FileInputStream("c:/dog.jpg"));
// 插入数据
int res = pst.executeUpdate();
if (res != 0) {
System.out.println("插入图片成功");
}
//
pst.close();
conn.close();
}
// 往数据库中存图片
private static void insert() throws Exception {
Connection conn = Dbutils.getConnection();
PreparedStatement pst = conn.prepareStatement("insert into my_blob values(null,?)");
// 对占位符进行赋值
pst.setBinaryStream(1, new FileInputStream("c:/PresionBreak.jpg"));
// 插入数据
int res = pst.executeUpdate();
if (res != 0) {
System.out.println("插入图片成功");
}
//
pst.close();
conn.close();
}
}
package com.test3;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.Reader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import com.utils.Dbutils;
/*
* tinytext:255字节
* text:64K
* mediumtext:16M
* longtext:4G
*
*/
public class TextDemo {
public static void main(String[] args) throws Exception {
// insert();
read();
}
//从数据库读取文本
private static void read() throws Exception {
Connection conn = Dbutils.getConnection();
PreparedStatement pst = conn.prepareStatement("select data from my_text where id = 1");
ResultSet rs = pst.executeQuery();
rs.next();
Reader r = rs.getCharacterStream(1);
//创建字符输出流
FileWriter w = new FileWriter("c:/text.txt");
char[] buf = new char[1024 * 8];
int len = 0;
while((len = r.read(buf)) != -1){
w.write(buf, 0, len);
}
//
w.close();
r.close();
rs.close();
pst.close();
conn.close();
}
//插入文本
private static void insert() throws Exception {
Connection conn = Dbutils.getConnection();
PreparedStatement pst = conn.prepareStatement("insert into my_text values(null,?)");
pst.setCharacterStream(1, new FileReader("dbconfig.txt"));
int res = pst.executeUpdate();
if(res != 0){
System.out.println("插入数据成功");
}
pst.close();
conn.close();
}
}
package com.test4;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import com.utils.Dbutils;
/*
* 批处理:
* Statement接口中的方法:
* PreparedStatement接口也可以使用!!!
*
* addBatch(String sql):
* executeBatch():
* clearBatch():
*
*
* Statement:适合多种类型的操作混合在一起操作
* PreparedStatement:适合同一种操作,但是参数不同!!
*
*/
public class BatchDemo {
public static void main(String[] args) throws Exception {
// test1();
long start = System.currentTimeMillis();
test2();
System.out.println(System.currentTimeMillis() - start);
}
//使用预编译语句的批处理
private static void test2() throws Exception {
Connection conn = Dbutils.getConnection();
PreparedStatement pst = conn.prepareStatement("insert into stu values(null,?,?)");
for(int i = 1;i<=1000;i++){
pst.setString(1, "name" + i);
pst.setInt(2, i);
//把当前语句放到批处理中
pst.addBatch();
//
if(i % 200 == 0){
pst.executeBatch();
}
}
//执行批处理
pst.executeBatch();
//
pst.close();
conn.close();
}
private static void test1() throws Exception, SQLException {
Connection conn = Dbutils.getConnection();
Statement st = conn.createStatement();
//添加批处理
st.addBatch("insert into stu values(null,'zhangsan',10)");
st.addBatch("insert into stu values(null,'lisi',10)");
st.addBatch("insert into stu values(null,'赵六',20)");
st.addBatch("insert into stu values(null,'王五',30)");
st.addBatch("insert into stu values(null,'Tyson',50)");
//
st.executeBatch();
//
st.close();
conn.close();
}
}
package com.test5;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.sql.Statement;
import com.utils.Dbutils;
/*
* 默认jdbc也是自动事务.
* 手动开启事务:
* 使用连接对象的方法:
* setAutoCommit(boolean on):设置为false,意味着手动事务开启
*
* commit():提交事务
* rollback():回滚到事务开启之前
* rollback(Savepoint sp):回滚到指定保存点
*
* setSavepoint():获取一个保存点
*
*/
public class TransactionDemo {
public static void main(String[] args) {
Connection conn = null;
Statement st = null;
Savepoint sp1 = null;
try{
//正常提交
conn = Dbutils.getConnection();
conn.setAutoCommit(false);
//
st = conn.createStatement();
st.executeUpdate("insert into student values (6,'yyy',10,20,1)");
//设置保存点:
sp1 = conn.setSavepoint();
int res = st.executeUpdate("update student set name = 'xxx' where id = 6");
// if(res != 0){
// System.out.println("更新成功");
// }
//异常
if(true){
throw new RuntimeException("发生异常");
}
//提交
conn.commit();
}catch(Exception e){
//异常回滚
System.out.println(e.getMessage());
//回滚到回滚点
try {
if(conn != null){
conn.rollback(sp1);
//结束事务:否则保存点之前的操作不能更新到底层数据库!!!
conn.commit();
}
} catch (SQLException e1) {
e1.printStackTrace();
}
}finally{
try {
if(st != null){
st.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(conn != null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
private static void test1() throws Exception, SQLException {
Connection conn = Dbutils.getConnection();
//手动开启事务
conn.setAutoCommit(false);
//
conn.createStatement().executeUpdate("delete from student where id = 2");
//回滚
// conn.rollback();
//提交
conn.commit();
//
conn.close();
}
}
-----------------------------------------------------------------
作业:
对一个对象的有返回值的方法进行增强!在方法前加"hello",方法调用后,加"world"
package com.homework;
/*
* 对一个对象的有返回值的方法进行增强!
在方法前加"hello",方法调用后,加"world".
*/
abstract class Animal{
public abstract void t1();
public abstract String t2();
}
class Dog extends Animal{
@Override
public void t1() {
System.out.println("Dog.t1()");
}
@Override
public String t2() {
System.out.println("Dog.t2()");
return "xxx";
}
}
class DogWrapper extends Animal{
Animal an ;
public DogWrapper(Animal an){
this.an = an;
}
@Override
public void t1() {
an.t1();
}
@Override
public String t2() {
System.out.println("hello");
String res = an.t2();
System.out.println("world");
return res;
}
}
public class Demo {
public static void main(String[] args) {
//被包装对象
Dog d = new Dog();
//创建包装类对象
DogWrapper dw = new DogWrapper(d);
//
dw.t1();
//
String res = dw.t2();
System.out.println(res);
}
}
--------------------------------------------------
使用set local xxx = ... 是对本地变量进行设置.
本次会话立即生效!
总结:
对客户端的会话变量进行设置:使用set local ...
对服务端的系统变量进行设置:使用set global ...
---恢复内容结束---