package org.jplus.hyb.database;
import com.jplus.json.EasyUiJson;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jplus.util.LoggerManage;
import org.jplus.util.Pagger;
/**
* 数据库持久层框架核心类之一
* <p>
* 此类用于不给定POJO类的数据库查询,所有查询到的信息只与查询结果集的信息有关。 需要与EasyData类配合使用。
* 均没有绑定数据库预处理机制,需要用户自己调用addParmeter(……)方法。
* 需要在项目缺省包下面添加配置文件properties(整个项目仅此一个数据库配置).
* 多用于对数据库单表或者多表的查询操作,不对POJO类产生依赖性。 支持一个数据库连接的单次,多次利用。
* </p>
*
* @version 3.6
* @author hyberbin
*/
public class SoEasy extends DatabaseAccess {
/** 结果集的字段名 */
private List columnName;
/** 结果集列表 */
private List<EasyData> dataList;
/**
* 空构造方法,适用于一次查询,操作完后自动关闭数据库。
* <p> Ex:
* <strong> <p>SoEasy soeasy=new SoEasy();</strong>
*/
public SoEasy() {
super(DatabaseINI.getConnection());//数据库操作对象
}
/**
* 带一个参数的构造方法,适用于一个连接做多次操作
* <p> Ex:
* <p>Connection conn = DatabaseINI.getDatabase().getConn();//获得一个数据库连接
* <strong><p>SoEasy soeasy=new SoEasy(conn);//用自带的数据库连接进行数据库操作</strong>
*
* @param conn 数据库连接对象
*/
public SoEasy(Connection conn) {
super(conn);
transactionBegan();
}
/**
* 一个连接可以多次操作的构造方法
* <p> Ex:
* <strong><p>SoEasy soeasy=new SoEasy(true);//可多次使用数据库连接</strong>
*
* @param repeat 是否可以重复操作
*/
public SoEasy(boolean repeat) {
super(DatabaseINI.getConnection());
if (repeat) {
transactionBegan();
}
}
/**
* 设置字段信息
* <p>设置字段名信息方便最后取数据,一般情况下可以自动获取,所以不需要调用。(此方法不常用)
* <p>Ex:
* <p>String[] column=new String[]{"id","content","type"};
* <p>SoEasy soeasy=new SoEasy();
* <p>soeasy.setColumn(column);
*
* @param columnName 字段信息
*/
public void setColumn(String[] columnName) {
this.columnName = Arrays.asList(columnName);
}
/**
* 在预处理中加入新的参数
* <p>些方法返回自身对象,可以链式编程。soEasy.addParmeter("%"+other+"%").soEasy("1");
* <p>为了增加数据库操作的安全性,建议所有自构的sql语句均要调用本方法。
* <p>加入参数时所有参数均不需要单引号。
* <p>加入时应该按照参数出现的位置按顺序调用。
* <p>like语句应该这样添加addParmeter("%"+other+"%");
* <p>Ex:
* <p>SoEasy soEasy=new SoEasy();//构建SoEasy,而且是一次性操作。操作完后自动关闭数据库。
* <p>String other="hyb";
* <strong><p>soEasy.addParmeter("%"+other+"%");</strong>
* <strong><p>soEasy.addParmeter("1");</strong>
* <p>soEasy.showOne("select * from news where content like ? and
* newstype=?");
*
* @param parmeter 参数
* @return 自身对象
*/
public SoEasy addParmeter(Object parmeter) {
setParmeter(parmeter);
return this;
}
/**
* 根据指定SQL语句查询一条数据
* <p>此方法用于对数据库单表的查询操作,用于用户自己提供sql语句。
* <p>此方法默认不会使用sql预处理技术。
* <p>建议用户自己使用预处理技术(addParmeter("……"))以提高安全性。
* <p>Ex:
* <p>SoEasy soEasy=new SoEasy();//操作完后自动关闭数据库。
* <p>soEasy.addParmeter(2);
* <strong><p>soEasy.showOne("select * from news where id=?");
* //查询id为2的新闻</strong>
*
* @param sql 指定SQL语句 sql语句可以是很复杂的多表关联查询等
* @return EasyData
*/
public EasyData showOne(String sql) {
if (super.isFilter()) {
super.getSql(sql);
sql = super.getSelectSQL();
}
List<EasyData> list = loadData(query(sql + " limit 0,1")); //执行查询
return list.size() > 0 ? list.get(0) : null;
}
public Map showOneForMap(String sql) {
if (super.isFilter()) {
super.getSql(sql);
sql = super.getSelectSQL();
}
Map map = new HashMap();
ResultSet rs = query(sql + " limit 0,1");
try {
ResultSetMetaData metaData = rs.getMetaData();
int columnCount = metaData.getColumnCount();
getColumn(metaData);
if (rs != null && rs.next()) {
for (int i = 1; i <= columnCount; i++) {
map.put(metaData.getColumnName(i), rs.getObject(i));
}
}
} catch (SQLException ex) {
LoggerManage.logger.getLogger("SoEasy查询出错,\nsql:" + sql + "\n", ex);
} finally {
close();
}
return map;
}
/**
* 从数据库查询结果集合中取得数据
*
* @param rs 数据库查询结果集合
* @return List<EasyData>
*/
private List<EasyData> loadData(ResultSet rs) {
dataList = new ArrayList<EasyData>();
try {
ResultSetMetaData metaData = rs.getMetaData();
int columnCount = metaData.getColumnCount();
getColumn(metaData);
while (rs != null && rs.next()) {
Object[] object = new Object[columnCount];
for (int i = 1; i <= columnCount; i++) {
object[i - 1] = rs.getObject(i);
}
dataList.add(new EasyData(object, columnName));
}
} catch (SQLException ex) {
LoggerManage.logger.getLogger("SoEasy加载数据出错", ex);
} finally {
close();
}
return dataList;
}
public int getCount(String sql) {
if (super.isFilter()) {
super.getSql(sql);
sql = super.getCountSQL();
}
int count = 0;
ResultSet rs = query(sql);
try {
if (rs != null && rs.next()) {
count = rs.getInt(1);
}
} catch (SQLException ex) {
LoggerManage.logger.getLogger("SoEasy查询数据总数出错\nsql:" + sql + "\n", ex);
} finally {
close();
}
return count;
}
/**
* 获得查询集合
* <p>此方法用于返回一个数据库集合
* <p>此方法默认不会使用sql预处理技术。
* <p>建议用户自己使用预处理技术(addParmeter("……"))以提高安全性。
* <p>Ex:
* <p>SoEasy soEasy=new SoEasy();//操作完后自动关闭数据库。
* <p>soEasy.addParmeter(2);
* <strong><p>List<EasyData> list=soEasy.getList("select * from
* news,newstype where newtype.id=news.type and news.type=?");</strong>
*
* @param sql
* @return List<EasyData>
*/
public List<EasyData> getList(String sql) {
if (super.isFilter()) {
super.getSql(sql);
sql = super.getSelectSQL();
}
loadData(query(sql));
close();
return dataList;
}
private void getColumn(ResultSetMetaData metaData) throws SQLException {
if (metaData != null) {
int columnCount = metaData.getColumnCount();
columnName = new ArrayList();
for (int i = 1; i <= columnCount; i++) {
columnName.add(metaData.getColumnName(i));
}
}
}
public List getColumnName() {
return columnName;
}
/**
* 根据SQL语句查出一个map集合
* <p>此方法用于返回一个数据库集合生成json格式数据更方便
* <p>此方法默认不会使用sql预处理技术。
* <p>建议用户自己使用预处理技术(addParmeter("……"))以提高安全性。
* <p>经大数据量测试getMapList比getList占用内存多。
* <p>Ex:
* <p>SoEasy soEasy=new SoEasy();//操作完后自动关闭数据库。
* <p>soEasy.addParmeter(2);
* <strong><p>List<Map> list=soEasy.getMapList("select * from news,newstype
* where newtype.id=news.type and news.type=?");</strong>
*
* @param sql
* @return
*/
public List<Map> getMapList(String sql) {
if (super.isFilter()) {
super.getSql(sql);
sql = super.getSelectSQL();
}
List<Map> list = new ArrayList<Map>();
ResultSet rs = query(sql);
try {
ResultSetMetaData metaData = rs.getMetaData();
int columnCount = metaData.getColumnCount();
getColumn(metaData);
while (rs != null && rs.next()) {
Map map = new HashMap();
for (int i = 1; i <= columnCount; i++) {
map.put(metaData.getColumnName(i), rs.getObject(i));
}
list.add(map);
}
} catch (SQLException ex) {
LoggerManage.logger.getLogger("SoEasy查询数据出错\nsql:" + sql + "\n", ex);
} finally {
close();
}
return list;
}
public List<Map> getMapList(String sql, Pagger page) {
if (autoClearPrepare) {
delayClear = true;
}
if (autoClose) {//如果之前是自动关闭
delayClose = true;
}
if (super.isFilter()) {
super.getSql(sql);
sql = super.getSelectSQL();
page.setItems(getCount(sql));
} else {
page.setItems(getCount("select count(*) as count from (" + sql + ")hybcount"));
}
List<Map> mapList = getMapList(sql + " limit " + page.getTop() + "," + page.getSize());
return mapList;
}
public List<Map> getMapList(String sql, EasyUiJson page) {
if (autoClearPrepare) {
delayClear = true;
}
if (autoClose) {//如果之前是自动关闭
delayClose = true;
}
if (super.isFilter()) {
super.getSql(sql);
sql = super.getSelectSQL();
page.setTotal(getCount(sql));
} else {
page.setTotal(getCount("select count(*) as count from (" + sql + ")hybcount"));
}
List<Map> mapList = getMapList(sql + " limit " + page.getTop() + "," + page.getRows());
return mapList;
}
}