import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
* Mysql操作类,封装了连接断开数据库、使用预编译的SQl模板快速增删改查方法,时间紧迫,异常没有处理完善
* 封装了将查询记录集转成Javabean集合和遍历记录集的方法
*
*
@author
王凯旋
*
*/
public
class Mysql {
private
static Mysql mysql;
private Connection conn;
private Statement stmt;
private Map
<
String,PreparedStatement
> pstmt;
private Mysql() {
}
private Mysql(
String url,
String username,
String password) {
try {
Class.forName(
"com.mysql.jdbc.Driver");
conn
= DriverManager.getConnection(url, username, password);
stmt
= conn.createStatement();
pstmt
=
new HashMap
<
String, PreparedStatement
>();
}
catch (
Exception e) {
e.printStackTrace();
}
}
/**
* 使用单例模式懒汉式,调用构造方法,创建本类实例
*
*
@param
mysql
* 地址,例如jdbc:mysql://localhost/table_name,
* database_name为你想要连接的数据库名
*
@param
username
* mysql管理员用户名,如root
*
@param
password
* mysql管理员密码
*
@return
返回本类实例
*/
public
static
synchronized Mysql getInstance(
String url,
String username,
String password) {
if (mysql
== null) {
mysql
=
new Mysql(url, username, password);
}
return mysql;
}
/**
* 将sql语句预编译成sql模板,储存该模板到本类内置的map集合,键为key
*
*
@param
sql
* sql语句,可以带占位符
*
@return
sql模板
*/
public
void setPstmt(
String key,
String sql) {
try {
PreparedStatement ps
= conn.prepareStatement(sql);
pstmt.put(key, ps);
}
catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 快速查询,该方法先检查内置的map集合中是否有预编译的sql模板,如果有就使用模板进行查询,否则使用普通查询
* 使用setPstmt()方法可设置sql模板
*
*
@param
stmt
* 存储到map集合中的sql模板的key,或者要执行的sql语句
*
@param
arr
* 替换占位符的参数,可变参数,模板中有几个问号就需要几个参数。支持任意类型,当使用普通查询时忽略该参数
*
@return
查询结果集
*/
public ResultSet Query(
String stmt,
Object... arr) {
try {
for (Entry
<
String, PreparedStatement
> en :
this.pstmt.entrySet()) {
if (en.getKey().equals(stmt)) {
PreparedStatement ps
= en.getValue();
for (
int i
= 0; i
< arr.length; i
++) {
ps.setObject(i
+ 1, arr[i]);
}
return ps.executeQuery();
}
}
return
this.stmt.executeQuery(stmt);
}
catch (SQLException e) {
e.printStackTrace();
}
return null;
}
/**
* 快速更新,该方法先检查内置的map集合中是否有预编译的sql模板,如果有就使用模板进行更新,否则使用普通更新
* 使用setPstmt()方法可设置sql模板
*
*
@param
pstmt
* 可调用getPstmt()方法得到
*
@param
arr
* 替换占位符的参数,可变参数,模板中有几个问号就需要几个参数。Object,支持任意类型
*
@return
查询结果集
*/
public
int Update(
String stmt,
Object... arr) {
try {
for (Entry
<
String, PreparedStatement
> en :
this.pstmt.entrySet()) {
if (en.getKey().equals(stmt)) {
PreparedStatement ps
= en.getValue();
for (
int i
= 0; i
< arr.length; i
++) {
ps.setObject(i
+ 1, arr[i]);
}
return ps.executeUpdate();
}
}
return
this.stmt.executeUpdate(stmt);
}
catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
/**
* 断开mysql连接,释放资源
*/
public
void close() {
if (stmt
!= null) {
try {
stmt.close();
stmt
= null;
}
catch (SQLException e) {
e.printStackTrace();
}
}
if (conn
!= null) {
try {
conn.close();
conn
= null;
}
catch (SQLException e) {
e.printStackTrace();
}
}
mysql
= null;
}
/**
* 遍历输出记录集的所有记录,包括列名称
* 此方法和getList()方法都会调用rs的close()方法释放资源
*
@param
rs 要遍历的记录集
*/
public
static
void showResult(ResultSet rs) {
try {
//获取元数据
ResultSetMetaData rsmd
= rs.getMetaData();
//得到总列数
int lie
=rsmd.getColumnCount();
//循环输出列名称
for (
int i
= 1; i
<= lie; i
++) {
System.out.print(rsmd.getColumnName(i)
+
"\t");
}
System.out.println();
//记录行数
int hang
=0;
while (rs.next()) {
hang
++;
//循环输出此行记录的每一列数据
for (
int x
= 1; x
<= lie; x
++) {
System.out.print(rs.getString(x)
+
"\t");
}
System.out.println();
}
//输出统计信息
System.out.println(lie
+
"列,"
+hang
+
"条记录。");
}
catch (SQLException e) {
e.printStackTrace();
}
finally{
try {
rs.close();
}
catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 一个神奇的方法!花了两个钟头才写出来,结合了Java的泛型和反射技术!
* 将mysql的查询结果集封装成Javabean储存到List集合中
*
* 实现原理:
* 获取结果集的元数据,得到各列的列名称
* 使用反射,创建参数clazz的对象,调用对象与列名称相对应的所有的set方法
* 【注意】请确保结果集的列名称和Javabean的属性名称、个数和类型完全相同
* 如果属性名称不同,可以在sql查询语句中使用 AS 关键字为列起别名
* 此方法和showResult()方法都会调用rs的close()方法释放资源
*
*
@param
rs 要封装到Javabean的结果集
*
@param
clazz Javabean的类对象,如:User.class,本方法使用泛型技术,
* 根据传入的class确定返回的集合类型
*
@return
返回储存Javabean的List集合
*/
public
static
<T
> List
<T
> getList(ResultSet rs,
Class
<T
> clazz) {
List
<T
> al
=null;
try {
ResultSetMetaData rsmd
= rs.getMetaData();
int lie
=rsmd.getColumnCount();
al
=
new ArrayList
<T
>();
while (rs.next()) {
T t
= null;
try {
t
= clazz.newInstance();
}
catch (
Exception e) {
e.printStackTrace();
}
for (
int j
= 0; j
< lie; j
++) {
// System.out.println("set"+rsmd.getColumnName(j+1)+"::"+rs.getObject(j+1));
invokeX(t,
"set"
+rsmd.getColumnName(j+1), rs.getObject(j+1));
}
al.add(t);
}
}
catch (SQLException e) {
e.printStackTrace();
}
finally{
try {
rs.close();
}
catch (SQLException e) {
e.printStackTrace();
}
}
return al;
}
/**
* 接收一个对象,根据传入的方法名称,调用方法(支持有参多参或无参)【反射实现】
*
@param
o 要处理的对象
*
@param
name 方法的名称,忽略大小写
*
@param
oo 参数,无参可使用null
*
@return
如果有返回值就返回,没有返回null
*/
private
static
Object invokeX(
Object o,
String name,
Object...oo) {
Class clazz
=o.getClass();
Method[] mm
=clazz.getDeclaredMethods();
for (Method method : mm) {
if (method.getName().equalsIgnoreCase(name)) {
try {
return method.invoke(o, oo);
}
catch (
Exception e) {
e.printStackTrace();
}
}
}
return null;
}
}
package com.kxrjkf.user.dao.impl;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.ResourceBundle;
import com.kxrjkf.user.dao.UserDao;
import com.kxrjkf.user.domin.User;
import com.kxrjkf.user.utils.Mysql;
public
class UserDaoImpl
implements UserDao {
private
static Mysql mysql
= null;
static {
ResourceBundle rb
= ResourceBundle.getBundle(
"config");
mysql
= Mysql.getInstance(rb.getString(
"url"),
rb.getString(
"username"), rb.getString(
"password"));
String biao
= rb.getString(
"biao");
// add方法的sql模板
mysql.setPstmt(
"addstmt",
"insert into "
+ biao
+
" VALUES(null,?,?,?) ;");
// delete方法的sql模板
mysql.setPstmt(
"delstmt",
"DELETE FROM "
+ biao
+
" where id=? ;");
// edit方法的sql模板
mysql.setPstmt(
"upstmt",
"UPDATE "
+ biao
+
" SET name=?,phone=?,`like`=? where id=? ;");
// findId方法的sql模板
mysql.setPstmt(
"findIdstmt",
"select * from "
+ biao
+
" where id=? ;" );
// getList方法的sql模板
mysql.setPstmt(
"liststmt",
"select * from "
+ biao
+
" ;");
// 分页getList方法的sql模板
mysql.setPstmt(
"fenyestmt",
"select * from "
+ biao
+
" limit ?,? ;" );
// getZong方法的sql模板
mysql.setPstmt(
"zongstmt",
"select count(*) from "
+ biao
+
" ;");
}
/**
* 添加客户
*
@param
user 想要添加的客户
*/
public
void add(User user) {
mysql.Update(
"addstmt", user.getName(), user.getPhone(),
user.getLike());
}
/**
* 删除客户
*
@param
id 客户的id
*/
public
void delete(
int id) {
mysql.Update(
"delstmt", id);
}
/**
* 修改客户资料
*
@param
id 客户id
*
@param
user 客户
*/
public
void update(
int id, User user) {
mysql.Update(
"upstmt", user.getName(), user.getPhone(),
user.getLike(), id);
}
/**
* 根据id查询客户
*
@param
id 客户id
*
@return
找到返回客户信息,找不到返回null
*/
public User findId(
int id) {
List
<User
> u
= mysql.getList(mysql.Query(
"findIdstmt", id),
User.
class);
User user
= null;
if (u.size()
!= 0) {
user
= u.get(0);
}
return user;
}
/**
* 获取所有客户
*
@return
List集合
*/
public List
<User
> getList() {
return mysql.getList(mysql.Query(
"liststmt"), User.
class);
}
/**
* 分页获取客户集合
*
@param
qishi 开始的位置
*
@param
tiaoshu 要查询的条数
*
@return
返回本页客户集合
*/
public List
<User
> getList(
int qishi,
int tiaoshu) {
return mysql.getList(mysql.Query(
"fenyestmt", qishi, tiaoshu),
User.
class);
}
/**
* 获取客户总数
*
@return
客户总数
*/
public
int getZong() {
ResultSet rs
= mysql.Query(
"zongstmt");
try {
rs.next();
return rs.getInt(1);
}
catch (SQLException e) {
e.printStackTrace();
}
return 0;
}
//测试
// public static void main(String[] args) {
// new UserDaoImpl().add(new User("张三", "3333", "三三"));
// new UserDaoImpl().delete(5);
// new UserDaoImpl().update(1, new User("小白", "8888888", "睡觉"));
// System.out.println(new UserDaoImpl().findId(3));
// for (User u : new UserDaoImpl().getList(1,2)) {
// System.out.println(u);
// }
// UserDaoImpl udi = new UserDaoImpl();
// System.out.println(udi.getZong());
// }
}