jdbc:java database connectivity java数据库的连接
是执行SQL语句的Java API。
jdbc连接数据库需要根据不同的数据库导入不同的.jar包
oracle需要导入ojdbc6.jar
mysql导入mysql-connector-java-5.1.26-bin.jar
(可以是不同的版本)
一:不使用配置文件方式
1、首先需要加载数据库驱动
oracle:
Class.forName("oracle.jdbc.driver.OracleDriver");
mysql:
Class.forName("com.mysql.jdbc.Driver");
2、通过DriverManager获取数据库连接
oracle连接格式:
Connection conn=DriverManager.getConnection("jdbc:oracle:thin:@<host>:<port>:<sid>","用户名","密码");
host指IP,port指端口,sid代指实例名
例如:
Connection conn=DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe","system","xxx");
mysql连接格式
conn=DriverManager.getConnection("jdbc:mysql://<host:port>/<databasename>","userName","passWord");
host:ip
port:端口(mysql默认端口3306)
databasename:要访问的数据库的名字
例如:
Connection conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/net"+"?useUnicode=true&characterEncoding=utf8","root","");
访问了net数据库,用户名为root,密码为空
其中useUnicode=true&characterEncoding=utf8
设置编码为utf-8
3、当访问完毕后需要关闭连接
以下为源代码
package util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/*
* jdbc工具类
*/
public class DButil1 {
public static Connection getConnection() throws Exception{
Connection conn=null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/net"+"?useUnicode=true&characterEncoding=utf8","root","");
} catch (Exception e) {
e.printStackTrace();
throw e;
}
return conn;
}
public static void close(Connection conn){
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
对该连接方式进行测试
首先建实体类Admin
package Entity;
import java.io.Serializable;
import java.sql.Timestamp;
public class Admin implements Serializable{
private static final long serialVersionUID = 1L;
private Integer adminId;
private String adminCode;
private String name;
private String password;
private String telephone;
private String email;
private Timestamp enrolldate;
public Integer getAdminId() {
return adminId;
}
public void setAdminId(Integer adminId) {
this.adminId = adminId;
}
public String getAdminCode() {
return adminCode;
}
public void setAdminCode(String adminCode) {
this.adminCode = adminCode;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Timestamp getEnrolldate() {
return enrolldate;
}
public void setEnrolldate(Timestamp enrolldate) {
this.enrolldate = enrolldate;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
其次在mysql里面创建表格admin_info
CREATE TABLE admin_info(
id int(11) PRIMARY KEY auto_increment,
admin_code VARCHAR(30) UNIQUE NOT NULL,
password VARCHAR(30) NOT NULL,
name VARCHAR(30) NOT NULL,
telephone VARCHAR(30),
email VARCHAR(50),
enrolldate DATETIME NOT NULL
);
并且增加两条数据
insert into admin_info values(1001,'jeffrey','123456','jeffrey','15966668888','yourzjf@163.com',now());
insert into admin_info values(1002,'admin','111111','lily','13688997766','shiyl@sin.com',now());
接下来创建测试类,完成数据库的连接,并且查询表中的所有数据
package test;
import java.sql.*;
import util.DBUtil1;
public class test1 {
public static void main(String[] args) throws Exception {
Connection conn=null;
try {
conn=DBUtil1.getConnection();
PreparedStatement statement=conn.prepareStatement("select * from admin_info");
ResultSet rst=statement.executeQuery();
while(rst.next()){
System.out.println("id:"+rst.getInt("id")+" "+"name:"+rst.getString("name"));
}
} catch (Exception e) {
e.printStackTrace();
throw e;
}finally{
DBUtil1.close(conn);
}
}
}
查询结果如下
二、使用配置文件方式
所谓使用配置文件即将数据库的驱动、链接、用户名和密码都放在配置文件中,这样减少代码耦合度
这样的配置可以使代码复用,减少对代码的修改
1、使用Properties类读取properties文件
/*
* 使用properties去读取配置文件
*/
Properties prop=new Properties();
InputStream is=DBUtil.class.getClassLoader().getResourceAsStream("util/config.properties");
/*
* 当通过properties读取文件后,这个流依然保持打开状态
* 应该将流关闭
*/
prop.load(is);
is.close();
properties文件的读取类似于map
文件中等号左边相当于key,右边相当于value
2、获取properties文件中的配置
driver=prop.getProperty("driver").trim();
url=prop.getProperty("url").trim();
user=prop.getProperty("user").trim();
pwd=prop.getProperty("pwd").trim();
3、连接数据库
//注册驱动
Class.forName(driver);
//通过DriverManager建立连接
Connection conn= DriverManager.getConnection(url,user,pwd);
4、关闭连接
以下为源码
package util;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
/*
* 使用配置文件来配置JDBC连接数据库
* 该类用来管理数据库的连接
*/
public class DBUtil2 {
//连接数据库的路径
private static String url;
//连接数据库的用户名
private static String user;
//连接数据库的密码
private static String pwd;
private static String driver;
//静态块
static{
try{
//读取配置文件
Properties prop=new Properties();
InputStream is=DBUtil.class.getClassLoader().getResourceAsStream("util/config.properties");
prop.load(is);
is.close();
driver=prop.getProperty("driver").trim();
url=prop.getProperty("url").trim();
user=prop.getProperty("user").trim();
pwd=prop.getProperty("pwd").trim();
}catch(Exception e)
{
e.printStackTrace();
}
}
/*
* 获取一个连接
*/
public static Connection getConnection() throws Exception {
try{
/*
* 通过DriverManager创建一个数据库的连接并返回
*/
//注册驱动
Class.forName(driver);
Connection conn= DriverManager.getConnection(url,user,pwd);
return conn;
}catch(Exception e){
//通知调用者,创建连接出错
e.printStackTrace();
throw e;
}
}
public static void closeConnection(Connection conn){
try{
if(conn!=null){
conn.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
创建测试类完成连接测试,并且向admin_info表中增加一条数据
package test;
import java.sql.*;
import util.DBUtil2;
import Entity.Admin;
public class test2 {
public void save(Admin admin) throws Exception {
Connection conn=null;
try {
conn=DBUtil2.getConnection();
PreparedStatement statement=conn.prepareStatement("insert into admin_info(id,admin_code,password,name,telephone,email,enrolldate)"+
"values(?,?,?,?,?,?,?)");
statement.setInt(1, admin.getAdminId());
statement.setString(2, admin.getAdminCode());
statement.setString(3, admin.getPassword());
statement.setString(4, admin.getName());
statement.setString(5, admin.getTelephone());
statement.setString(6, admin.getEmail());
statement.setTimestamp(7, admin.getEnrolldate());
statement.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
throw e;
}finally{
DBUtil2.closeConnection(conn);
}
}
public static void main(String[] args) throws Exception{
Admin admin=new Admin();
admin.setAdminId(1003);
admin.setAdminCode("test");
admin.setPassword("111111");
admin.setName("testadmin");
admin.setEmail("test@163.com");
admin.setTelephone("135135");
admin.setEnrolldate(new Timestamp(System.currentTimeMillis()));
test2 t=new test2();
t.save(admin);
}
}
测试结果如下
三、使用连接池管理连接
采用dbcp连接池来管理数据库的连接,同时采用ThreadLocal来管理不同线程的连接
dbcp:database connection pool是apache上的一个java连接池项目
单独使用dbcp需要.jar包
commons-dbcp-1.4.jar
commons-pool.jar
commons-collections.jar
使用dbcp的好处(摘自百度百科)
建立数据库连接是一个非常消耗资源的行为,如当有一个数据访问操作时,需要创建一个连接,当这次服务访问完成后,这个连接虽然已关闭但是还没有被销毁,这样会耗内存。当下次再有需要数据访问的操作时程序又会创建连接,如此以往既消耗时间,又要消耗资源。所以最后就使用了一种节省资源的方式,即数据库连接池的方式。
DBCP 的工作原理是,程序首先会初始化相应的数据库连接池,以供程序访问,当某个操作需要访问数据库时,程序会首先在连接池中取得空闲连接,如没有空闲连接在创建,用完之后归还连接池,这样达到了连接的重利用,不用频繁的创建连接和销毁,从而优化程序。
dbcp参数配置(配置在properties文件中)
ThreadLocal主要用于解决多线程的问题,保证多线程之间资源隔离,不相互干扰,保证线程安全。
以下是源码
package util;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
import org.apache.commons.dbcp.BasicDataSource;
/*
* 使用连接池技术管理数据库连接
*/
public class DBUtil3 {
//数据库连接池
private static BasicDataSource ds;
//为不同线程管理连接
private static ThreadLocal<Connection> tl;
static{
try{
Properties prop=new Properties();
InputStream is=DBUtil.class.getClassLoader().getResourceAsStream("util/config.properties");
prop.load(is);
is.close();
//初始化连接池
ds=new BasicDataSource();
//设置驱动(Class.forName())
ds.setDriverClassName(prop.getProperty("driver"));
//设置url
ds.setUrl(prop.getProperty("url"));
//设置用户名
ds.setUsername(prop.getProperty("user"));
//设置密码
ds.setPassword(prop.getProperty("pwd"));
//设置最大链接数量
//先将prop中读出的字符串转为整数
ds.setMaxActive(Integer.parseInt(prop.getProperty("maxactive")));
//设置初始大小,开始就创建5个连接
ds.setInitialSize(Integer.parseInt(prop.getProperty("initsize")));
//设置最大等待时间
ds.setMaxWait(Integer.parseInt(prop.getProperty("maxwait")));
//设置最小空闲数
ds.setMinIdle(Integer.parseInt(prop.getProperty("minidle")));
//设置最大空闲数
ds.setMaxIdle(Integer.parseInt(prop.getProperty("maxidle")));
//初始化本地线程
tl=new ThreadLocal<Connection>();
}catch(Exception e){
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException {
/*
* 通过连接池获取空闲连接
*/
Connection conn=ds.getConnection();
tl.set(conn);
return conn;
}
/*
* 关闭数据库连接
*/
public static void closeConnection() {
try{
Connection conn=tl.get();
if(conn!=null){
//恢复连接为自动提交事务
conn.setAutoCommit(true);
/*
* 通过连接池获取的Connection的close()方法
* 实际并没有将连接关闭而是将连接还给连接池
*/
conn.close();
tl.remove();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
创建测试类,并且修改表中的一条数据
package test;
import util.DBUtil3;
import java.sql.*;
import Entity.Admin;
public class test3 {
public void update(Admin admin) throws SQLException{
Connection conn=null;
try {
conn=DBUtil3.getConnection();
System.out.println(conn);
PreparedStatement statement=conn.prepareStatement("update admin_info set admin_code=?,password=?,name=?,telephone=?,email=? where id=?");
statement.setString(1, admin.getAdminCode());
System.out.println(admin.getAdminCode());
statement.setString(2, admin.getPassword());
statement.setString(3, admin.getName());
statement.setString(4, admin.getTelephone());
statement.setString(5, admin.getEmail());
statement.setInt(6, admin.getAdminId());
System.out.println(admin.getAdminId());
statement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
throw e;
}finally{
DBUtil3.closeConnection();
}
}
public static void main(String[] args) throws SQLException{
Admin admin=new Admin();
admin.setAdminCode("update");
admin.setPassword("333333");
admin.setName("testupdate");
admin.setTelephone("123456");
admin.setEmail("update@163.com");
admin.setAdminId(1003);
test3 t3=new test3();
t3.update(admin);
}
}
测试结果如下