2021/07/30笔记

我们于2021/07/30 的学习目标是:数据库、JDBC与MyBatis,核心任务为:

1、学习技术:

1)、删除delete与截断truncate

2)、事务

3)、JDBC的概念

4)、JDBC工具类

5)、预处理块

6)、BaseDao

7)、MyBatis

2、文档总结

1)、删除delete与截断truncate

delete from 表名 where 行过滤条件

主外键关系如下:

删除从表中的数据,可以直接删除

删除主表中的数据:违反约束条件,不允许直接删除

前提:主表被从表中数据引用

要删除被从表引用的主表数据:

  1. 先删除从表中引用的数据,再删除主表数据(默认)
  2. 删除主表数据的同时删除哪些引用了当前主表数据的从表数据
  3. 删除主表数据,从表中那些引用了当前主表数据的外键字段设置为null。
cid number(5) references class(cid) on delete set null;

truncate截断数据:可以实现截断(删除)表中所有的数据

truncate table t_user;

truncate不会开启事务,delete默认会开启事物

截断表中的数据时,如果表是主表,从表结构检查上不允许

2)、事务

事务:单个逻辑工作单元执行的一组相关操作。这些操作要求全部完成或全部不完成。使用事务是为了保证数据安全有效。

事务的特点:

  1. 原子性(Atomic):事务中所有数据的修改,要么全部执行,要么全部不执行。
  2. 一致性(Consistent):事务完成时,要使所有的数据都保持一致的状态。换言之:通过事务进行的所有数据修改,必须在所有相关的表中得到反映。
  3. 隔离性(Isolation):事务应该在另一个事务对数据的修改前或修改后进行访问。
  4. 持久性(Durability):保证事务对数据库的修改是持久有效的,即使发生系统故障也不应丢失。

事务的隔离级别:

隔离级别

脏读

不可重复读

幻读

Read Uncommitted(读未提交)

Read Committed(读已提交)

Repeatable Read(可重复读)

Serializable(串行读)

Oracle默认的隔离级别是Read Committed。

Oracle支持Read Committed和Serializable。除此之外,Oracle中还定义了Read only与Read write隔离级别。

Read only:事务中不能有任何修改数据库中数据的操作语句,是Serializable的一个子集。

Read Write:它是默认配置,该选项表示在事务中可以有访问语句和修改语句,但不经常使用。

丢失更新:两个事务同时存储,其中一个的更新未成功

脏读:一个事务更新数据,未提交修改;另一个读到后回滚,读到的这种数据为脏读数据。

不可重复读:一个事务读取一行数据,另一个事务修改了刚刚读取的记录,再次读取发现两次读取的数据不一致。

幻读:一个事务读取一条带Where条件的语句,返回结果集;另一个事务插入一条新记录,恰好符合Where条件,再次查询时看到了新记录,新纪录就叫做幻读。

事务的开启:自动开启于DML之insert delete update

成功:

事务的结束:分成功与失败

正常执行完成的DDL语句:create alter drop

正常执行完的DCL语句 grant revoke

正常退出的SQL客户端

如果人工要使用隐式事务,set autocommit on(只针对一个连接)

手动提交:commit

失败:

rollback手动回滚

非法退出

意外断电

注意:在Java中操作数据库,事务会自动提交

conn.commit();//提交

conn.rollback();//回滚

3)、JDBC的概念

JDBC:Java Database Connectivity Java与数据库的连接

角色分类:

   服务器(数据库端):接收SQL,执行SQL,返回结果

   客户端(Java端):接收数据,组装SQL,发送SQL,分析结果

面向接口编程:

Java提供的SQL接口在java.sql.*包下

Oracle实现接口(jar)

Java提供的SQL接口:

java.sql.Connection 连接

java.sql.Statement 静态处理块

java.sql.PreparedStatement 预处理块

java.sql.ResultSet 结果集

java.sql.ResultSetMetaData 结果集元信息

JDBC基本流程:

把Oracle实现Jar包拿到项目下 add as library

  1. 加载驱动(选择数据库)
  2. 建立连接 Connection (与数据库之间建立连接)
  3. 准备SQL
  4. 封装处理块,发送SQL
  5. 得到结果集
  6. 处理结果
  7. 关闭资源

import java.sql.*;

public class Class001_JDBC {

