用戶登錄註冊【JDBC版】

前言

在講解Web開發模式的時候,曾經寫過XML版的用戶登錄註冊案例!如今在原有的項目上,使用數據庫版來完成用戶的登錄註冊!若是不瞭解的朋友,能夠看看我Web開發模式的博文!

原本使用的是XML文件做爲小型數據庫,如今使用Mysql數據庫,代碼究竟要改多少呢?咱們拭目以待!html

使用C3P0數據庫鏈接池

導入C3P0的開發包和導入配置文件

開發包導入的是這個:c3p0-0.9.2-pre1和mchange-commons-0.2.jar.java

C3P0不只性能好,並且配置文件可使用XML文檔來配置!mysql

相似的配置文件能夠在官方文檔上找獲得sql

咱們來改造一下:數據庫

<?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>

寫獲取鏈接的工具類

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("數據庫初始化失敗了!");
            }
        }
    }

設計數據庫表

很是簡單,根據實體表來設計就行了!編程

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實現

public class UserImplDataBase implements UserDao {
    
    
        @Override
        public User find(String username, String password) {
            
            return null;
        }
    
        @Override
        public void register(User user) {
    
            
        }
    }

下面咱們就直接使用DBUtils框架了設計模式

  • 導入DBUtils的開發包

  • 具體的代碼以下
@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實現,也就是如下的代碼:微信

UserDao userDao = new UserImplXML();

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

這樣作有點不夠靈活,也就有點不夠專業!下面咱們來講一下爲何須要DaoFactory?oracle

爲何須要DaoFactory?

參考博文:http://blog.sina.com.cn/s/blog_4ca34d0501008tpc.html框架

摘抄重點:

優勢:

  • 透明化:商業對象能夠在徹底不知道數據源如何具體實現的狀況下來使用數據源. 訪問數據源是透明的,由於實現細節已經被隱藏進了DAO.
  • 遷移簡單化:DAO 層的出現,使得應用程序向不一樣的數據庫實現進行遷移變的容易.商業對象能夠對底層數據實現一無所知.這樣,遷移只涉及到了對DAO層的修改. 另外,若是使用工廠策略,則使爲每一種底層數據實現提供一個具體的工廠實現成爲可能.在這種狀況下,遷移到一種不一樣的數據實現,其實就至關於爲這個應用程序再提供一個新的工廠實現.
  • 減小在商業對象中的編程難度:因爲DAO管理着全部的數據訪問細節,於是大大簡化了在商業對象和其餘使用DAO的數據客戶端裏的代碼.全部的實現細節相關的代碼好比(SQL 語句)都包含在DAO而不在商業對象中. 這樣使得代碼變的更加健壯並且大大提升了開發效率.
  • 將全部的數據訪問都單獨集中到一層中去: 由於全部的數據訪問操做如今都已經被DAO所代理,因此這個單獨的數據訪問層能夠被看做能夠是將數據訪問實現和其他應用程序相互隔離的一層. 這樣的集中,使得應用程序能夠更加容易的來維護和管理.

缺點:

  • 增長了多餘的層:因爲DAO在數據客戶端和數據源以外多建立了一層對象,於是,須要對他進行設計和實現,來均衡這個設計模式的利弊. 可是,通常來講,採用此設計模式仍是利大於弊的.
  • 須要對類的相互繼承關係進行設計:當使用工廠策略的時候,具體工廠類的繼承關係和由這些工廠類生成的產品須要進行設計和實現. 咱們須要仔細考慮這些多付出的工做是否真的能夠產生出來更高的靈活性. 使用這個策略會使設計變的更加複雜,然而,你能夠先從工廠方法模式開始來實現這個策略,而後在須要的狀況下再轉向抽象工廠

設計DaoFactory

首先,咱們把DaoFactory設計成單例的【工廠有一個就夠了!】

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目錄下加入配置文件
  • 注意:不要加""字符串的符號!!!!!我就是這裏搞了好久!!!!
#class須要的是完整的對象名稱(包括包)
#userClass=zhongfucheng.dao.impl.UserImplDataBase
userClass=zhongfucheng.dao.impl.UserImplXML
  • 讀取配置文件的信息,建立相對應的UserDao對象,直接在構造函數作就好了(其實就是個初始化的操做罷了)
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對象

UserDao userDao = DaoFactory.newInstance().createUserDao();

測試

若是咱們的mysql驅動版本過低,就出現如下的異常!咱們只須要下載新的mysql的jar包,導入項目便可!

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. 因而咱們有了工廠,工廠的目的就是解耦,咱們經過配置文件來建立具體的對象。

若是文章有錯的地方歡迎指正,你們互相交流。習慣在微信看技術文章的同窗,能夠 關注微信公衆號:Java3y
相關文章
相關標籤/搜索