前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【JavaWeb基础】JDBC用户登录注册(修订版)

【JavaWeb基础】JDBC用户登录注册(修订版)

作者头像
Java3y
发布2019-05-08 11:27:34
9880
发布2019-05-08 11:27:34
举报
文章被收录于专栏:Java3y

前言

只有光头才能变强。 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y

在讲解Web开发模式的时候,曾经写过XML版的用户登陆注册案例!现在在原有的项目上,使用数据库版来完成用户的登陆注册!如果不了解的朋友,可以看看我Web开发模式的博文!

本来使用的是XML文件作为小型数据库,现在使用Mysql数据库,代码究竟要改多少呢?我们拭目以待!

使用C3P0数据库连接池

导入C3P0的开发包和导入配置文件

开发包导入的是这个:c3p0-0.9.2-pre1和mchange-commons-0.2.jar.

C3P0不仅性能好,而且配置文件可以使用XML文档来配置!

类似的配置文件可以在官方文档上找得到

我们来改造一下:

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <default-config>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/zhongfucheng</property>
        <property name="user">root</property>
        <property name="password">root</property>

        <property name="acquireIncrement">5</property>
        <property name="initialPoolSize">10</property>
        <property name="minPoolSize">5</property>
        <property name="maxPoolSize">20</property>
    </default-config>

    <named-config name="mysql">
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/zhongfucheng</property>
        <property name="user">root</property>
        <property name="password">root</property>

        <property name="acquireIncrement">5</property>
        <property name="initialPoolSize">10</property>
        <property name="minPoolSize">5</property>
        <property name="maxPoolSize">20</property>
    </named-config>


    <named-config name="oracle">
        <property name="driverClass">oracle.jdbc.driver.OracleDriver</property>
        <property name="jdbcUrl">jdbc:oracle:thin:@//localhost:1521/事例名...</property>
        <property name="user">用户名</property>
        <property name="password">密码</property>

        <property name="acquireIncrement">5</property>
        <property name="initialPoolSize">10</property>
        <property name="minPoolSize">5</property>
        <property name="maxPoolSize">20</property>
    </named-config>
</c3p0-config>

写获取连接的工具类

代码语言:javascript
复制
public class DBUtils {

  private static ComboPooledDataSource comboPooledDataSource = null;

  static {

    //它会自动寻找配置文件,节点为mysql的数据库【如果没有指定,就使用默认的!】
    comboPooledDataSource = new ComboPooledDataSource("mysql");
  }


  public static DataSource getDataSource() {
    return comboPooledDataSource ;
  }


  public static Connection getConnection() {
    try {
      return comboPooledDataSource.getConnection();
    } catch (SQLException e) {
      e.printStackTrace();
      throw new RuntimeException("数据库初始化失败了!");
    }
  }
}

设计数据库表

非常简单,根据实体表来设计就好了!

代码语言:javascript
复制
    CREATE TABLE user (
    id       VARCHAR(20) PRIMARY KEY,
    username VARCHAR(20) UNIQUE NOT NULL,
    password VARCHAR(20)        NOT NULL,
    email    VARCHAR(20),
    birthday DATE

  );

写一个操作数据库的Dao实现

代码语言:javascript
复制
public class UserImplDataBase implements UserDao {


  @Override
  public User find(String username, String password) {

    return null;
  }

  @Override
  public void register(User user) {


  }
}

下面我们就直接使用DBUtils框架了

  • 导入DBUtils的开发包
  • 具体的代码如下
代码语言:javascript
复制
@Override
public User find(String username, String password) {

  QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());

  String sql = "SELECT * FROM user WHERE username=? AND password=?";

  try {
    User user = (User) queryRunner.query(sql, new BeanHandler(User.class), new Object[]{username, password});

    return user == null ? null : user;
  } catch (SQLException e) {
    e.printStackTrace();
    throw new RuntimeException("登陆失败了!");
  }
}

@Override
public void register(User user) {

  QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());

  String sql = "INSERT INTO user (id, username, password, email,birthday) VALUES (?,?,?,?,?);";

  String id = user.getId();
  String username = user.getUsername();
  String password = user.getPassword();
  String email = user.getEmail();

  Date date = user.getBirthday();


  try {
    queryRunner.update(sql, new Object[]{id, username, password, email,date});

  } catch (SQLException e) {
    e.printStackTrace();
    throw new RuntimeException("注册失败了");
  }
}
}

开发DaoFactory

我们的Dao实现已经有了XML版和JDBC版的,BusinessService调用Dao层方法的时候还是要new出具体的Dao实现,也就是以下的代码:

代码语言:javascript
复制
UserDao userDao = new UserImplXML();

//或者
UserDao userDao= new UserImplDataBase();

这样做有点不够灵活,也就有点不够专业!下面我们来说一下为什么需要DaoFactory?

为什么需要DaoFactory?

参考博文:http://blog.sina.com.cn/s/blog_4ca34d0501008tpc.html

摘抄重点:

