学习JDBC的Dao模式

JDBC—Dao模式的学习

  1. Dao模式是一种软件工程中使用的设计模式,用于将业务逻辑与持久性逻辑分离。它提供了一种访问数据库或其他数据源中的数据的方式,而不暴露数据源的底层细节。Dao模式通常与其他设计模式(如工厂模式)一起使用,以提供完整的数据访问和操作解决方案。
  2. Dao模式是用来:当我们完成一个业务需求需要使用资源时,如果直接调用资源层,就要直接对数据库进行操作,这时,业务层不光要完成具体业务的实现,还需要兼顾——编写SQL语句、连接数据库、和数据库进行交互、获得数据等等的操作。而且不利于一个程序的重用性。所以我们需要让业务层只来做业务实现,这时候和数据库的沟通交流就要交给DAO层来实现。
  3. Dao模式的结构,以本篇为例如图所示:
    在这插入图片描述
    首先,我们需要建立一个数据库,以本篇为例我们建立一个my_shop_db数据库,在库中添加四张表格,商品分类表、商品表、用户表和订单表:tb_cateproy、tb_order、tb_prod、tb_user,方便之后获取Dao的实例化对象。建表语句如下,数据库信息的录入可以参考以下:

商品分类表:

--创建商品分类表:
CREATE TABLE `tb_category` (
                               `category_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT '类目ID',
                               `shop_id` bigint NOT NULL COMMENT '店铺ID',
                               `parent_id` bigint unsigned NOT NULL COMMENT '父节点',
                               `category_name` varchar(50) NOT NULL DEFAULT '' COMMENT '产品类目名称',
                               `icon` varchar(255) DEFAULT NULL COMMENT '类目图标',
                               `pic` varchar(300) DEFAULT NULL COMMENT '类目的显示图片',
                               `seq` int NOT NULL COMMENT '排序',
                               `status` int NOT NULL DEFAULT '1' COMMENT '默认是1,表示正常状态,0为下线状态',
                               `rec_time` datetime NOT NULL COMMENT '记录时间',
                               `grade` int NOT NULL COMMENT '分类层级',
                               `update_time` datetime DEFAULT NULL COMMENT '更新时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--向表中录入数据
insert into tb_category values (85,1,0,'手机数码',null,null,1,1,'2019-04-21 17:28:33',0,'2019-04-30 18:00:25'),
                               (87,1,0,'美妆护肤',null,null,1,1,'2019-04-21 17:28:33',0,'2019-04-30 18:00:25'),
                               (88,1,0,'运动服饰',null,null,1,1,'2019-04-21 17:28:33',0,'2019-04-30 18:00:25'),
                               (93,1,85,'手机通信',null,null,1,1,'2019-04-21 17:28:33',0,'2019-04-30 18:00:25'),
                               (94,1,85,'智能设备',null,null,1,1,'2019-04-21 17:28:33',0,'2019-04-30 18:00:25'),
                               (95,1,0,'美味零食',null,null,1,1,'2019-04-21 17:28:33',0,'2019-04-30 18:00:25'),
                               (96,1,85,'珠宝钟表',null,null,1,1,'2019-04-21 17:28:33',0,'2019-04-30 18:00:25');

商品表:

--创建商品表
CREATE TABLE `tb_prod` (
                           `prod_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT '产品ID',
                           `prod_name` varchar(300) NOT NULL DEFAULT '' COMMENT '商品名称',
                           `shop_id` bigint DEFAULT NULL COMMENT '店铺id',
                           `ori_price` decimal(15,2) DEFAULT '0.00' COMMENT '原价',
                           `price` decimal(15,2) DEFAULT NULL COMMENT '现价',
                           `brief` varchar(500) DEFAULT '' COMMENT '简要描述,卖点等',
                           `content` text COMMENT '详细描述',
                           `pic` varchar(255) DEFAULT NULL COMMENT '商品主图',
                           `imgs` varchar(1000) DEFAULT NULL COMMENT '商品图片,以,分割',
                           `status` int DEFAULT '0' COMMENT '默认是1,表示正常状态, -1表示删除, 0下架',
                           `category_id` bigint unsigned DEFAULT NULL COMMENT '商品分类',
                           `sold_num` int DEFAULT NULL COMMENT '销量',
                           `total_stocks` int DEFAULT '0' COMMENT '总库存',
                           `delivery_mode` json DEFAULT NULL COMMENT '配送方式json见TransportModeVO',
                           `delivery_template_id` bigint DEFAULT NULL COMMENT '运费模板id',
                           `create_time` datetime DEFAULT NULL COMMENT '录入时间',
                           `update_time` datetime DEFAULT NULL COMMENT '修改时间',
                           `putaway_time` datetime DEFAULT NULL COMMENT '上架时间',
                           `version` int DEFAULT NULL COMMENT '版本 乐观锁'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--录入数据
insert into tb_prod() values (18,'Apple iphone XS Max 移动版',1,0.00,1.01,'6.5英寸大屏,双卡双待',null,null,null,1,93,null,null,null,null,'2019-04-21 17:28:33','2019-04-30 18:00:25','2019-04-30 18:00:25',null);

创建订单表和用户表:

--创建商品订单表
create table tb_order(
    order_id int not null auto_increment primary key ,
    order_number varchar(40) not null comment '订单号',
    user_id int not null comment '用户编号',
    total double not null  comment '订单总价',
    acutal_total int comment '实付价格',
    status varchar(30) comment '支付状态',
    pay_time datetime  comment '支付时间',
    is_payed varchar(20) comment '是否支付'
);
--用户表
create table tb_user(
    user_id int primary key not null comment '用户编号',
    user_name varchar(50) not null  comment '用户登录名',
    login_password varchar(40) not null  comment '登录密码',
    real_name varchar(30) default null comment '真名',
    mail varchar(200) default null comment '邮箱',
    mobile varchar(50) not null comment '电话',
    status int not null comment '默认状态0或者1'
);

其次,在整个DAO中实际上都是以接口为操作标准的,即:客户端依靠DAO实现的接口进行操作,而服务端要将接口进行具体的实现。DAO由以下几个部分组成。

  • DbHelper:专门负责数据库的打开与关闭,或者操作进行的类,在util包中;
  • Entity实例对象:主要由属性、setter、getter方法组成,类中的属性与表中的字段相对应,每一个类的对象都表示表中的每一条记录;
  • DAO:主要定义操作的接口,定义一系列数据库的原子性操作,例如:增加、修改、删除、查询等;Impl : DAO接口的真实实现类,完成具体的数据库操作,但是不负责数据库的打开和关闭;
  • Service:对Dao的接口进行操作,实现定义的方法,这里是一个优化的方法。将Dao接口和其实例,要功能在Service层优化和实现;
  • Test:定义简单的测试类进行相关测试。
    最后以User为例,操作如下,写工具类DbHelper,建立数据库连接,封装增删改查的方法。
// DbHelper类
public class DbHelper {
    private static String URL;
    private static String USER;
    private static String PWD;

    static {//执行一次,执行一次
        Properties properties = new Properties();
        try {
            InputStream inputStream = DbHelper.class.getClassLoader().getResourceAsStream("db.properties");
            properties.load(inputStream);
            URL = properties.getProperty("URL");
            USER = properties.getProperty("USER");
            PWD = properties.getProperty("PWD");// 根据属性名字,获取属性值
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
//        获取连接
        private static Connection getConn() throws SQLException {
            return DriverManager.getConnection(URL,USER,PWD);
        }

//        使用listMAp 进行数据操作,封装一个查询方法
    public static List<Map<String,Object>> Query(String sql,Object... params){
       Connection connection =null;
       PreparedStatement statement = null;
        ResultSet resultSet = null;
        List<Map<String,Object>> list = new ArrayList<>();

        try {
            connection = getConn();
            statement = connection.prepareStatement(sql);
            setParams(statement,params);//调用方法绑定参数
            resultSet = statement.executeQuery();
            ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
            while (resultSet.next()) { //逐行读取,next():移动指针到 下一行,判断是否读到数据,一次读取一行
                Map<String, Object> rowMap = new HashMap<>(); //代表一行
                for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
//                    getColumnLabel():获取列的别名,如果没有就获取列名
                    rowMap.put(resultSetMetaData.getColumnLabel(i), resultSet.getObject(i) == null ? " " : resultSet.getObject(i));
                }
                list.add(rowMap);//填充list
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeAll(connection, statement, resultSet);//调用关闭方法
        }
        return list;
    }


// 关闭方法
    private static void closeAll(Connection connection, PreparedStatement statement, ResultSet resultSet) {
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                System.out.println(e.getMessage());
            }
        }
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                System.out.println(e.getMessage());
            }
        }
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                System.out.println(e.getMessage());
            }
    }
    }