    public static void main(String[] args) throws ClassNotFoundException, SQLException {

        //1.加载驱动  (选择数据库)

        Class.forName("oracle.jdbc.driver.OracleDriver");

        //2.建立连接 Connection (与数据库之间建立连接)

        Connection conn = DriverManager.getConnection(

                "jdbc:oracle:thin:@localhost:1521:XE",

                "SCOTT",

                "TIGER"

        );

        //3.准备sql

        String sql = "select * from dept";

        //4.封装处理块

        Statement state = conn.createStatement();

        //5.发送sql,得到结果集

        ResultSet reault = state.executeQuery(sql);

        //6.处理结果

        while(reault.next()){

            //字段序号从1开始,每次+1

            int deptno = reault.getInt(1);

            String dname = reault.getString(2);

            String loc = reault.getString(3);

            System.out.println(deptno+"--->"+dname+"--->"+loc);

        }

        //7.关闭资源

        reault.close();

        state.close();

        conn.close();

    }

}



优化:

  1. 异常捕获
  2. 通过配置文件实现软编码
import java.io.IOException;

import java.sql.*;

import java.util.Properties;

public class Class002_JDBC {

    public static void main(String[] args){

        //构建 properties对象

        Properties pro = new Properties();

        try {

            pro.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));

        } catch (IOException e) {

            e.printStackTrace();

        }



        //1.加载驱动  (选择数据库)

        try {

            Class.forName(pro.getProperty("driver"));

        } catch (ClassNotFoundException e) {

            e.printStackTrace();

        }



        //2.建立连接 Connection (与数据库之间建立连接)

        Connection conn = null;

        Statement state = null;

        ResultSet result = null;

        try {

            conn = DriverManager.getConnection(

                    pro.getProperty("url"),

                    pro.getProperty("username"),

                    pro.getProperty("password")

            );

            //3.准备sql

            String sql = "select * from dept";

            //4.封装处理块

            state = conn.createStatement();

            //5.发送sql,得到结果集

            result = state.executeQuery(sql);

            //6.处理结果

            while(result.next()){

                //字段序号从1开始,每次+1

                int deptno = result.getInt(1);

                String dname = result.getString(2);

                String loc = result.getString(3);

                System.out.println(deptno+"--->"+dname+"--->"+loc);

            }



        } catch (SQLException throwables) {

            throwables.printStackTrace();

        } finally {

            //7.关闭资源

           if(result!= null){

               try {

                   result.close();

               } catch (SQLException throwables) {

                   throwables.printStackTrace();

               }

           }

            if(state!=null){

                try {

                    state.close();

                } catch (SQLException throwables) {

                    throwables.printStackTrace();

                }

            }

            if(conn!=null){

                try {

                    conn.close();

                } catch (SQLException throwables) {

                    throwables.printStackTrace();

                }

            }



        }



    }

}

4)、JDBC工具类

1.加载驱动

2.获取连接

3.关闭资源

静态块的内容每次运行都会加载,把加载模块放到静态块中

静态方法不能直接使用成员变量,需要静态变量

可以将获取连接和关闭资源的操作封装为静态方法

import java.io.IOException;

import java.sql.*;

import java.util.Properties;

public class DBUtils {

    private static Properties pro = new Properties();

    static{

        //1.加载驱动

        //构建 properties对象

        try {

            pro.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));

        } catch (IOException e) {

            e.printStackTrace();

        }



        //加载驱动  (选择数据库)

        try {

            Class.forName(pro.getProperty("driver"));

        } catch (ClassNotFoundException e) {

            e.printStackTrace();

        }

    }



    //2.获取连接

    public static Connection getConnection() throws SQLException {

        Connection conn = null;

        conn = DriverManager.getConnection(

                pro.getProperty("url"),

                pro.getProperty("username"),

                pro.getProperty("password")

        );

        return conn;

    }



    //3.关闭资源

    public static void close(ResultSet result, Statement state,Connection conn){

        if(result!= null){

            try {

                result.close();

            } catch (SQLException throwables) {

                throwables.printStackTrace();

            }

        }

        if(state!=null){

            try {

                state.close();

            } catch (SQLException throwables) {

                throwables.printStackTrace();

            }

        }

        if(conn!=null){

            try {

                conn.close();

            } catch (SQLException throwables) {

                throwables.printStackTrace();

            }

        }

    }

    public static void close(Statement state,Connection conn){

        close(null,state,conn);

    }

}

5)、预处理块

静态块:得到数据直接和SQL语句模板拼接

SQL注入:在数据中加入代码,使系统不安全

解决:通过预处理块处理和传递参数

预处理块优点:

  1. 防止SQL注入
  2. 预先编译,可以提高效率
import java.io.IOException;

import java.sql.*;

import java.util.Properties;

public class Class003_User {

    public static void main(String[] args){

        System.out.println(update("zhangsan","321321"));;



    }



    //修改根据用户名修改用户密码

