开发SSH时,往往写完PO类,设置好映射的数据库字段时,写对应的DAO的方法,再写所谓的DTO,设置好所有返回前前台的结果集,无谓就是省着写SQL了而已如果我直接在ACTION中写SQL去操作数据,查询出来的结果集直接通过封装好的JDBC方法按照字段名转换成JSON对象传递给前台,前台通过EXT去的STORE去解析对应的字段,这样完全可以省略PO DTO等等模式 如果不使用EXT,也可以传递到前台一个LIST,每条记录一个MAP,前台用过JSTL也是完全可以解析展示的。如果说没有写DAO层会造成一些复用的麻烦,也可以把所有的SQL方法写到一个DAO类中,完全也能够实现DAO操作相同数据库方法的复用个人觉得比写PO DTO啥的方便,而且HSQL写起来也不通俗 效率也低,一些复杂的SQL往往还不支持

解决方案 »

  1.   

    我也曾经考虑这样做,而且代码都写好了
    后来总结了一下,
    这样做可以省略不少代码,省了很多jar和框架,ssh通通不靠边了。
    但是这样做,失去了mvc模式,失去了面向对象的概念,不能很好的分层,后期维护很困难,
    不利于数据库移植,不灵活!我们目前是这样做的:
    根据模板连接数据库生成映射文件和实体类,自己封装了一个SqlUtil类,泛型操作,dao和service就不用了,一个servlet解决所有http请求,比如:SqlUtil<User> sqlUtil = new SqlUtil<User>();
    User user = new User();
    user.setName("张三");
    user = sqlUtil.insert(user);
    Long id = user.getId();
    user = sqlUtil.getById(id);
    user.setAge(20);
    user = sqlUtil.update(user);
    user = sqlUtil.delete(user.getId());
    List<User> users = sqlUtil.getDataList("select * from t_user where age >= ? order by id", new Object[] { user.getAge() });
    好好运用javax.sql.DataSource这个接口和连接池,合理利用缓存(cache),其效率比hibernate或ibatis 要高的多!
      

  2.   


    我这样说,可能会有很多人不认同,没关系,这只是个人观点。
    hibernate或ibatis我都用过,时间都不短,算是深有体会吧,但最终选择了jdbc,
    运行效率和灵活度最终取决于设计模式!
      

  3.   

    个人认为对于数据应该分为不变的数据、有限增长的数据、无限增长的数据。
    对于不变的数据(如某种数据库有多少个正式版本,各个版本有多少种字段类型),最好的方式是枚举,写死它,无论它有多复杂。
    对于有限增长的数据,应该尽量将这些数据的对象完全放进内存,比如直接描述物理设备的对象、城市对象等。
    对于无限增长的数据,应该按需求将这些数据部分缓存,根据用户的行为决定缓存的内容。我现在是自己实现了内存对象库,可以通过sql直接查询内存中的对象,如果要查询在内存中就能得到满足,就不需要去查询数据库,否则则从数据库补充需要的数据到内存对象库,并将不常用的对象抛弃,数据发生更新时将内存中的对象持久化至数据库。
      

  4.   

    这个想法很好!
    我是这样觉得的,ssh只是框架,框架其实是服务于业务的,那么也就是说什么样的业务决定要用什么样的框架。
    如果这样看的话,其实怎么做,做成什么样,不是由框架决定的,而是由业务决定的。
    所以,我们在设计系统或是产品技术框架的时候要综合考虑,技术体系的确定由方方面面决定。
    例如:产品的维护、产品性能、产品的扩展性等等。所以用什么样的层次来实现都没有问题,关键有产品决定。
    当然,一般ssh适合做大型的产品,模块化的需要有很强扩展性的产品,业务角度来看需要层次区分明确的产品。
    并且不光是使用数据持久还有文件持久地系统,业务逻辑处理相当多的产品。
    直接使用action处理数据,前台使用EXT等这样的框架是适合对业务逻辑不是很复杂或是不怎么需要业务逻辑处理的产品,直接和数据库打交道的产品特别适合使用这样的方法,不需要分那么多层。
    希望这些卓见可以帮到你!
      

  5.   

    根据具体情况具体分析,java web 本身就是适合大型项目,所以才那么多层次,如果小项目快速开发可以action-》dao
      

  6.   


    个人这么觉的的  
      1  首先数据库的移植的问题,除了部分通用的产品有数据库移植的需求,大部分的行业软件基本上数据库定下来就不会动了,我想估计80%的都不会动了吧
      2  大型项目分这么多层,我觉得是为了后期控制项目的复杂度和规范性,毕竟那么多人在同时开发。
      3  EXT是表现层 我个人觉得业务逻辑的处理还是放在后台比较好
      4  另外 面向对象的思想我觉得没必要那么拘泥,起始在设计数据库表的时候,就是在做对象的设计,代码中对应表的PO类,我觉得根本上并不是对象,而是在对对象操作的定义。
      

  7.   


    你的SqlUtil通过对象的映射简化了insert update的操作 实现了hibernate的部分功能能否分享出来学习
      

  8.   

    我极度怀疑这句话,就我个人的经验来说,越大越复杂的项目,hibernate越玩不转。
      

  9.   


    import java.lang.reflect.Method;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.ResultSetMetaData;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    import org.apache.log4j.Logger;
    import com.zl.common.entity.EntityBean;
    import com.zl.common.entity.Settled;
    import com.zl.view3d.Pager;/**
     * sql工具类, 经过多线程(5000个)测试, 该类线程安全,无并发,经比对,该类的运行效率比ibatis更胜一筹
     * */
    @SuppressWarnings("unchecked")
    public final class SqlUtil<T> {

    private static final Logger log = Logger.getLogger(SqlUtil.class);
    private Class entityClass = null;

    /**
     * 构造方法
     * @param entityClass
     */
    public SqlUtil(Class entityClass) {
    this.entityClass = entityClass;
    }

    /**
     * 获得当前的EntityBean
     * @return EntityBean
     */
    public EntityBean getEntity() {
    return Settled.ENTITY_MAP.get(entityClass.getName());
    }

    /**
     * 获得数据库连接
     * @return Connection
     */
    public Connection getConnection() {
    try {
    Connection connection = Settled.dataSource.getConnection();
    connection.setAutoCommit(true);
    return connection;
    } catch (Exception e) {
    e.printStackTrace();
    return null;
    }
    }

    /**
     * 获得预编译语句
     * @param connection 数据库连接
     * @param sql sql语句
     * @param args 参数列表
     * @return PreparedStatement
     */
    public PreparedStatement getPrepared(Connection connection, String sql, Object[] args) {
    PreparedStatement prepared = null;
    try {
    if (null != connection && null != sql) {
    prepared = connection.prepareStatement(sql);
    if (null != prepared) {
    if (null != args && args.length > 0) {
    for (int i = 0; i < args.length; i++) {
    prepared.setObject(i + 1, args[i]);
    }
    }
    }
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    return prepared;
    }

    /**
     * 获得结果集
     * @param prepared 预编译语句
     * @return ResultSet
     */
    public ResultSet getResultSet(PreparedStatement prepared) {
    ResultSet resultSet = null;
    try {
    if (null != prepared) {
    resultSet = prepared.executeQuery();
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    return resultSet;
    }

    /**
     * 关闭所有连接
     * @param connection 数据库连接
     * @param prepared 预编译语句
     * @param resultSet 结果集
     */
    public void closeAll(Connection connection, PreparedStatement prepared, ResultSet resultSet) {
    try {
    if (null != resultSet) {
    resultSet.close();
    resultSet = null;
    }
    if (null != prepared) {
    prepared.close();
    prepared = null;
    }
    if (null != connection && !connection.isClosed()) {
    connection.close();
    connection = null;
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    }

    /**
     * 操作数据库(增删改)
     * @param sql sql语句
     * @param args 参数列表
     * @return Integer
     */
    public Integer manage(String sql, Object[] args) {
    Integer result = 0;
    Connection connection = null;
    PreparedStatement prepared = null;
    try {
    connection = getConnection();
    prepared = getPrepared(connection, sql, args);
    log.info(sql);
    if (null != prepared) {
    result = prepared.executeUpdate();
    clearCacheList();
    }
    } catch (Exception e) {
    e.printStackTrace();
    } finally {
    closeAll(connection, prepared, null);
    }
    return result;
    }

    // 添加缓存
    private void setCacheList(String key, List list) {
    if (null != entityClass && null != list && list.size() <= 30) {
    key = entityClass.getName() + "_" + key;
    Settled.CACHE_LIST_ENTITY_MAP.put(key, list);
    }
    }

    // 取出缓存
    private List getCacheList(String key) {
    if (null != entityClass) {
    key = entityClass.getName() + "_" + key;
    List list = Settled.CACHE_LIST_ENTITY_MAP.get(key);
    return list;
    }
    return null;
    }

    // 根据条件清空集合缓存
    private void clearCacheList() {
    if (null != entityClass) {
    Object []array = Settled.CACHE_LIST_ENTITY_MAP.keySet().toArray();
    for (int i = 0; i < array.length; i++) {
    String key = (String) array[i];
    if (key.indexOf(entityClass.getName()) != -1) {
    Settled.CACHE_LIST_ENTITY_MAP.remove(key);
    }
    }
    }
    }

    /**
     * 从数据库中获得一列值
     * @param sql sql语句
     * @param args 参数列表
     * @return List
     */
    public List<String> getTeam(String sql, Object[] args) {
    List<String> result = getCacheList(sql + "_" + getArg(args));
    if (null != result) {
    return result;
    }
    result = new ArrayList<String>();
    Connection connection = null;
    PreparedStatement prepared = null;
    ResultSet resultSet = null;
    try {
    connection = getConnection();
    prepared = getPrepared(connection, sql, args);
    log.info(sql);
    resultSet = getResultSet(prepared);
    if (null != resultSet) {
    while (resultSet.next()) {
    result.add(resultSet.getString(1));
    }
    }
    } catch (Exception e) {
    e.printStackTrace();
    } finally {
    closeAll(connection, prepared, resultSet);
    }
    setCacheList(sql + "_" + getArg(args), result);
    return result;
    } /**
     * 从数据库中获得一个值
     * @param sql sql语句
     * @param args 参数列表
     * @return String
     */
    public String getValue(String sql, Object[] args) {
    List<String> list = getTeam(sql, args);
    return (list.size() > 0) ? list.get(0) : "";
    } /**
     * 判断真假(数据库是否有这个记录)
     * @param sql sql语句必须是select count(*) from ...
     * @param args 参数列表
     * @return Boolean
     */
    public Boolean validate(String sql, Object[] args) {
    Boolean result = false;
    try {
    String value = getValue(sql, args);
    if (!"".equals(value) && Integer.parseInt(value) > 0) {
    result = true;
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    return result;
    }

    /**
     * 获得对象数组
     * @param sql sql语句
     * @param args 参数列表
     * @param keys 取值的key
     * @return Object[]
     */
    public Object[] getArray(String sql, Object[] args, String[] keys) {
    Object[] array = new Object[] {};
    if (null != keys && keys.length > 0) {
    array = new Object[keys.length];
    Connection connection = null;
    PreparedStatement prepared = null;
    ResultSet resultSet = null;
    try {
    connection = getConnection();
    prepared = getPrepared(connection, sql, args);
    log.info(sql);
    resultSet = getResultSet(prepared);
    if (null != resultSet && resultSet.next()) {
    for (int i = 0; i < keys.length; i++) {
    array[i] = resultSet.getObject(keys[i]);
    }
    }
    } catch (Exception e) {
    e.printStackTrace();
    } finally {
    closeAll(connection, prepared, resultSet);
    }
    }
    return array;
    }

    /**
     * 获得对象数组的集合
     * @param sql sql语句
     * @param args 参数列表
     * @param keys 取值的key
     * @return List
     */
    public List<Object[]> getArrayList(String sql, Object[] args, String[] keys) {
    List<Object[]> list = getCacheList(sql + "_" + getArg(args) + "_" + getArg(keys));
    if (null != list) {
    return list;
    }
    list = new ArrayList<Object[]>();
    if (null != keys && keys.length > 0) {
    Connection connection = null;
    PreparedStatement prepared = null;
    ResultSet resultSet = null;
    try {
    connection = getConnection();
    prepared = getPrepared(connection, sql, args);
    log.info(sql);
    resultSet = getResultSet(prepared);
    if (null != resultSet) {
    while (resultSet.next()) {
    Object[] array = new Object[keys.length];
    for (int i = 0; i < keys.length; i++) {
    array[i] = resultSet.getObject(keys[i]);
    }
    list.add(array);
    }
    }
    } catch (Exception e) {
    e.printStackTrace();
    } finally {
    closeAll(connection, prepared, resultSet);
    }
    }
    setCacheList(sql + "_" + getArg(args) + "_" + getArg(keys), list);
    return list;
    }
    /**
     * 获得表的所有字段
     * @param table 表名
     * @return String
     */
    public String getColumns(String table) {
    List<String> list = getTeam("select COLUMN_NAME from USER_TAB_COLUMNS where TABLE_NAME = ?", new Object[] { table });
    String json = "[";
    for (int i = 0; i < list.size(); i++) {
    json += "\"" + columnLower(list.get(i)) + "\"";
    if (i != list.size() - 1) {
    json += ",";
    }
    }
    json += "]";
    return json;
    }
    /**
     * 获得JSONArray格式的字符串
     * @param sql sql语句
     * @param args 参数列表
     * @return String
     */
    public String getJson(String sql, Object[] args) {
    StringBuffer json = new StringBuffer("[");
    Connection connection = null;
    PreparedStatement prepared = null;
    ResultSet resultSet = null;
    try {
    connection = getConnection();
    prepared = getPrepared(connection, sql, args);
    log.info(sql);
    resultSet = getResultSet(prepared);
    if (null != resultSet) {
    ResultSetMetaData metaData = resultSet.getMetaData();
    while (resultSet.next()) {
    json.append("{");
    for (int i = 1; i <= metaData.getColumnCount(); i++) {
    String value = resultSet.getString(metaData.getColumnName(i));
    json.append(columnLower(metaData.getColumnName(i)) + ":\"" + (null != value ? value : "") + "\"");
    if (i != metaData.getColumnCount()) {
    json.append(",");
    }
    }
    json.append("},");
    }
    }
    } catch (Exception e) {
    e.printStackTrace();
    } finally {
    closeAll(connection, prepared, resultSet);
    }
    json = json.length() > 1 ? json.replace(json.length() - 1, json.length(), "") : json;
    json.append("]");
    return json.toString();
    }
    /**
     * 字段转小写(驼峰命名法)
     * @param value 字段
     * @return String
     */
    public String columnLower(String value) {
    if (value.indexOf("_") != -1) {
    String []arr = value.split("_");
    String str = "";
    for (int i = 0; i < arr.length; i++) {
    if (i == 0) {
    str += arr[i].toLowerCase();
    } else {
    String qian = arr[i].substring(0, 1).toUpperCase();
    String hou = arr[i].substring(1, arr[i].length()).toLowerCase();
    str += qian + hou;
    }
    }
    return str;
    }
    return value.toLowerCase();
    }
      

  10.   


    /**
     * 封装数据
     * @param sql sql语句
     * @param args 参数列表
     * @return List
     * */ 
    public List<T> getDataList(String sql, Object[] args) {
    List list = getCacheList(sql + "_" + getArg(args));
    if (null != list) {
    return list;
    }
    list = new ArrayList();
    Connection connection = null;
    PreparedStatement prepared = null;
    ResultSet resultSet = null;
    try {
    connection = getConnection();
    prepared = getPrepared(connection, sql, args);
    log.info(sql);
    resultSet = getResultSet(prepared);
    EntityBean bean = getEntity();
    while (resultSet.next()) {
    T object = (T) entityClass.newInstance();
    for (String property : bean.getPropertyMap().keySet()) {
    ReflectUtil.setPropertyValue(object, property, resultSet.getString(bean.getPropertyMap().get(property)));
    }
    if (null != getEntity().getIdColumn() && null != getEntity().getIdName()) {
    String idValue = resultSet.getString(bean.getIdColumn());
    ReflectUtil.setPropertyValue(object, bean.getIdName(), idValue);
    Settled.CACHE_ID_ENTITY_MAP.put(getEntity().getClassName() + "_" + idValue, object);
    }
    list.add(object);
    }
    } catch (Exception e) {
    e.printStackTrace();
    } finally {
    closeAll(connection, prepared, resultSet);
    }
    setCacheList(sql + "_" + getArg(args), list);
    return list;
    }

    // 把参数列表拼接成字符串
    private String getArg(Object[] args) {
    if (null != args && args.length > 0) {
    String arg = "";
    for (int i = 0; i < args.length; i++) {
    if (null != args[i]) {
    arg += args[i].toString() + ",";
    }
    }
    return arg;
    }
    return "";
    }

    /**
     * 查询部分实体集合
     * @param sql sql语句
     * @param args 参数列表
     * @param num 实体的个数
     * @return List
     */
    public List<T> getListPart(String sql, Object[] args, int num) {
    List list = getCacheList(sql + "_" + getArg(args) + "_" + num);
    if (null != list) {
    return list;
    }
    list = new ArrayList();
    Connection connection = null;
    PreparedStatement prepared = null;
    ResultSet resultSet = null;
    try {
    connection = getConnection();
    prepared = getPrepared(connection, sql, args);
    log.info(sql);
    resultSet = getResultSet(prepared);
    EntityBean bean = getEntity();
    int i = 0;
    while (resultSet.next()) {
    i++;
    if (i <= num) {
    T object = (T) entityClass.newInstance();
    for (String property : bean.getPropertyMap().keySet()) {
    ReflectUtil.setPropertyValue(object, property, resultSet.getString(bean.getPropertyMap().get(property)));
    }
    if (null != getEntity().getIdColumn() && null != getEntity().getIdName()) {
    String idValue = resultSet.getString(bean.getIdColumn());
    ReflectUtil.setPropertyValue(object, bean.getIdName(), idValue);
    Settled.CACHE_ID_ENTITY_MAP.put(getEntity().getClassName() + "_" + idValue, object);
    }
    list.add(object);
    } else {
    break;
    }
    }
    } catch (Exception e) {
    e.printStackTrace();
    } finally {
    closeAll(connection, prepared, resultSet);
    }
    setCacheList(sql + "_" + getArg(args) + "_" + num, list);
    return list;
    }

    /**
     * 查询单个实体
     * @param sql sql语句
     * @param args 参数列表
     * @return Object
     */
    public T getObject(String sql, Object[] args) {
    List list = getDataList(sql, args);
    return (list.size() > 0) ? (T) list.get(0) : null;
    }

    /**
     * 获得表中的下一个ID的值
     * @return Long
     */
    public Long getNextId() {
    Long result = 0l;
    try {
    String sql = "select max(" + getEntity().getIdColumn() + ") from " + getEntity().getTableName();
    String value = getValue(sql, null);
    if (null != value && !"".equals(value)) {
    result = Long.parseLong(value) + 1;
    } else {
    result = 1l;
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    return result;
    }

    /**
     * 保存记录
     * @param entity 实体
     * @return Object
     * */
    public T insert(T entity) {
    EntityBean bean = getEntity();
    String idValue = null;
    List<Object> args = new ArrayList<Object>();
    String sql = "insert into " + bean.getTableName() + " (", columnSql = "", paramSql = "";;
    for (String property : bean.getPropertyMap().keySet()) {
    Object value = ReflectUtil.getPropertyValue(entity, property);
    if (null != value) {
    columnSql += bean.getPropertyMap().get(property) + ", ";
    if (Settled.DATE_CLASS.equals(value.getClass().getName())) {
    paramSql += "to_date('" + Settled.formatDateTime().format((Date) value) + "', 'yyyy-mm-dd hh24:mi:ss'), ";
    } else {
    paramSql += "?, ";
    args.add(value.toString());
    }
    }
    }
    sql += (columnSql.length() > 0 ? columnSql.substring(0, columnSql.length() - 2) : columnSql);
    if (EntityBean.ID_CREATE_CUSTOM.equals(bean.getIdCreate()) || EntityBean.ID_CREATE_SEQUENCE.equals(bean.getIdCreate())) {
    sql += ", " + bean.getIdColumn();
    idValue = (EntityBean.ID_CREATE_CUSTOM.equals(bean.getIdCreate()) ? (String) ReflectUtil.getPropertyValue(entity, bean.getIdName()) : getValue("select " + bean.getIdSequence() + ".Nextval from dual", null));
    args.add(idValue);
    }
    sql += ") values (";
    sql += (paramSql.length() > 0 ? paramSql.substring(0, paramSql.length() - 2) : paramSql);
    if (EntityBean.ID_CREATE_CUSTOM.equals(bean.getIdCreate()) || EntityBean.ID_CREATE_SEQUENCE.equals(bean.getIdCreate())) {
    sql += ", ?";
    }
    sql += ")";
    manage(sql, args.toArray());
    if (EntityBean.ID_CREATE_NATIVE.equals(bean.getIdCreate())) {
    idValue = String.valueOf(getNextId() - 1);
    }
    ReflectUtil.setPropertyValue(entity, bean.getIdName(), idValue);
    Settled.CACHE_ID_ENTITY_MAP.put(bean.getClassName() + "_" + idValue, entity);
    return (T) entity;
    }

    /**
     * 删除记录
     * @param id 实体的ID
     * @return Object
     * */
    public T delete(Serializable id) {
    T entity = get(id);
    String sql = "delete from " + getEntity().getTableName() + " where " + getEntity().getIdColumn() + " = ?";
    manage(sql, new Object[]{ id });
    Settled.CACHE_ID_ENTITY_MAP.remove(getEntity().getClassName() + "_" + id);
    return (T) entity;
    }

    /**
     * 修改记录
     * @param entity 实体
     * @return Object
     * */
    public T update(T entity) {
    EntityBean bean = getEntity();
    List<Object> args = new ArrayList<Object>();
    String sql = "update " + bean.getTableName() + " set";
    for (String property : bean.getPropertyMap().keySet()) {
    Object value = ReflectUtil.getPropertyValue(entity, property);
    if (null != value) {
    if (Settled.DATE_CLASS.equals(value.getClass().getName())) {
    sql += " " + bean.getPropertyMap().get(property) + " = to_date('" + Settled.formatDateTime().format((Date) value) + "', 'yyyy-mm-dd hh24:mi:ss'),";
    } else {
    sql += " " + bean.getPropertyMap().get(property) + " = ?,";
    args.add(value.toString());
    }
    }
    }
    sql = sql.substring(0, sql.length() - 1);
    sql += " where " + bean.getIdColumn() + " = ?";
    String idValue = String.valueOf(ReflectUtil.getPropertyValue(entity, bean.getIdName()));
    args.add(idValue);
    manage(sql, args.toArray());
    return resetEditCache(entity, idValue);
    }

    // 修改记录是更新缓存
    private T resetEditCache(T entity, String idValue) {
    try {
    EntityBean bean = getEntity();
    T object = (T) Settled.CACHE_ID_ENTITY_MAP.get(bean.getClassName() + "_" + idValue);
    if (null != object) {
    for (String property : bean.getPropertyMap().keySet()) {
    Object value = ReflectUtil.getPropertyValue(entity, property);
    if (null != value) {
    Method method = object.getClass().getMethod(ReflectUtil.getMethodName(property, "set"), value.getClass());
    method.invoke(object, value);
    }
    }
    Settled.CACHE_ID_ENTITY_MAP.put(bean.getClassName() + "_" + idValue, object);
    return (T) object;
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    return get(idValue);
    }

    /**
     * 根据ID获得记录
     * @param id 实体的ID
     * @return Object
     * */
    public T getById(Serializable id) {
    if (null != Settled.CACHE_ID_ENTITY_MAP.get(getEntity().getClassName() + "_" + id)) {
    return (T) Settled.CACHE_ID_ENTITY_MAP.get(getEntity().getClassName() + "_" + id);
    }
    String sql = "select * from " + getEntity().getTableName() + " where " + getEntity().getIdColumn() + " = ?";
    T entity = getObject(sql, new Object[]{ id });
    Settled.CACHE_ID_ENTITY_MAP.put(getEntity().getClassName() + "_" + id, entity);
    return (T) entity;
    }

    /**
     * 获得表中的所有的实体
     * @return List
     */
    public List<T> getBeans() {
    String order = (null != getEntity().getIdColumn() ? " order by " + getEntity().getIdColumn() : "");
    String sql = "select * from " + getEntity().getTableName() + order;
    return getDataList(sql, null);
    }

    // 获得分页
    private Pager<T> pagination(String numSql, Object[] args, int pageNo, int pageSize) {
    try {
    Pager pager = new Pager(pageNo, pageSize);
    pager.setTotalCount(Integer.parseInt(getValue(numSql, args)));
    return pager;
    } catch (Exception e) {
    e.printStackTrace();
    }
    return new Pager();
    }

    /**
     * 获得分页
     * @param sql 查询数据数量的sql必须是select * from 开头
     * @param args 参数列表(可以为null)
     * @param pageNo 当前页数
     * @param pageSize 分页的基数
     * @return Pager
     * */
    public Pager<T> getPage(String sql, Object[] args, int pageNo, int pageSize) {
    args = (null == args ? new Object[] {} : args);
    Pager pager = pagination(sql.replace("*", "count(*)"), args, pageNo, pageSize); 
    Object[] newArgs = new Object[args.length + 2];
    for (int i = 0; i < args.length; i++) {
    newArgs[i] = args[i];
    }
    sql = "select * from ( select temp.*, rownum rownumt from (" + sql + ") temp where rownum <= ?) where rownumt > ?";
    newArgs[newArgs.length - 2] = pager.getSkipResults() + pageSize;
    newArgs[newArgs.length - 1] = pager.getSkipResults();
    pager.setList(getDataList(sql, newArgs));
    return pager;
    }

    }
      

  11.   


    这些方法是必须泛型才能调用的,差不多每个方法需要提供两个参数: sql语句和参数列表,
    基本上可以满足日常操作了,
    增删改操作的事物默认设置为自动提交,如果需要手动提交,只能重写jdbc代码。
    以上代码如果有不足之处,还请多多指教哈!
    希望各位大侠多提宝贵意见,在下必会虚心接受!
      

  12.   

    楼主说的也是有道理的确实数据库持久层是否需要一些流行的框架有待考虑json确实不错。
      

  13.   

    分层,框架,设计模式等等  都是要根据实际需求来决定的我的需求你这样没发解决我的 moudel的数据来源不局限于 DB  还有可能是文件,是webservice等其他接口分层就是 service 我只调用了 dao的接口  但是 数据实际的来源DB也好文本也好 都是根据当时程序里拿到的具体实现来做到的如果用你这套东西 ,其实增加了开发工作
      

  14.   


    这位同学问的很好,如果有多个数据库,只要稍微改改就好了。
    首先建一个实体类:JdbcConfig:
    /** 数据库类型为:oracle */
    public static final String DATABASE_ORACLE = "oracle";

    /** 数据库类型为:mysql */
    public static final String DATABASE_MYSQL = "mysql";

    /** 数据库类型为:sqlserver */
    public static final String DATABASE_SQLSERVER = "sqlserver";

    private static final long serialVersionUID = 1L;
    private DataSource dataSource;// 数据源
    private String jdbcFolder;// 实体类和表结构的映射文件目录
    private Boolean showSql;// 是否显示sql语句
    private String databaseType;// 数据库类型(暂时支持oracle,mysql,sqlserver三种)
    private Boolean createSqlFile;// 是否生成创建表结构的sql语句(如果为true,将会在classes根目录生成sql文件)
    private Map<String, EntityBean> entityMap;// 包含的EntityBean, EntityBean中包含了实体类和表的映射关系
    /**set和get方法就省略了**/假如项目要连接这三个数据库,在项目启动的时候,想办法初始化三个JdbcConfig,设置为静态变量,保存在内存中。
    再修改SqlUtil的代码private JdbcConfig jdbcConfig = null;
    private Class entityClass = null;
    private EntityBean entityBean = null;
         
        /**
         * 构造方法
         * @param entityClass
         */
        public SqlUtil(JdbcConfig jdbcConfig, Class entityClass) {
            if (null == jdbcConfig || null == entityClass) {
                //做异常处理
            }
            this.jdbcConfig = jdbcConfig;
            this.entityClass = entityClass;
            EntityBean entity = this.jdbcConfig.getEntityMap().get(entityClass.getName());
            if (entity != null) {
                this.entityBean = entity;
            } else {
                // jdbcConfig没有要包含这个entityClass,或者说表和数据库没扯上关系,做异常处理
            }
        }
         
        /**
         * 获得当前的EntityBean
         * @return EntityBean
         */
        public EntityBean getEntity() {
            return entityBean;
        }
         
        /**
         * 获得数据库连接
         * @return Connection
         */
        public Connection getConnection() {
            try {
                Connection connection = jdbcConfig.getDataSource().getConnection();
                connection.setAutoCommit(true);
                return connection;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }这样做的可以让SqlUtil根据不同的JdbcConfig获得不同的Connection,找到对应的实体和库表再操作,
    insert,update和分页是SqlUtil自动生成的sql,可以写点判断语句,根据jdbcConfig.getDatabaseType()生成与数据库对应的sql,确保万无一失。这是一个简单的SqlUtil工具类,只能满足单表的增删改查,要想解决多表主外键关系的话,dao数据层还是少不了的呀,有了数据层,就要考虑注入了。只要你掌握好java反射机制,这些都是小问题。
    让人头疼的是三个数据库的事物不好统一管理,所以还得研究spring
      

  15.   

    当项目大了,分模块来做,好维护,代码结构也清晰,需要修改什么地方都很容易写到文档里,如果整个源码里到处是SQL语句,例如某个表的字段修改了,而这个表在代码的SQL里有好多地方都用到,这个时候哭都哭不出来呢。
    分模块还易于测试。
    像MySQL的Mapper还能提供编译期检测,好处很多,利大于弊。
      

  16.   

    像MyBatis的Mapper还能提供编译期检测,好处很多,利大于弊。
      

  17.   


    这里写错了,应该是:SqlUtil<User> sqlUtil = new SqlUtil<User>(User.class);
    不好意思哈!
      

  18.   


    是的,到处是sql语句,自己看到也难过,别人就更加难维护了。
    我们通常把sql语句写在.xml(一张表一个xml)文件中,在项目启动的时候,想办法读一下xml,把sql语句加载到Map,或者说内存中,要用的时候去Map取。但有时候需要动态拼接sql,只好根据需要再写一个util工具类.
      

  19.   


    无论数据的来源是文件 数据库 还是SOCKET接口等等
    只是获取的方式不同,最终数据还是可以整理成list/map的形式返回前台
    无非多封装几个方法罢了
    况且这个h照样也搞不定  照样还是要自己去实现
      

  20.   

    这样搞到最后  基本上就在自己实现h或者batis实现的功能了,只是在实现上比用别人的东西更加的灵活
      

  21.   

    你说的很对,hibernate本身就不是为大型产品来服务的,hibernate是一个好东西,但是它只适合数据库结构超好,超符合范式的那种,一般约束关系很强并且结构很好的数据库结构,这种情况下它可以起到相当好的效果,对开发者来说是一个很好的东西。但是它的缓存机制如果不能深入理解就使用的话,它就会让你死的很惨。
      

  22.   

    LZ  再次跟你书说一下 DAO 层 是数据访问层 在这一层不仅仅局限于数据库我先声明一下不是说你代码写的不好,也不是说你的想法有什么问题在一个小的增删查改的数据库项目中,你这样方式没什么问题但是在一个大的应用系统中,分层不仅仅是为了分工,开发人员各负责一层互不影响。分层更多的是为了系统功能的调整,扩展,维护。合理的分层结构,可以为你的软件开发的整个生命周期提供很好的支撑。
    我这里说的意思,不是说你写的sql工具有什么问题,也不是返回的map也好list也好这都没什么关系,
    我是说你在action中直接去写逻辑,哪怕是简单的增删改查,这样带来的后果就是,页面严重和数据层耦合了,真是牵一发而动全身了。
      

  23.   

    这几天看了回帖  也看来下其他版块,像NET版块啥的 也有人对此有疑惑我觉得可能和我以前写的程序或者项目的规模有关系以前写的程序,基本上都是面向过程,或者面向交易,数据用个结构体传来传去的 或者XML字符串啥的
    虽然对我看来,无论结构体还是字符串还是实体类,基本上都是一样的,或者实现的结果都是一样的,
    前台发起交易,构造出基本的数据,后台校验数据,最终操作数据库。
    而且项目规模小,基本上就10-20张表。
    所以,我更倾向于开发的时候更加直接高效的写代码。今天看到一个老帖,有人提出了个问题,先有实体类还是先有表。我觉得这个可能是我疑惑的根源,或者是面向对象的理解不透彻吧。上面讨论的有几点我承认,按照我的想法,
    确实造成表字段修改的地方不集中,很麻烦;SQL写的到处都是很不简洁
    这也是我想解决的问题,所以才想到和大家进行讨论