//    更新操作
public static boolean update(String sql, Object... params) {
    Connection connection = null;
    PreparedStatement statement = null;
    boolean result = false;
    try {
        connection = getConn();
        statement = connection.prepareStatement(sql);//预编译
        setParams(statement, params);//调用方法绑定参数
        int n = statement.executeUpdate();
        if (n > 0) {
            result = true;
        }
    } catch (SQLException e) {
        throw new RuntimeException(e);
    } finally {
        closeAll(connection, statement, null);
    }
    return result;
}

    //    设置参数
    private static void setParams(PreparedStatement statement,Object[] params) throws SQLException {
        if (params != null) {
            for (int i = 0; i < params.length; i++) {
                statement.setObject(i + 1, params[i]);
            }
        }

    }
}

//创建db.properties文件,存放连接的数据库以及账号密码,方便修改(更换库表等)
//文件内容如下
#用于文件加载
URL = jdbc:mysql://localhost:3306/my_shop_db?serverTimeZone=asia/shanghai&rewriteBatchedStatements=true
USER = root
PWD = MySQL

按照Dao模式进行如下操作,实现简单的用户登录。代码示例如下:

//entity实例类,user-对应tb_user表,选取关键字段写入
public class User {
    private int userId;
    private String userName;
    private String loginPassword;
    private String realName;
    private int status;