    public static boolean update(String username,String password){

        //1.获取连接

        Connection conn = null;;

        PreparedStatement ps = null;

        boolean flag = false;



        try {

            conn = DBUtils.getConnection();



            //设置手动提交

            conn.setAutoCommit(false);



            //2.构建预处理块

            ps = conn.prepareStatement("update t_user set password=? where username=?");

            //3.为?赋值

            ps.setObject(1,password);

            ps.setObject(2,username);



            //4.执行,得到影响行数

            int rows = ps.executeUpdate();



            //5.判断

            if(rows>0){

                flag = true;

                conn.commit(); //提交

            }else{

                conn.rollback(); //回滚

            }

        } catch (SQLException throwables) {

            throwables.printStackTrace();

        } finally {

            DBUtils.close(ps,conn);

        }





        return flag;

    }





    //登录  : 1)根据用户名与密码一起到数据库中查询,查询到了数据登录成功,否则登录失败   2)根据用于名去查询,得到结果的密码值与用户输入的密码比较,相等登录,不等登录失败

    public static boolean login(String username,String password){

        //1.获取连接

        Connection conn = null;

        PreparedStatement state = null;

        ResultSet result = null;

        try {

            conn = DBUtils.getConnection();

            //2.准备sql

            String sql = "select * from t_user where username=? and password=?";



            //3.构建预处理快

            state = conn.prepareStatement(sql);

            //4.需要为sql中的?占位符传递参数

            state.setObject(1,username);

            state.setObject(2,password);



            //5.执行sql,得到结果集

            result = state.executeQuery();  //预处理块新增的方法 executeQuery()  executeUpdate()

           //5.处理结果

            if(result.next()){

                return true;

            }

        } catch (SQLException throwables) {

            throwables.printStackTrace();

        } finally {

            DBUtils.close(result,state,conn);

        }

        return false;

    }

    //修改

    //注销

    //注册用户

    public static boolean reg(String username,String password){

        //1.获取连接

        Connection conn = null;

        Statement state = null;

        try {

            conn = DBUtils.getConnection();

            //2.准备sql

            String sql = "insert into t_user values('"+username+"',"+password+")";



            //3.构建处理快

            state = conn.createStatement();

            //4.执行sql,得到结果

            int rows  = state.executeUpdate(sql);

            if(rows<=0){

                return false;

            }

        } catch (SQLException throwables) {

            throwables.printStackTrace();

        } finally {

            DBUtils.close(state,conn);

        }



        return true;

    }

}

6)、BaseDao

数据库通用访问对象封装 BaseDao --> 扩展

增删改 查询

可变参数:

...表示可变参数

对应类型的形参个数有0~n个

方法的形参列表最后存在

方法内部通过使用数组的方式使用可变参数接收的数据。

注意:在Oracle中的number类型在java中默认转为java.math.BigDecimal

import java.lang.reflect.Field;

import java.math.BigDecimal;

import java.sql.*;

import java.util.ArrayList;

import java.util.List;

public class BaseDao<T> {



    public List<T> testQuery(String sql,Class<T> cls,Object ...args){

        //1.获取连接

        Connection conn = null;

        PreparedStatement ps = null;

        ResultSet result= null;

        ResultSetMetaData data = null;

        List<T> list = new ArrayList<>(); //存储查询到的对象信息

        try {

            conn = DBUtils.getConnection();

            //2.构建预处理块

            ps = conn.prepareStatement(sql);

            //3.为?赋值

            if(args!=null && args.length!=0){

                for(int i=0;i<=args.length-1;i++){

                    ps.setObject(i+1,args[i]);

                }

            }

            //4.执行sql,得到相应行数

            result = ps.executeQuery();



            //结果集原信息对象

            data = result.getMetaData();

            //从结果集原信息对象上获取当前结果集中每条数据的字段个数

            int columnCount = data.getColumnCount();



            //5.处理数据

            //循环遍历结果集

            while(result.next()){

                //查询出一条数据,对应创建java中的一个对象

                T obj = cls.newInstance();

                //循环获取每一个列的值,获取每一个属性,为对象属性赋值

                for(int i=1;i<=columnCount;i++){

                    //获取每一条数据的每一个字段的值

                    Object value = result.getObject(i);

                    //判断value是否指向一个java.math.BigDecimal类型的对象,转为对应的int

                    if(value instanceof BigDecimal){

                        BigDecimal b = (BigDecimal)value;

                        value = b.intValue();

                    }



                    //获取字段的名字

                    String columnName = data.getColumnLabel(i);

                    //获取与字段所对应的属性

                    Field field = cls.getDeclaredField(columnName);

                    //为当前创建的对象的这个属性赋值

                    //忽略权限

                    field.setAccessible(true);

                    field.set(obj,value);

                }

                //把对象放入集合

                list.add(obj);

            }



        } catch (SQLException throwables) {

            throwables.printStackTrace();

        } catch (IllegalAccessException e) {

            e.printStackTrace();

        } catch (InstantiationException e) {

            e.printStackTrace();

        } catch (NoSuchFieldException e) {

            e.printStackTrace();

        } finally {

            DBUtils.close(ps,conn);

        }

        return list;

    }



