MySQL---資料庫從入門走向大神系列(十五)-Apache的DBUtils框架使用
DBUtils簡介:
commons-dbutils 是 Apache 組織提供的一個開源 JDBC工具類庫,它是對JDBC的簡單封裝,學習成本極低,並且使用dbutils能極大簡化jdbc編碼的工作量,同時也不會影響程式的效能。因此dbutils成為很多不喜歡hibernate的公司的首選(嗯~商業競爭…..)。
commons-dbutilsAPI介紹:
org.apache.commons.dbutils.QueryRunner
org.apache.commons.dbutils.ResultSetHandler
工具類
org.apache.commons.dbutils .DbUtils
QueryRunner類講解
該類簡單化了SQL查詢,它與ResultSetHandler組合在一起使用可以完成大部分的資料庫操作,能夠大大減少編碼量。
QueryRunner類提供了兩個構造方法:
1、預設的構造方法
2、需要一個 javax.sql.DataSource 來作引數的構造方法。
QueryRunner類的主要方法
public Object query(Connection conn, String sql, Object[] params, ResultSetHandler rsh) throws SQLException:
執行一個查詢操作,在這個查詢中,物件陣列中的每個元素值被用來作為查詢語句的置換引數。該方法會自行處理 PreparedStatement 和 ResultSet 的建立和關閉。
public Object query(String sql, Object[] params, ResultSetHandler rsh) throws SQLException:
幾乎與第一種方法一樣;唯一的不同在於它不將資料庫連線提供給方法,並且它是從提供給構造方法的資料來源(DataSource) 或使用的setDataSource 方法中重新獲得 Connection。
public Object query(Connection conn, String sql, ResultSetHandler rsh) throws SQLException : 執行一個不需要置換引數的查詢操作。
public int update(Connection conn, String sql, Object[] params) throws SQLException
用來執行一個更新(插入、更新或刪除)操作。
public int update(Connection conn, String sql) throws SQLException:
用來執行一個不需要置換引數的更新操作。
JAR包準備:
程式碼演示:
首先準備資料庫:
create database hncu character set utf8;
use hncu;
create table person(
id varchar(30) primary key,
name varchar(30),
address varchar(30),
age int
);
insert into person(id,name,address,age) values('P001','張三','湖南長沙',20);
insert into person(id,name,address,age) values('P002','李四','中國北京',25);
insert into person(id,name,address,age) values('P003','李白','武漢',56);
insert into person(id,name,address,age) values('P004','張三丰','武當三',78);
insert into person(id,name,address,age) values('P005','Tom','美國紐約',34);
insert into person(id,name,address,age) values('P006','Jack','美國舊金山',28);
不使用dbUtils工具的資料庫查詢程式碼實現
@Test//原來不使用dbUtils工具的資料庫查詢程式碼實現
public void jdbcQuery() throws SQLException{
List<Person> persons = new ArrayList<Person>();
Connection con = C3p0Pool.getConnection();
String sql = "select * from person";
Statement st = con.createStatement();
ResultSet rs = st.executeQuery(sql);
while(rs.next()){
Person p = new Person();
p.setId(rs.getString("id"));
p.setName(rs.getString("name"));
p.setAddr(rs.getString("address"));
p.setAge(Integer.parseInt(rs.getString("age")));
persons.add(p);
}
for(Person p:persons){
System.out.println(p);
}
}
結果:
使用dbUtils工具的資料庫查詢程式碼實現
BeanListHandler返回型別為List<>
@Test
public void dbUtilsQuery() throws SQLException{
QueryRunner run = new QueryRunner(C3p0Pool.getDataSource());
String sql = "select * from person";
List<Person> persons = run.query(sql,new BeanListHandler<Person>(Person.class));
for(Person p:persons){
System.out.println(p);
}
}
資料庫的欄位名為:address、
public String addr;
//這裡的名字如果和資料庫的欄位名不同。會出現讀取值為null的情況
//如果要解決,把get和set函式的set/get***寫成和資料的欄位名一樣就可以了。setAddress()/getAddress()
//或者在查詢的時候取別名如:select id,name,address as addr ,age from person
//但是最好還是和資料庫的欄位名一樣比較好
MapListHandler返回型別為List<Map<String,Object>>
而且注意,這個與前面的依賴person類的不同,這個不依賴person類,
也就是person的成員變數名可以和資料庫的欄位名取不同。
@Test
public void dbUtilsQuery2() throws SQLException{
QueryRunner run = new QueryRunner(C3p0Pool.getDataSource());
String sql = "select * from person ";
List<Map<String, Object>> persons = run.query(sql,new MapListHandler());
for(Map<String, Object> p:persons){
System.out.println(p);
}
}
DbUtils工具的使用演示: 增刪改–用update()
只演示 增,刪和改類似:
@Test
public void save() throws SQLException{
QueryRunner run = new QueryRunner(C3p0Pool.getDataSource());
//statement方式
//run.update("insert into person(id,name,address,age) values('P007','Rose','湖南長沙',22) ");
//prepareStatement方式
run.update("insert into person(id,name,address,age) values(?,?,?,?)", "P008","Marry","中國西安",34);
}
如果使用prepareStatement方式,注意引數個數或型別 與 “?”號必須匹配,否則會出異常 。
為 增新增事務處理:
@Test
public void saveTx() throws SQLException{
QueryRunner run = new QueryRunner(C3p0Pool.getDataSource());
Connection con = C3p0Pool.getConnection();
try {
con.setAutoCommit(false);
run.update(con, "insert into person(id,name,address,age) values(?,?,?,?)","P011","Tom","浙江杭州",24);
run.update(con, "insert into person(id,name,address,age) values(?,?,?,?)","P012","Gimo","江蘇蘇州",45);
con.commit();
} catch (Exception e) {
if(con!=null){
con.rollback();
System.out.println("事務回滾了...");
}
}finally{
if(con!=null){
con.setAutoCommit(true);
con.close();
}
}
}
注意,實現事務功能時,要傳入con物件,且多條語句共處一個事務時,要傳入同一個con物件。但如果不實現事務功能,可以不傳入con物件。
查詢的結果集封裝
封裝成BeanList
@Test
public void query2() throws SQLException{
QueryRunner run = new QueryRunner(C3p0Pool.getDataSource());
//封裝成BeanList: 如果值物件中的屬性名和表中的欄位名不一致,那麼該屬性的值返回的是null
//解決方法是採用別名,或者修改set**/get**名
List<Person> persons = run.query("select id,name,address addr,age from person ",new BeanListHandler<Person>(Person.class) );//用屬性名 當 欄位別名
for(Person p:persons){
System.out.println(p);
}
}
封裝成MapList
@Test
public void query3() throws SQLException{
QueryRunner run = new QueryRunner(C3p0Pool.getDataSource());
String sql = "select * from person";
List<Map<String, Object>> persons = run.query(sql, new MapListHandler());
for(Map<String, Object> p:persons){
System.out.println(p);
}
}
封裝成BeanList—查詢帶引數
@Test
public void query4() throws SQLException{
QueryRunner run = new QueryRunner(C3p0Pool.getDataSource());
String sql = "select id,name,address,age from person where name like ? and age > ?";
List<Person> persons = run.query(sql, new BeanListHandler<Person>(Person.class),"%o%",34);
for(Person p:persons){
System.out.println(p);
}
}
演示批處理功能
@Test
public void batch() throws SQLException{
QueryRunner run = new QueryRunner(C3p0Pool.getDataSource());
for(int i=1;i<=100;i++){
String sql = "insert into person values(?,?,?,?)";
String str = "000"+i;
str=str.substring(str.length()-3, str.length());
String id1="A"+str;
String id2="B"+str;
String params[][]={{id1,"Alice"+i,"中國",i+""},{id2,"Bob"+i,"湖南",i+""}};
run.batch(sql, params);
}
}
演示擴充套件包commons-dbutilss-ext.jar的功能
封裝成BeanList—直接通過JavaBean的位元組碼查詢所有
注意,下面的用法要生效,必須給值物件添加註解@Table(value = “person”)
@Test
public void query5(){
ExtQueryRunner run = new ExtQueryRunner(C3p0Pool.getDataSource());
List<Person> persons = run.query(Person.class);//不用sql語句,,直接查詢Bean-List
for(Person p:persons){
System.out.println(p);
}
}
封裝成JavaBean—直接通過JavaBean物件儲存進資料庫
@Test
public void save3(){
ExtQueryRunner run = new ExtQueryRunner(C3p0Pool.getDataSource());
Person p = new Person();
p.setId("A000");
p.setName("梨子");
p.setAddress("中國");
p.setAge(20);
run.save(p);//不用sql語句,直接存物件
System.out.println(p);
}
注意:使用此功能時,需要在JavaBean物件中的每個成員變數上都加上@Column註解!!!
還有注意這裡的JavaBean中的addr與資料庫的欄位名address是不同的,所以需要在JavaBean物件的addr屬性上加上一句註解:
@Column(value=”address”)
Person.java
package cn.hncu.dbutils;
import org.apache.commons.dbutils.ext.Column;
import org.apache.commons.dbutils.ext.Table;
/**
* @author 陳浩翔
*
* 2016-8-15
*/
@Table(value = "person")
public class Person {
@Column
private String id;
@Column
private String name;
@Column(value="address")
public String addr;
//這裡的名字如果和資料庫的欄位名不同。會出現讀取值為null的情況
//如果要解決,把get和set函式的set/get***寫成和資料的欄位名一樣就可以了。
//或者在查詢的時候取別名如:select id,name,address as addr ,age from person
//但是最好還是和資料庫的欄位名一樣比較好
@Column
private Integer age;
public Person() {
super();
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return addr;
}
public void setAddress(String addr) {
this.addr = addr;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
@Override
public String toString() {
return "[id=" + id + ", name=" + name + ", addr=" + addr
+ ", age=" + age + "]";
}
}