我们在对mysql数据库进行操作时,就要使用JDBC去连接数据库,所以代码不免要出现大量的冗余,比如连接,关闭等等实现其实都是一样的,所以聪明的程序员就会将这些重复的功能封装,简化使用过程,提高代码复用性。
1.BaseDao源码
package com.xintoucloud.jdbcutil;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.xintoucloud.jdbcutil.exception.NoEntityClassException;
import com.xintoucloud.jdbcutil.exception.NoIdException;
public class BaseDao <E,P extends Serializable> {
//实例类Class对象
private Class<?> entityClass;
//实体类对应的表名
private String tableName;
//主键列名(为了根据id查询和删除)
private String idColumn;
//实体类属性和表的字段映射关系的集合(为了拼接SQL语句),save(E entity),update(E endity)
private List<PropertyColumnMapper> propertyColumnMappers;
//列名和属性名映射Map(为了通过列名找到属性名,进行映射一个列值到属性),为了查询
private Map<String,String> columnPropertyMap;
//Id属性
private Field idField;
protected BaseDao() {
//获取父类的泛型class
Type type = this.getClass().getGenericSuperclass();
ParameterizedType parameterizedType = (ParameterizedType)type;
entityClass =(Class<?>) (parameterizedType.getActualTypeArguments()[0]);
if(entityClass==null){
throw new NoEntityClassException("没有使用泛型指定实体类");
}
columnPropertyMap = new HashMap<>();
scanTableAnnotation();
scanIdProperty();
scanNormalProperty();
}
/**
* 扫描Table注解:得到表名
*/
private void scanTableAnnotation() {
Table table = entityClass.getAnnotation(Table.class);
if(table != null) {
tableName = table.value();
} else {
tableName = entityClass.getSimpleName();
}
}
/**
* 扫描Id属性:为了得到主键列和属性
*/
private void scanIdProperty() {
boolean hasId = false;
Field[] fields = entityClass.getDeclaredFields();
for(int i=0;i<fields.length;i++) {
Field field = fields[i];
Id idAnnotation = field.getAnnotation(Id.class);
//如果有Id注解
if(idAnnotation != null) {
//默认属性名称作为主键名称
idColumn = field.getName();
//如果Id注解有value值,那么主键名称就变成value值
String value = idAnnotation.value();
if(!value.isEmpty()) {
idColumn = value;
}
//赋值idField,(找到了Id属性)
idField = field;
columnPropertyMap.put(idColumn, field.getName());
//(找到了Id属性)
hasId = true;
}
}
if(!hasId) {
throw new NoIdException("请设置Id标示");
}
}
/**
* 扫描普通属性
*/
private void scanNormalProperty() {
Field[] fields = entityClass.getDeclaredFields();
propertyColumnMappers = new ArrayList<>();
for(int i=0;i<fields.length;i++) {
Field field = fields[i];
//不管Id属性
if(field.equals(idField)) {
continue;
}
//判断是否需要忽略
Transient transientAnnotation = field.getAnnotation(Transient.class);
//如果不需要忽略
if(transientAnnotation == null) {
Column column = field.getAnnotation(Column.class);
String columnName=null;
//有Column注解
if(column != null) {
//列名就是注解的value
columnName = column.value();
} else {
//否则是属性的名称
columnName = field.getName();
}
PropertyColumnMapper propertyColumnMapper = new PropertyColumnMapper(field.getName(),columnName,field.getType());
propertyColumnMappers.add(propertyColumnMapper);
columnPropertyMap.put(columnName, field.getName());
}
}
}
/**
* 通用的更新方法
*
* @param sql
* 要执行的SQL语句,参数使用?占位符
* @param parameters
* 占位符的值,顺序和SQL占位符对应
* @return 更新影响的行数
*/
public int update(String sql, Object[] parameters) {
Connection conn = JdbcUtil.getConnection();
int affectedRow = 0;
try (PreparedStatement st = conn.prepareStatement(sql)) {
// 给占位符赋值
setParameters(st, parameters);
affectedRow = st.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
return affectedRow;
}
/**
* 往那张表中填?
* 往哪些字段填(这个表一共有多少字段?哪些不需要填?)
* 主键如果是自增不需要填
*
* 保存一个对象
* @param entity 要保存的对象
* @return 数据表中受影响的行数
*
*
*/
public int save(E entity) {
//需要设置的参数数量赋值成需要保存的普通列的数量 6
int parameterCount = propertyColumnMappers.size();
StringBuilder sb = new StringBuilder("insert into ");
sb.append(tableName);
sb.append("(");
//循环实体类属性和表的字段映射关系的集合,拼接要添加的列名(除了Id列)
//insert into Student(sname,
for(int index=0;index<propertyColumnMappers.size();index++) {
PropertyColumnMapper propertyMapper = propertyColumnMappers.get(index);
sb.append(propertyMapper.getColumnName());
//一个列名后加,分割,最后一个列名后不加
if(index<propertyColumnMappers.size()-1) {
sb.append(",");
}
}
//判断id列是否需要加入
Id idAnnotation = idField.getAnnotation(Id.class);
GenarateType genarate = idAnnotation.genarate();
//如果Id是手工设置,拼接Id列名(参与保存操作)
if(genarate == GenarateType.ASSIGNED) {
sb.append(",");
sb.append(idColumn);
}
sb.append(") ");
sb.append("values ");
sb.append("(");
//拼接普通列对应的占位符?
for(int index=0;index<propertyColumnMappers.size();index++) {
sb.append("?");
if(index<propertyColumnMappers.size()-1) {
sb.append(",");
}
}
//如果Id是手工设置,拼接Id列名对应的占位符
if(genarate == GenarateType.ASSIGNED) {
sb.append(",?");
//需要设置的参数数量+1 7
parameterCount++;
}
//insert into Student(sname,ssex,sage,sdept,leftMoney,birthday,sno) values (?,?,?,?,?,?,?)
sb.append(")");
System.out.println(sb.toString());
//参数数组 7
Object[] parameters = new Object[parameterCount];
//给参数数组赋值
for(int index=0;index<propertyColumnMappers.size();index++) {
PropertyColumnMapper propertyMapper = propertyColumnMappers.get(index);
//从实体对象中取值
String propertyName = propertyMapper.getPropertyName();
String getMethodName = null;
//如果是boolean
if(propertyMapper.getPropertyType().equals(boolean.class)) {
getMethodName = "is"+propertyName.substring(0,1).toUpperCase()+propertyName.substring(1);
} else {
//getNo
getMethodName = "get"+propertyName.substring(0,1).toUpperCase()+propertyName.substring(1);
}
try {
//调用方法取值放入参数Object数组
parameters[index] = entityClass.getDeclaredMethod(getMethodName).invoke(entity);
} catch (Exception e) {
e.printStackTrace();
}
}
//如果Id列要保存,获取Id列对应属性的值加到参数值数组中
if(parameterCount > propertyColumnMappers.size()) {
try {
String getMethodName = "get"+idField.getName().substring(0,1).toUpperCase()+idField.getName().substring(1);
//Id列永远在最后
parameters[propertyColumnMappers.size()] = entityClass.getDeclaredMethod(getMethodName).invoke(entity);
} catch (Exception e) {
e.printStackTrace();
}
}
for(Object o : parameters) {
System.out.println(o);
}
return update(sb.toString(), parameters);
}
/**
* update student set sname=?,sage=? where sno=?
* 根据Id更新:数据表字段对应的属性都必须全部赋值,否则将置成属性默认值
* @param entity 要更新的实体
* @return 受影响的数据行数
*/
public int update(E entity) {
StringBuilder sb = new StringBuilder("update ");
sb.append(tableName);
sb.append(" ");
sb.append("set ");
for(int index=0;index<propertyColumnMappers.size();index++) {
PropertyColumnMapper propertyMapper = propertyColumnMappers.get(index);
sb.append(propertyMapper.getColumnName());
sb.append("=?");
if(index<propertyColumnMappers.size()-1) {
sb.append(",");
}
}
sb.append(" ");
sb.append("where ");
sb.append(idColumn);
sb.append("=?");
//update student set sname=?,ssex=?... where sno=?
System.out.println(sb.toString());
/*for(int i=0;i<values.length;i++) {
System.out.println(values[i]);
}*/
//return update(sb.toString(), values);
Object[] parameters = new Object[propertyColumnMappers.size()+1];
for(int index=0;index<propertyColumnMappers.size();index++) {
PropertyColumnMapper propertyMapper = propertyColumnMappers.get(index);
//从实体对象中取值
String propertyName = propertyMapper.getPropertyName();
String getMethodName = null;
//如果是boolean
if(propertyMapper.getPropertyType().equals(boolean.class)) {
getMethodName = "is"+propertyName.substring(0,1).toUpperCase()+propertyName.substring(1);
} else {
getMethodName = "get"+propertyName.substring(0,1).toUpperCase()+propertyName.substring(1);
}
try {
//调用方法取值放入参数Object数组
parameters[index] = entityClass.getDeclaredMethod(getMethodName).invoke(entity);
} catch (Exception e) {
e.printStackTrace();
}
}
try {
String getMethodName = "get"+idField.getName().substring(0,1).toUpperCase()+idField.getName().substring(1);
parameters[propertyColumnMappers.size()] = entityClass.getDeclaredMethod(getMethodName).invoke(entity);
} catch (Exception e) {
e.printStackTrace();
}
for(Object o : parameters) {
System.out.println(o);
}
return update(sb.toString(),parameters);
}
/**
* ?删除的是哪张表的数据?
* ?怎么确定主键的名称?
* 根据主键查询一条记录并封装为实体对象
* @param idValue id值
*/
public E get(P idValue) {
String sql = "select * from "+tableName+" where "+idColumn+"=?";
System.out.println("get(sql)="+sql);
return get(sql,new Object[] {idValue});
}
/**
* 根据主键删除一条记录并封装为实体对象
* @param idValue id值
* @return 受影响的数据行数
*/
public int delete(P idValue) {
String sql = "delete from "+tableName+" where "+idColumn+"=?";
System.out.println("delete(sql)="+sql);
return update(sql,new Object[] {idValue});
}
/**
* 统计一个表中的全部记录行数
* @return 全部记录行数
*/
public int count() {
String sql = "select count(*) from "+tableName;
return count(sql, null);
}
/**
* 根据传入的SQL语句统计结果集行数
* @param sql SQL语句
* @param parameters 参数值数组
* @return 结果集行数
*/
public int count(String sql,Object[] parameters) {
Connection conn = JdbcUtil.getConnection();
PreparedStatement st = null;
ResultSet rs = null;
int rowCount = 0;
try {
st = conn.prepareStatement(sql);
// 给占位符赋值
setParameters(st, parameters);
rs = st.executeQuery();
if(rs.next()) {
rowCount = rs.getInt(1);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JdbcUtil.closeResultSet(rs);
JdbcUtil.closeStatement(st);
}
return rowCount;
}
/**
* 根据查询SQL语句查询一条记录并封装为实体对象
* @param sql 查询SQL语句
* @param parameters 占位符的值,顺序和SQL占位符对应
* @return 返回封装好的实体对象,如果记录不存在返回null
*/
public E get(String sql, Object ... parameters) {
Connection conn = JdbcUtil.getConnection();
PreparedStatement st = null;
ResultSet rs = null;
E obj = null;
try {
st = conn.prepareStatement(sql);
// 给占位符赋值
setParameters(st, parameters);
rs = st.executeQuery();
//String sql = "select bid,bname from board";
if(rs.next()) {
//把一行记录封装到一个实体对象里
obj = oneRowToObject(rs);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JdbcUtil.closeResultSet(rs);
JdbcUtil.closeStatement(st);
}
return obj;
}
/**
* 根据查询SQL语句查询一条记录并封装为实体对象
* @param sql 查询SQL语句
* @param parameters 占位符的值,顺序和SQL占位符对应
* @param rowMapper 行映射对象
* @return 返回封装好的实体对象,如果记录不存在返回null
*/
public <V> V get(String sql,RowMapper<V> rowMapper, Object...parameters) {
Connection conn = JdbcUtil.getConnection();
PreparedStatement st = null;
ResultSet rs = null;
V obj = null;
try {
st = conn.prepareStatement(sql);
// 给占位符赋值
setParameters(st, parameters);
rs = st.executeQuery();
//String sql = "select bid,bname from board";
if(rs.next()) {
//把一行记录封装到一个实体对象里
obj = rowMapper.mapRow(rs);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JdbcUtil.closeResultSet(rs);
JdbcUtil.closeStatement(st);
}
return obj;
}
/**
* 根据查询SQL语句查询多条记录并封装为实体对象集合
* @param sql 查询SQL语句
* @param parameters 占位符的值,顺序和SQL占位符对应
* @return 返回封装好的实体对象集合,如果记录不存在返回一个空集合
*/
public List<E> list(String sql, Object...parameters) {
Connection conn = JdbcUtil.getConnection();
PreparedStatement st = null;
ResultSet rs = null;
List<E> list = new ArrayList<>();
try {
st = conn.prepareStatement(sql);
// 给占位符赋值
setParameters(st, parameters);
rs = st.executeQuery();
while(rs.next()) {
//把一行记录封装到一个实体对象里
E obj = oneRowToObject(rs);
list.add(obj);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JdbcUtil.closeResultSet(rs);
JdbcUtil.closeStatement(st);
}
return list;
}
/**
* 单表分页查询
* @param start 开始位置
* @param limit 限定行数
* @return 返回封装好的实体对象集合,如果记录不存在返回一个空集合
*/
public List<E> list(int start,int limit) {
String sql = "select * from "+tableName+" limit ?,?";
return list(sql,new Object[] {start,limit});
}
/**
* 单表分页查询
* @param start 开始位置
* @param limit 限定行数
* @return 返回封装好的实体对象集合,如果记录不存在返回一个空集合
*/
public void list(Page<E> page) {
if(page.autoCount) {
int totalCount = count();
page.setTotalCount(totalCount);
}
List<E> data = list(page.start,page.limit);
page.setResult(data);
}
/**
* 多表连接查询
* 根据查询SQL语句查询多条记录并封装为实体对象集合
* @param sql 查询SQL语句
* @param parameters 占位符的值,顺序和SQL占位符对应
* @param rowMapper 行的映射器
* @return 返回封装好的实体对象集合,如果记录不存在返回一个空集合
*/
public <V> List<V> listJoin(String sql,RowMapper<V> rowMapper, Object...parameters) {
Connection conn = JdbcUtil.getConnection();
PreparedStatement st = null;
ResultSet rs = null;
List<V> list = new ArrayList<>();
try {
st = conn.prepareStatement(sql);
// 给占位符赋值
setParameters(st, parameters);
rs = st.executeQuery();
while(rs.next()) {
//把一行记录封装到一个实体对象里
//回调接口
V obj = rowMapper.mapRow(rs);
list.add(obj);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JdbcUtil.closeResultSet(rs);
JdbcUtil.closeStatement(st);
}
return list;
}
/**
* 一行到一个对象的映射
* @param rs 结果集
* @return 设置好数据的一个对象
* @throws InstantiationException
* @throws IllegalAccessException
* @throws InvocationTargetException
* @throws NoSuchMethodException
* @throws SQLException
*/
@SuppressWarnings("unchecked")
private E oneRowToObject(ResultSet rs) throws InstantiationException,
IllegalAccessException, InvocationTargetException, NoSuchMethodException, SQLException {
E obj = (E) entityClass.getConstructor().newInstance();
//获取结果集元数据
ResultSetMetaData rsmd = rs.getMetaData();
for(int i=0;i<rsmd.getColumnCount();i++) {
//获取一列的列名和数据类型
String columnName = rsmd.getColumnName(i+1);
Integer columnType = rsmd.getColumnType(i+1);
//拼实体对象里对应的set方法名
//String methodName = "set"+columnName.substring(0,1).toUpperCase()+columnName.substring(1);
//sno -> no
String fieldName = columnPropertyMap.get(columnName);
if(fieldName!=null) {
String methodName = "set"+columnPropertyMap.get(columnName).substring(0,1).toUpperCase()+columnPropertyMap.get(columnName).substring(1);
//System.out.println(methodName);
switch(columnType) {
case java.sql.Types.INTEGER:
case java.sql.Types.SMALLINT:
case java.sql.Types.TINYINT:
Method method = null;
try {
//先尝试使用int类型映射
method = entityClass.getMethod(methodName, int.class);
if(method != null) {
method.invoke(obj, rs.getInt(columnName));
}
} catch (Exception e) {
//再试使用Integer类型映射
method = entityClass.getMethod(methodName, Integer.class);
if(method != null) {
method.invoke(obj, rs.getInt(columnName));
}
}
break;
case java.sql.Types.BIGINT:
try {
//先尝试使用int类型映射
method = entityClass.getMethod(methodName, long.class);
if(method != null) {
method.invoke(obj, rs.getLong(columnName));
}
} catch (Exception e) {
//先尝试使用Integer类型映射
method = entityClass.getMethod(methodName, Long.class);
if(method != null) {
method.invoke(obj, rs.getLong(columnName));
}
}
break;
case java.sql.Types.BIT:
try {
//先尝试使用int类型映射
method = entityClass.getMethod(methodName, boolean.class);
if(method != null) {
method.invoke(obj, rs.getBoolean(columnName));
}
} catch (Exception e) {
//先尝试使用Integer类型映射
method = entityClass.getMethod(methodName, int.class);
if(method != null) {
method.invoke(obj, rs.getInt(columnName));
}
}
break;
case java.sql.Types.CHAR:
case java.sql.Types.VARCHAR:
case java.sql.Types.LONGVARCHAR:
try {
//先尝试使用int类型映射
method = entityClass.getMethod(methodName, String.class);
if(method != null) {
method.invoke(obj, rs.getString(columnName));
}
} catch (NoSuchMethodException e) {
}
break;
case java.sql.Types.DATE:
try {
//先尝试使用int类型映射
method = entityClass.getMethod(methodName, String.class);
if(method != null) {
method.invoke(obj, rs.getString(columnName));
}
} catch (Exception e) {
//先尝试使用Integer类型映射
method = entityClass.getMethod(methodName, Date.class);
if(method != null) {
method.invoke(obj, rs.getDate(columnName));
}
}
break;
case java.sql.Types.TIMESTAMP:
try {
//先尝试使用int类型映射
method = entityClass.getMethod(methodName, String.class);
if(method != null) {
method.invoke(obj, rs.getString(columnName));
}
} catch (Exception e) {
//先尝试使用Integer类型映射
method = entityClass.getMethod(methodName, Date.class);
if(method != null) {
method.invoke(obj, rs.getTimestamp(columnName));
}
}
break;
case java.sql.Types.TIME:
try {
//先尝试使用int类型映射
method = entityClass.getMethod(methodName, String.class);
if(method != null) {
method.invoke(obj, rs.getString(columnName));
}
} catch (Exception e) {
//先尝试使用Integer类型映射
method = entityClass.getMethod(methodName, Date.class);
if(method != null) {
method.invoke(obj, rs.getTime(columnName));
}
}
break;
case java.sql.Types.FLOAT:
case java.sql.Types.REAL:
case java.sql.Types.DOUBLE:
try {
//先尝试使用int类型映射
method = entityClass.getMethod(methodName, double.class);
if(method != null) {
method.invoke(obj, rs.getDouble(columnName));
}
} catch (Exception e) {
//先尝试使用Integer类型映射
method = entityClass.getMethod(methodName, String.class);
if(method != null) {
method.invoke(obj, rs.getString(columnName));
}
}
break;
case java.sql.Types.DECIMAL:
try {
//先尝试使用int类型映射
method = entityClass.getMethod(methodName, BigDecimal.class);
if(method != null) {
method.invoke(obj, rs.getBigDecimal(columnName));
}
} catch (Exception e) {
//先尝试使用Integer类型映射
method = entityClass.getMethod(methodName, String.class);
if(method != null) {
method.invoke(obj, rs.getString(columnName));
}
}
break;
default:
break;
}
}
}
return obj;
}
/**
* 私有方法:给SQL语句占位符赋值
* @param st PreparedStatement对象
* @param parameters 参数数组
* @throws SQLException SQL异常
*/
private void setParameters(PreparedStatement st, Object[] parameters) throws SQLException {
if (parameters != null && parameters.length > 0) {
for (int i = 0; i < parameters.length; i++) {
st.setObject(i + 1, parameters[i]);
}
}
}
}
2.column
package com.xintoucloud.jdbcutil;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 映射实体属性名对应表的列名
* @author Administrator
*
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
/**
* 映射的列名,默认和属性名一样
* @return
*/
String value();
}
3.generateType
package com.xintoucloud.jdbcutil;
public enum GenarateType {
AUTO_INCREMENT,
ASSIGNED
}
4.id
package com.xintoucloud.jdbcutil;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 标示一个主键的注解,只能用到属性上
* @author Administrator
*
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Id {
/**
* 对应的列名,默认为""和属性名一样
* @return
*/
String value() default "";
/**
* 主键生成类型,默认自动增长
* @return
*/
GenarateType genarate() default GenarateType.AUTO_INCREMENT;
}
5.JdbcUtil
package com.xintoucloud.jdbcutil;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
* 数据库连接工具类
* @author yccn@163.com
*
*/
public class JdbcUtil {
private static String DRIVER;
private static String URL;
private static String USER;
private static String PASSWORD;
private static final ThreadLocal<Connection> THREAD_LOCAL = new ThreadLocal<>();
static {
InputStream is = JdbcUtil.class.getResourceAsStream("/db-config.properties");
Properties properties = new Properties();
try {
properties.load(is);
DRIVER = properties.getProperty("DRIVER_CLASS");
URL = properties.getProperty("URL");
USER = properties.getProperty("USER");
PASSWORD = properties.getProperty("PASSWORD");
Class.forName(DRIVER);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取数据库连接
* @return 数据库连接,如果有异常返回null
*/
public static Connection getConnection() {
//System.out.println("getConnection");
//尝试从本地线程变量中获取连接
Connection conn = THREAD_LOCAL.get();
//如果本地线程变量中没有连接
if(conn == null) {
try {
//从数据库获取连接
conn = DriverManager.getConnection(URL,USER,PASSWORD);
//放入本地线程变量
THREAD_LOCAL.set(conn);
} catch (SQLException e) {
e.printStackTrace();
}
}
return conn;
}
/**
* 开启事务
*/
public static void beginTransaction() {
Connection conn = getConnection();
if(conn != null) {
try {
conn.setAutoCommit(false);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 提交事务
*/
public static void commit() {
Connection conn = getConnection();
if(conn != null) {
try {
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 回滚事务
*/
public static void rollback() {
Connection conn = getConnection();
if(conn != null) {
try {
conn.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 关闭结果集
* @param rs
*/
public static void closeResultSet(ResultSet rs) {
try {
if(rs != null) {
rs.close();
rs = null;
}
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 关闭Statement
* @param st
*/
public static void closeStatement(Statement st) {
try {
if(st != null) {
st.close();
st = null;
}
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 关闭连接
*/
public static void closeConnection() {
Connection conn = THREAD_LOCAL.get();
if(conn != null) {
try {
conn.close();
//从线程本地变量中移除
THREAD_LOCAL.remove();
conn = null;
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 释放资源
* @param conn 连接对象
* @param st Statement对象
* @param rs ResultSet对象
*/
public static void closeAll(Connection conn,Statement st,ResultSet rs) {
try {
if(rs != null) {
rs.close();
}
if(st != null) {
st.close();
}
if(conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
6.Page
package com.xintoucloud.jdbcutil;
import java.util.ArrayList;
import java.util.List;
/**
*
* @param <T>
* Page中记录的类型.
*
* @author YCCN
*/
public class Page<T> {
// -- 分页参数 --//
protected int start;
protected int limit;
// 是否自动查询总条数
protected boolean autoCount = true;
// -- 返回结果 --//
protected List<T> result = new ArrayList<T>();
// 保存数据总条数
protected int totalCount;
// -- 构造函数 --//
public Page() {
}
public Page(int start, int limit) {
this.start = start;
this.limit = limit;
}
public int getStart() {
return start;
}
public void setStart(int start) {
this.start = start;
}
public int getLimit() {
return limit;
}
public void setLimit(int limit) {
this.limit = limit;
}
/**
* 获得查询对象时是否先自动执行count查询获取总记录数, 默认为false.
*/
public boolean isAutoCount() {
return autoCount;
}
/**
* 设置查询对象时是否自动先执行count查询获取总记录数.
*/
public void setAutoCount(final boolean autoCount) {
this.autoCount = autoCount;
}
/**
* 获得页内的记录列表.
*/
public List<T> getResult() {
return result;
}
/**
* 设置页内的记录列表.
*/
public void setResult(final List<T> result) {
this.result = result;
}
/**
* 获得总记录数, 默认值为0.
*/
public long getTotalCount() {
return totalCount;
}
/**
* 设置总记录数.
*/
public void setTotalCount(final int totalCount) {
this.totalCount = totalCount;
}
/**
* 获得总页数
*
* @return 总页数
*/
public int getTotalPages() {
if (autoCount && totalCount != -1 && limit != -1) {
return totalCount % limit == 0 ? totalCount / limit : totalCount / limit + 1;
}
return 0;
}
/**
* 获得当前页
*
* @return 当前页
*/
public int getPageIndex() {
if (getTotalPages() > 0) {
return start / limit + 1;
}
return 0;
}
/**
* 是否有下一页
*
* @return
*/
public boolean isNextPage() {
if (getPageIndex() < getTotalPages()) {
return true;
}
return false;
}
/**
* 是否有上一页
*
* @return
*/
public boolean isPrePage() {
if (getPageIndex() > 1) {
return true;
}
return false;
}
}
7.PropertyColumnMapper
package com.xintoucloud.jdbcutil;
/**
* 实体属性和列名和属性类型的映射
* @author Administrator
*
*/
class PropertyColumnMapper {
private String propertyName;
private String columnName;
private Class<?> propertyType;
public PropertyColumnMapper() {}
public PropertyColumnMapper(String propertyName, String columnName,Class<?> propertyType) {
super();
this.propertyName = propertyName;
this.columnName = columnName;
this.propertyType = propertyType;
}
public String getColumnName() {
return columnName;
}
public String getPropertyName() {
return propertyName;
}
public Class<?> getPropertyType() {
return propertyType;
}
public void setColumnName(String columnName) {
this.columnName = columnName;
}
public void setPropertyName(String propertyName) {
this.propertyName = propertyName;
}
public void setPropertyType(Class<?> propertyType) {
this.propertyType = propertyType;
}
}
8.RowMapper
package com.xintoucloud.jdbcutil;
import java.sql.ResultSet;
/**
* 结果集行的映射(主要对应多表连接查询)
* @author Administrator
*
*/
public interface RowMapper<V> {
/**
* 结果集一行映射为一个对象
* @param rs 结果集
* @return 映射好的对象
*/
V mapRow(ResultSet rs);
}
9.Table
package com.xintoucloud.jdbcutil;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 设置一个实体对应的表名,如果没有设置则和实体类名一样
* @author Administrator
*
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
String value() ;
}
10.Transient
package com.xintoucloud.jdbcutil;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 标示一个不持久化的属性的注解,只能用到属性上
* @author Administrator
*
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Transient {
}
11.NoEntityClassException
package com.xintoucloud.jdbcutil.exception;
public class NoEntityClassException extends RuntimeException {
/**
*
*/
private static final long serialVersionUID = -6894334255503447296L;
public NoEntityClassException(String message) {
super(message);
}
}
12.NoIdException
package com.xintoucloud.jdbcutil.exception;
public class NoIdException extends RuntimeException{
/**
*
*/
private static final long serialVersionUID = -981438111240259266L;
public NoIdException(String message) {
super(message);
}
}