DAO模式及单例模式

为什么进行JDBC封装2-1

1、将相似功能的代码抽取封装成方法,减少代码冗余

2、因为不同的数据库会有不同的实现,对数据库的操作一般抽取成接口,在以后的开发中可以降低耦合
在这里插入图片描述

  1. 隔离业务逻辑代码和数据访问代码
  2. 隔离不同数据库的实现

在这里插入图片描述

实现JDBC封装

  • 将所有增删改查操作抽取成接口
  • 定义实体类传输数据
  • 将通用的操作(打开、关闭连接等)封装到工具类
  • 数据库工具类BaseDao:增、删、改、查的通用方法
public class BaseDao {
    public Connection getConn() throws Exception {
        //加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        String url="jdbc:mysql://192.168.83.35:3306/MySchool";
        //驱动管理器来获取连接
        Connection conn= DriverManager.getConnection(url,"root","ok");
        return conn;
    }
    public void showTables() throws Exception {
        //获取连接
        Connection conn=getConn();
     //先获取Statement对象
        Statement stmt=conn.createStatement();
        String sql="show tables";
        ResultSet rs = stmt.executeQuery(sql);
        while(rs.next()){
            System.out.println(rs.getString("Tables_in_MySchool"));
        }
    }


    public ResultSet query(String sql) throws Exception{
        Connection conn=getConn();
        Statement stmt=conn.createStatement();
        String sql1=sql;
        ResultSet rs = stmt.executeQuery(sql1);
        return  rs;
    }
    
    public int update(String sql)throws Exception{
        Connection conn=getConn();
        Statement stmt=conn.createStatement();
        int i = stmt.executeUpdate(sql);
        return  i;


    }
}
package demo;


import entiry.Student;
import org.junit.Test;


import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;


import static org.junit.Assert.*;


public class BaseDaoTest {


    @Test
    public void getConn() throws Exception {
        BaseDao dao=new BaseDao();
        Connection conn=dao.getConn();
        System.out.println(conn);
    }


    @Test
    public void showTables() throws Exception {
        BaseDao dao=new BaseDao();
        dao.showTables();
    }
    @Test
    public  void query() throws Exception {
        BaseDao dao=new BaseDao();
        String sql="select * from student";
        ResultSet rs=dao.query(sql);
        ArrayList<Student> stulist=new ArrayList<>();
        while (rs.next()){
            Student s=new Student();
            s.setStudentNo(rs.getInt("StudentNo"));
            s.setStudentName(rs.getString("StudentName"));
            stulist.add(s);
        }
        for (Student student : stulist) {
            System.out.println(student);
        }


    }


    @Test
    public void update() throws Exception {
        BaseDao dao=new BaseDao();
        String sql="insert into student(StudentNo,StudentName) "+
                "values(1011,'一灯'),(1065,'因故')";
        int num=dao.update(sql);
        System.out.println(num > 0 ? "插入成功" : "插入失败");
    }
    //使用jdbc创建一个库,切换到这个库,创建一个表
    @Test
    public void testDo() throws Exception{
        BaseDao dao=new BaseDao();
        Connection conn=dao.getConn();
        Statement stmt=conn.createStatement();
        String createDabase="create database if not exists userControl";
        boolean isSuccess = stmt.execute(createDabase);
        System.out.println(isSuccess);
        String changeDatabase="use userControl";
        stmt.execute(changeDatabase);
        String createTable="create table user_info(" +
                "uid int(11) auto_increment primary key," +
                "uname varchar(30)," +
                "password varchar(30))";
        stmt.execute(createTable);
    }
}

什么是DAO

  • Data Access Object(数据存取对象)
  • 位于业务逻辑和持久化数据之间
  • 实现对持久化数据的访问

在这里插入图片描述

DAO模式的组成

DAO模式的组成部分

  • DAO接口
  • DAO实现类
  • 实体类
  • 数据库连接和关闭工具类

优势

  • 隔离了数据访问代码和业务逻辑代码
  • 隔离了不同数据库实现

配置数据库访问参数

弊端

数据库发生改变时,要重新修改代码,重新编译和部署