    /**

     * 增删改

     * @param sql  要执行的sql语句

     * @param args 为?赋值的实参

     * @return 成功与否

     */

    public boolean update(String sql,Object[] args){

        //1.获取连接

        Connection conn = null;

        PreparedStatement ps = null;

        boolean flag = false;

        try {

            conn = DBUtils.getConnection();

            //2.构建预处理块

            ps = conn.prepareStatement(sql);

            //3.为?赋值

            if(args!=null && args.length!=0){

               for(int i=0;i<=args.length-1;i++){

                   ps.setObject(i+1,args[i]);

               }

            }

            //4.执行sql,得到相应行数

            int rows = ps.executeUpdate();



            //5.对相应行数判断结果

            if(rows>0){

                flag = true;

            }

        } catch (SQLException throwables) {

            throwables.printStackTrace();

        } finally {

            DBUtils.close(ps,conn);

        }

        return flag;

    }

}

7)、MyBatis

MyBatis:更加简化jdbc代码,简化持久层,sql语句从代码中分离,利用反射,将表中数据与java bean 属性一一映射 即ORM(Object Relational Mapping 对象关系映射)

使用范围:日常的开发项目,中小型开发

特点:持久层 对象关系映射框架(ORM) 半自动化

使用mybatis框架的步骤:

下载jar包,jar包资源拿到项目中,add as lib...

mybatis核心jar包

mybatis依赖jar包

数据库的驱动jar

定义mybatis核心配置文件--> 参考文档+官网

定义sql映射文件

定义要执行的sql语句

jar类中进行测试

加载核心配置文件

构建工厂

获取回话

执行sql

处理结果

关闭回话

project01_mybatis.iml

<?xml version="1.0" encoding="UTF-8"?>

<module type="JAVA_MODULE" version="4">

  <component name="NewModuleRootManager" inherit-compiler-output="true">

    <exclude-output />

    <content url="file://$MODULE_DIR$">

      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />

    </content>

    <orderEntry type="inheritedJdk" />

    <orderEntry type="sourceFolder" forTests="false" />

    <orderEntry type="library" name="asm-7.1" level="project" />

  </component>

</module>

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE configuration

        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"

        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<!--根元素: 核心配置-->

<configuration>

    <!--

        环境配置

        default : 要使用的环境的id值

    -->

    <environments default="ev">

        <!--environment : 一个环境的配置    id: 当前环境的唯一标识 -->

        <environment id="ev">

            <!--transactionManager 事务管理器   type="JDBC" :选择与jdbc相同的事务管理机制 -->

            <transactionManager type="JDBC"/>

            <!--数据源配置  type="POOLED" :  通过数据库连接池管理连接-->

            <dataSource type="POOLED">

                <property name="driver" value="oracle.jdbc.driver.OracleDriver"/>

                <property name="url" value="jdbc:oracle:thin:@localhost:1521:XE"/>

                <property name="username" value="SCOTT"/>

                <property name="password" value="TIGER"/>

            </dataSource>

        </environment>

    </environments>

    <!--sql映射配置加载 : 定义sql语句的配置文件-->

    <mappers>

        <mapper resource="com/yjxxt/mappers/DeptMapper.xml"/>

    </mappers>

</configuration>

Java Class

import com.yjxxt.entity.Dept;

import org.apache.ibatis.io.Resources;

import org.apache.ibatis.session.SqlSession;

import org.apache.ibatis.session.SqlSessionFactory;

import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;

import java.io.InputStream;

import java.util.List;

public class Class001_Dept {

    public static void main(String[] args) throws IOException {

        //1.加载mybatis的核心配置文件

        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");

        //2.构建SqlSessionFactory

        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);

        //3.根据工厂构建回话

        SqlSession session = factory.openSession();

        //4.执行sql,得到结果

        //selectList("命名空间.id")

        List<Dept> list =  session.selectList("com.yjxxt.mappers.DeptMapper.queryAll");

        //5.处理结果

        list.forEach(System.out::println);

        //5.关闭回话

        session.close();

    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值