    public User() {
    }

    public User(int userId, String userName, String loginPassword, String realName, int status) {
        this.userId = userId;
        this.userName = userName;
        this.loginPassword = loginPassword;
        this.realName = realName;
        this.status = status;
    }

    public User(String userName, String loginPassword) {
        this.userName = userName;
        this.loginPassword = loginPassword;
    }

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getLoginPassword() {
        return loginPassword;
    }

    public void setLoginPassword(String loginPassword) {
        this.loginPassword = loginPassword;
    }

    public String getRealName() {
        return realName;
    }

    public void setRealName(String realName) {
        this.realName = realName;
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    @Override
    public String
    toString() {
        return "User{" +
                "userId=" + userId +
                ", userName='" + userName + '\'' +
                ", loginPassword='" + loginPassword + '\'' +
                ", realName='" + realName + '\'' +
                ", status=" + status +
                '}';
    }
}

对数据表实例化后,我们要进行dao操作定义接口,Impl实现具体的数据库操作,可以书写一个商品订单的Dao模式,小伙伴们有兴趣可以进行尝试。

//创建UserDao接口
public interface UserDao {
    List<Map<String,Object>> queryAll();
    List<Map<String, Object>> login(User user); //登陆方法
}

//创建实现类UserDaoImpl类,实现接口 重写方法
public class UserDaoImpl implements UserDao {
    @Override
    public List<Map<String, Object>> queryAll() {
        String sql = "select user_name, real_name,status from tb_user order by user_id desc";
        return DbHelper.Query(sql);
    }

    @Override
    public List<Map<String, Object>> login(User user) {
       String sql = "select user_name,login_password from tb_user where user_name=? and login_password = ?";
       return DbHelper.Query(sql,user.getUserName(),user.getLoginPassword());
    }
}

//测试类 测试简单的登录方法
//执行此操作前,你的tb_user中需要有或者你录入一条user_name = laolang login_password = 123456这样的数据在数据库中存储。 
public class Test1 {
    private static UserDao userDao = new UserDaoImpl();

    public static void main(String[] args) {
        String userName = "laolang";
        String loginpassword = "123456";
        User user = new User(userName,loginpassword);
        List<Map<String, Object>> list = userDao.login(user);
        if (list.size() > 0) {
            System.out.println("登录成功");
        } else {
            System.out.println("登录失败");
        }
    }
}

结果:
请添加图片描述
欢迎大家的学习,我们下期再见!

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值