使用 Properties
在上面的文章中,我已經(jīng)介紹了在 Java 中如何使用 MySQL, 下面就來看看怎么使用 Propreties 對(duì)原本的程序進(jìn)行優(yōu)化。
String url = "jdbc:mysql://localhost:3306/user_db?" + "user=root&password=hwaphon&&useSSL=true";
這個(gè)時(shí)候問題出現(xiàn)了,如果我們的數(shù)據(jù)庫更改名稱了,訪問密碼改了,那我們?cè)趺崔k?我們直接去修改源代碼嗎?當(dāng)然這樣是可以的,但不推薦這么做,因?yàn)檫@樣違背了開閉原則。所以我們最好將其放到配置文件中,這樣我們只需要對(duì)配置文件進(jìn)行修改即可,不必再去修改我們的源代碼。
首先我們新建一個(gè)名為 dbconfig.properties文件,在其中寫入下面這兩行代碼。
mysql_driver=com.mysql.jdbc.Driver
mysql_url=jdbc:mysql://localhost:3306/user_db?user=root&password=hwaphon&&useSSL=true
下面我們新建一個(gè)工廠類,用于讀取配置文件中的內(nèi)容,并且實(shí)現(xiàn)返回 Connection 的方法。
public class ConnectionFactory {
private static String mysql_driver;
private static String mysql_url;
private static ConnectionFactory factory = new ConnectionFactory();
static {
Properties properties = new Properties();
try {
InputStream inputStream = ConnectionFactory.class
.getClassLoader()
.getResourceAsStream("dbconfig.properties");
properties.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
mysql_driver = properties.getProperty("mysql_driver");
mysql_url = properties.getProperty("mysql_url");
}
private ConnectionFactory() {
}
public static ConnectionFactory getInstance() {
return factory;
}
public Connection makeConnection() {
Connection connection = null;
try {
Class.forName(mysql_driver);
connection = DriverManager.getConnection(mysql_url);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
}
1.首先我們利用 static 定義了一個(gè)塊,這個(gè)塊會(huì)在 JVM 首次加載類的時(shí)候被調(diào)用,在這里我們將之前寫在配置文件中的內(nèi)容讀取出來,并且其保存在我們自己聲明的變量中,用于在 makeConnection() 中獲取到一個(gè) Connection。
2.注意在這里我們使用了單例模式用于對(duì)工廠類實(shí)例的創(chuàng)建進(jìn)行限制。
下面我們就去測試一下這么寫是否能夠?qū)?shù)據(jù)庫進(jìn)行正常操作。
public class Client {
public static void main(String[] args) {
Connection connection = ConnectionFactory.getInstance().makeConnection();
try {
Statement statement = connection.createStatement();
String sql = "INSERT INTO table_user(username,password,email) " +
"VALUES('testPerson','testPass','testEm@163.com')";
statement.executeUpdate(sql);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
運(yùn)行之后,進(jìn)入 MySQL Workbench 查詢一下數(shù)據(jù),發(fā)現(xiàn)以上代碼確實(shí)是可以有效運(yùn)行的。修改之后,我們可以看到,在主方法中代碼量大大減少了。重要的是我們這么做讓我們的程序遵守了開閉原則。
DAO && DTO
什么是 DTO 呢 ? 我所理解的就是,將數(shù)據(jù)庫中的表抽象成 Java 中的一個(gè)對(duì)象,將表中的字段抽象成對(duì)象的屬性,并為其設(shè)置 Setter 和 Getter。那么為什么將表轉(zhuǎn)化成一個(gè)對(duì)象呢?Java 是一種面向?qū)ο蟮恼Z言,一旦我們將表抽象成對(duì)象,那么我們對(duì)其的操作也就變得簡單起來。
什么是 DAO 呢?就是對(duì)非對(duì)象數(shù)據(jù)進(jìn)行對(duì)象化操作。下面我將我創(chuàng)建表的語句粘貼出來,然后進(jìn)行講解如何使用 DAO 和 DTO 概念對(duì)數(shù)據(jù)庫操作進(jìn)行優(yōu)化。
CREATE TABLE table_user (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
username VARCHAR(20) NOT NULL DEFAULT '',
password VARCHAR(16) NOT NULL DEFAULT '',
email VARCHAR(20) DEFAULT '',
PRIMARY KEY (id)
) ENGINE=INNODB DEFAULT CHARSET=UTF8;
下面我們將這個(gè)表抽象成一個(gè)對(duì)象。
public class User {
private String username;
private String password;
private String email;
protected Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", email='" + email + '\'' +
", id=" + id +
'}';
}
}
為了代碼的可拓展性,我們先定義一個(gè)接口。
public interface UserDao {
public void save(Connection connection, User user) throws SQLException;
public void update(Connection connection, Long id, User user) throws SQLException;
public void delete(Connection connection, User user) throws SQLException;
}
然后定義一個(gè)實(shí)現(xiàn)類,完成對(duì)數(shù)據(jù)庫的操作。
public class ConcreteUserDao implements UserDao {
@Override
public void save(Connection connection, User user) throws SQLException {
PreparedStatement statement = connection
.prepareCall("INSERT INTO table_user(username,password,email) VALUES(?,?,?)");
statement.setString(1, user.getUsername());
statement.setString(2, user.getPassword());
statement.setString(3, user.getEmail());
statement.execute();
}
@Override
public void update(Connection connection, Long id, User user) throws SQLException {
}
@Override
public void delete(Connection connection, User user) throws SQLException {
}
}
由于各個(gè)方法的代碼都是類似的,所以在這里我只實(shí)現(xiàn)了一個(gè) save() 方法。注意 VALUES 后面括號(hào)中的 ? 是一個(gè)占位符,其值我們是在下面進(jìn)行手動(dòng)指定的。
利用這種方式,我們對(duì)數(shù)據(jù)庫的操作顯得十分簡單,邏輯十分清晰。好了,本篇文章就介紹到這里,有疑問可在下方進(jìn)行留言。