MySQL成长之路(005)
一、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 ...