解决

将数据库信息写在配置文件当中,让程序通过读取配置文件来获得这些信息

属性文件

  • 后缀为.properties
  • 数据格式为“键=值”
  • 使用“#”来注释
    在这里插入图片描述
package demo;


import until.Prop;


import java.sql.*;


/**
* @Author lichangxin
* @date 2020-08-21
* @Des
*/


public class PstDao {
    private static String driver= Prop.getP("driver");
    private static String url=Prop.getP("url");
    private static String user=Prop.getP("user");
    private static String pwd=Prop.getP("pwd");


    public static Connection getConn(){
        try {
            Class.forName(driver);
            return DriverManager.getConnection(url,user,pwd);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }


    public static void close(Connection conn, PreparedStatement pst, ResultSet rs){
        if (conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (pst!=null){
            try {
                pst.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }


    public static ResultSet query(String sql,Object ...params ){
        Connection conn = getConn();
        PreparedStatement pst=null;
        ResultSet rs=null;
        try {
             pst=conn.prepareStatement(sql);
            for (int i = 0; i < params.length; i++) {
                pst.setObject(i+1,params[i]);
            }
            rs=pst.executeQuery();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
//            close(conn,pst,null);
        }
        return rs;
    }


    public static int update(String sql,Object...params){
        Connection conn=getConn();
        PreparedStatement pst=null;
        try {
            pst=getConn().prepareStatement(sql);
            for (int i = 0; i < params.length; i++) {
                pst.setObject(i+1,params[i]);
            }
            return pst.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {if (pst!=null) {
                pst.close();
            }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (conn!=null) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return -1;


    }
}
package demo;


import org.junit.Test;


import java.sql.ResultSet;
import java.sql.SQLException;


import static org.junit.Assert.*;


public class PstDaoTest {


    @Test
    public void query() throws SQLException {
        String sql="SELECT SubjectName,score FROM `subject` s " +
                "JOIN result r ON s.SubjectNo=r.sub_no WHERE score>? AND SubjectName IN(?,?)";
        ResultSet rs=PstDao.query(sql,60,"高等数学-1","高等数学-2");
        while (rs.next()){
            System.out.print(rs.getString("SubjectName")+"----");
            System.out.println(rs.getInt("score"));
        }
        rs.close();
    }


    @Test
    public void update(){
        String sql="update account set cash=cash+? where name=?";
        int num=PstDao.update(sql,10000,"icbc");
        System.out.println(num > 0 ? "更新成功" : "更新失败");
    }
}
package until;


import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;


/**
* @Author lichangxin
* @date 2020-08-21
* @Des
*/


public class Prop {
    private  static Properties p=new Properties();
    public  static String getP(String param){
        try {
            p.load(new FileInputStream("resources/db.properties"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return p.getProperty(param);
    }
}
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://192.168.83.35:3306/shop
user=root
pwd=ok

为何需要单例模式

  • BaseDao:操作数据库的基类
  • 每个线程对系统操作都需new一个BaseDao实例
  • 初始化时的I/O操作消耗系统资源,影响系统性能

系统运行期间,有且仅有一个实例

一个类只有一个实例——最基本的要求

只提供私有构造器

它必须自行创建这个实例

定义了静态的该类私有对象

它必须自行向整个系统

提供这个实例提供一个静态的公有方法,返回创建或者获取本身的静态私有对象

懒汉模式

在类加载时不创建实例,采用延迟加载的方式,在运行调用时创建实例
特点

  1. 线程不安全
  2. 延迟加载(lazy loading)

如何解决线程安全问题?
同步(synchronized)

饿汉模式

在类加载的时候,就完成初始化
特点

  1. 线程安全
  2. 不具备延迟加载特性
单例模式懒汉模式饿汉模式
概念在类加载时不创建实例,采用延迟加载的方式,在运行调用时创建实例在类加载的时候,就完成初始化
特点类加载速度快,但是运行时获取对象的速度较慢。——“时间换空间”类加载较慢,但获取对象速度快。——“空间换时间”
延迟加载(lazy loa ding)具备不具备
线程安全线程不安全线程安全
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值