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) 具备 不具备
线程安全 线程不安全 线程安全

猜你喜欢

转载自blog.csdn.net/zmzdmx/article/details/108207091