JDBC笔记

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层结构
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值