优点:

  • 透明化:商业对象可以在完全不知道数据源如何具体实现的情况下来使用数据源. 访问数据源是透明的,因为实现细节已经被隐藏进了DAO.
  • 迁移简单化:DAO 层的出现,使得应用程序向不同的数据库实现进行迁移变的容易.商业对象可以对底层数据实现一无所知.这样,迁移只涉及到了对DAO层的修改. 另外,如果使用工厂策略,则使为每一种底层数据实现提供一个具体的工厂实现成为可能.在这种情况下,迁移到一种不同的数据实现,其实就相当于为这个应用程序再提供一个新的工厂实现.
  • 减少在商业对象中的编程难度:由于DAO管理着所有的数据访问细节,因而大大简化了在商业对象和其他使用DAO的数据客户端里的代码.所有的实现细节相关的代码比如(SQL 语句)都包含在DAO而不在商业对象中. 这样使得代码变的更加健壮而且大大提高了开发效率.
  • 将所有的数据访问都单独集中到一层中去: 因为所有的数据访问操作现在都已经被DAO所代理,所以这个单独的数据访问层可以被看作可以是将数据访问实现和其余应用程序相互隔离的一层. 这样的集中,使得应用程序可以更加容易的来维护和管理.

缺点:

  • 增加了多余的层:由于DAO在数据客户端和数据源之外多创建了一层对象,因而,需要对他进行设计和实现,来均衡这个设计模式的利弊. 但是,一般来说,采用此设计模式还是利大于弊的.
  • 需要对类的相互继承关系进行设计:当使用工厂策略的时候,具体工厂类的继承关系和由这些工厂类生成的产品需要进行设计和实现. 我们需要仔细考虑这些多付出的工作是否真的可以产生出来更高的灵活性. 使用这个策略会使设计变的更加复杂,然而,你可以先从工厂方法模式开始来实现这个策略,然后在需要的情况下再转向抽象工厂

设计DaoFactory

首先,我们把DaoFactory设计成单例的【工厂有一个就够了!】

代码语言:javascript
复制
public class DaoFactory {

  private DaoFactory() {

  }

  private static final DaoFactory DAO_FACTORY = new DaoFactory();

  //暴露公开方法获取工厂对象
  public static DaoFactory newInstance() {
    return DAO_FACTORY;
  }

}

目前我们操作的是User,所以工厂造UserDao对象,而UserDao对象是JDBC版呢,还是XML版呢,我们通过配置文件来定(这样就更灵活了)!

  • 在src目录下加入配置文件
  • 注意:不要加""字符串的符号!!!!!我就是这里搞了很久!!!!
代码语言:javascript
复制
#class需要的是完整的对象名称(包括包)
#userClass=zhongfucheng.dao.impl.UserImplDataBase
userClass=zhongfucheng.dao.impl.UserImplXML
  • 读取配置文件的信息,创建相对应的UserDao对象,直接在构造函数做就行了(其实就是个初始化的操作罢了)
代码语言:javascript
复制
private static UserDao userDao = null;

private DaoFactory() {


  try {

    //读取配置文件的信息
    InputStream inputStream = DaoFactory.class.getClassLoader().getResourceAsStream("UserDao.properties");
    Properties properties = new Properties();
    properties.load(inputStream);
    String userClass = properties.getProperty("userClass");

    //利用反射机制创建相对应的对象
    userDao = (UserDao) Class.forName(userClass).newInstance();

  } catch (IOException e) {
    e.printStackTrace();
    throw new RuntimeException("读取文件失败了!");
  } catch (IllegalAccessException e) {
    e.printStackTrace();
    throw new RuntimeException("反射失败了!");
  } catch (InstantiationException e) {
    e.printStackTrace();
    throw new RuntimeException("反射失败了!");
  } catch (ClassNotFoundException e) {
    e.printStackTrace();
    throw new RuntimeException("反射失败了!");
  }

}

public static UserDao createUserDao() {
  return userDao;
}

在BusinessService层中用DaoFactory获取UserDao对象

代码语言:javascript
复制
UserDao userDao = DaoFactory.newInstance().createUserDao();

测试

如果我们的mysql驱动版本太低,就出现以下的异常!我们只需要下载新的mysql的jar包,导入项目即可!

代码语言:javascript
复制
java.sql.SQLException: Feature not implemented Query:insert into guestbook (id,name,email,url,title,content,time) value(?,?,?,?,?,?,?) Parameters: [1, qwq,wqwq,qwqw,qw,qw, 2010-09-13]

JDBC版的成功的效果如下


XML版的成功效果如下:

这里写图片描述


总结

  1. 由于我们的Service层可能有多种实现【jdbc,xml】,如果我们直接是使用new具体的Service,那么这耦合性就有点高了
  2. 于是我们有了工厂,工厂的目的就是解耦,我们通过配置文件来创建具体的对象
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-04-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java3y 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用C3P0数据库连接池
    • 导入C3P0的开发包和导入配置文件
      • 写获取连接的工具类
      • 设计数据库表
      • 写一个操作数据库的Dao实现
      • 开发DaoFactory
        • 为什么需要DaoFactory?
          • 设计DaoFactory
          • 在BusinessService层中用DaoFactory获取UserDao对象
          • 测试
          • 总结
          相关产品与服务
          数据库
          云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档