之所有要写这么一个数据库连接方法,就是为了有一个整理一下思路和所需要的东西总是会丢三落四,总是不好找,所以整理好,总不至于在需要的东西总是找不到。
一:JDBC连接数据库:
首先,连接数据库的准备工作:
1.我所用的编写工具为eclipse和Navicat。
2.连接数据库要有所需要的jar包。
自定义连接只需要jar包为驱动包Mysql—connector-java-xxx-bin.jar
在连接中所需要的类有Connection类、ResultSet类、Statement类。
那么究竟怎样才能连接到数据库,并且能在界面化上才做数据呢?要想完成这样的操作,首先我们要得和Navicat获取连接。我们要加载连接数据库的驱动。也就是上面所需要的jar包驱动,把它放在eclipse中新建的工程的lib里面,在build Path一下,使用Class.forName(“com.mysql.jdbc.Driver”)来注册驱动。这就完成了对驱动的注册,之后获取数据库的连接,使用Manager.getConnection(url,username,password),url="jdbc:mysql://127.0.0.1/3306/表名?useUnicoding=true&characterEncoding=utf8",username="连接数据库的名称",password="连接数据库的密码";这样就已经连接上了数据库。
那么接下来我们就对数据库进行操作:
我们知道,对数据库的操作‘无非就是对数据库的增删改查,我们写出相应的增删改查的sql语句。
增:insert into 表名(firstName,secondName,thirdName,fourthName) values(?,?,?,?);
删:delet frome 表的名称 where 条件;
改:updata 表名 set 字段="需要改的值" where ID="条件";
查:select * from 表名;查询所有的值;
写出相应的SQL语句,并且创建出Statement对象;connection.excuteQuery(sql);这样查询相应的数据。connction.executUpdate(sql);来执行相应的增删改;
使用Statement类我们需要注意一个问题,那就是会出现sql注入问题,所以一般我们会使用PrepareStatement类,所以在使用的时候,创建出所使用的PrepareStatement类,使用PrepareStatement类的excuteQuery(sql)来执行查询,excuteUpdata(sql)来更新。当然,我们都是在执行sql语句,但是对于Connection类、Statement类、ResultSet类、PrepareStatement类我们需要把它们关掉,不然会浪费资源。判断是否存在,若是存在,那么就.Close()关掉。
回到我们的标题,自定义连接,但是我们在执行不论是增删改查存在重复的相同的代码,我们是否可以对应的封装一下,封装成相应的工具类。那么以后我们就可以使用对应的工具类了,不用这么麻烦的写重复的代码。而且我们若是在源代码中去改连接数据库的表名、用户名、密码是不是很麻烦呢?有没有什么方法方便去修改这些经常去改变的东西呢?
我们可以使用外部文件去修改:
外部文件:文件名固定为:xxx.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/数据库名?useUnicode=true&characterEncoding=utf8
username=XXX
password=XXX
既然使用了外部文件,那么怎样去读取外部文件?
第一:创建ResourceBundle对象:
static {
//表示加载命名为db.properties的外部文件
ResourceBundle resourcebundle = ResourceBundle.getBundle("db");
driver = resourcebundle.getString("driver");
url = resourcebundle.getString("url");
username = resourcebundle.getString("username");
password = resourcebundle.getString("password");
}
第二:创建类加载器,如JDBCUtils.class.getClassLoader().getResourceAsStream("db.properties");值得注意的是需要注意加载的外部文件是db.properties
static{
try {
InputStream is =
JDBCUtils.class.getClassLoader().getResourceAsStream("db.properties");
Properties prop = new Properties();
prop.load(is);
driver = prop.getProperty(driver);
url = prop.getProperty(url);
username = prop.getProperty(username);
password = prop.getProperty(password);
} catch (IOException e) {
e.printStackTrace();
}
}
使用连接数据库若是我们封装成一个工具类或是jar包,那么以后就不需要如此的麻烦。
JDBCUtils工具包:
package utils;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
import java.util.ResourceBundle;
public class JDBCUtils {
public static String driver;
public static String url;
public static String username;
public static String password;
static {
/*
* ResourceBundle resourcebundle = ResourceBundle.getBundle("db"); driver =
* resourcebundle.getString("driver"); url = resourcebundle.getString("url");
* username = resourcebundle.getString("username"); password =
* resourcebundle.getString("password");
*/
try {
InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("db.properties");
Properties prop = new Properties();
prop.load(is);
driver = prop.getProperty(driver);
url = prop.getProperty(url);
username = prop.getProperty(username);
password = prop.getProperty(password);
} catch (IOException e) {
e.printStackTrace();
}
}
public static Connection getConnection() {
Connection conn = null;
try {
Class.forName(driver);
conn = DriverManager.getConnection(url, username, password);
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
public static void release(Connection conn, PreparedStatement prep, ResultSet rs) {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (prep != null) {
try {
prep.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
这样就能完成连接数据库了,但是连接了数据库,但是有一个问题,我们可以调用JDBCUtils类,但是只有一个连接,若是有几个同时使用这个连接,而Connection就只有一个,那么我们可以创建一个连接池,这样就很好的解决这个问题。
二.怎样去创建一个连接池?
1.创建一个类去实现(implements)DataSource接口,且实现接口的众多方法,我们重写里面的getConnection()方法。但在之前需要创建一个容器,private static LinkedList<Connection> pool = new LinkedList<Connection>();且写出静态代码块:
private static Connection conn = null;
可以创建多个连接,但是不能一味的多,注意考虑性能就OK
static {
for (int i = 0; i < 5; i++) {
conn = JDBCUtils.getConnection();
pool.add(conn );
}
}
这样就可以去重写getConnection()方法了,首先判断是否还有连接,若是没有还可以创建连接,且存在容器中,在使用连接时,可以从容器中去拿取,使用pool.remove()或是pool.removeFirst()等方法,这里使用remove()方法,字面意思是移除,但是注意是从容器中移除,那就是从容器中拿取一个连接,在getConnection()方法中返回拿取的连接,这样就能有多个连接可以拿取。那么若是我们断开一个连接之后,我们得去把它放回连接池,不然连接总有拿取完的时候,在此写出一个方法backConnection(Connection conn),在pool.add(conn);完成放回连接。
public class MyDataSource2 implements DataSource {
private static LinkedList<Connection> pool = new LinkedList<Connection>();
private static Connection conn = null;
static {
for (int i = 0; i < 5; i++) {
conn = JDBCUtils.getConnection();
pool.add(conn);
}
}
public Connection getConnection() throws SQLException {
if (pool.isEmpty()) {
for (int i = 0; i < 5; i++) {
pool.add(conn);
}
}
conn = pool.removeFirst();
return conn;
}
public void backConnection(Connection conn) {
pool.add(conn);
}
在我测试之后,却是是可以的,但是我们返回连接是看到这个backConnection有点不习惯,若是使用原生的close()多好?那把名字修改一下就OK吧,但是我们使用的不是原生的close(),若是能直接调用close()就爽了。既然我们调用的是Connection的close()方法,那么我们就去从写一下Connection在中的close()方法,创建一个类来实现(implements)Connection,创建容器,连接Connection,创建构造方法:
public MyConnnection(Connection conn,LinkedList<Connection> pool) {
this.conn = conn;
this.pool = pool;
}
重写close()方法:
public void close() throws SQLException {
pool.add(conn);
}
这样就可以去测试了,但是去测试的时候,会发现我们在preps = conn.prepareStatement(sql);此处出现空指针异常,为什么呢?因为我们改写了Connection,所以PrepareStatement我们也得重写:
public PreparedStatement prepareStatement(String sql) throws SQLException {
return conn.prepareStatement(sql);
}
既然改写了Connection,那么我们在连接池中也得改:
public class MyDataSource2 implements DataSource {
private static LinkedList<Connection> pool = new LinkedList<Connection>();
private static Connection conn = null;
static {
for (int i = 0; i < 5; i++) {
conn = JDBCUtils.getConnection();
MyConnnection myconn = new MyConnnection(conn, pool);
pool.add(myconn);
}
}
public Connection getConnection() throws SQLException {
if (pool.isEmpty()) {
for (int i = 0; i < 5; i++) {
MyConnnection myconn = new MyConnnection(conn, pool);
pool.add(myconn);
}
}
conn = pool.removeFirst();
return conn;
}
和上面的MyDataSource相比,去掉backConnection()方法,且添加了我们重写的MyConnection类,这样就可以直接调用close()方法了。
测试jar包:junit.XX.jar和匹配jar包:hamcrest-core-XX.jar及其连接数据库的驱动mysql-connector-XX-jar包
链接:https://pan.baidu.com/s/1g6Ygnu7HGPDWsfldToPRhQ
提取码:sp1r