手擼一個簡單的ORM工具

ORM工具類

package per.nonoas.orm;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
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.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public abstract class MyOrmUtil<T> {

    /**
     * 查詢一條數據
     *
     * @param sql    執行的SQL語句
     * @param params SQL語句佔位符值
     * @return Class &lt;T> 的實例對象,沒有查詢結果時返回null
     */
    final protected T selectOne(String sql, Object... params) {
        T t = null;
        Connection conn = getConnection();
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = conn.prepareStatement(getSql(sql)); // 將#{}佔位符替換爲?
            for (int i = 0; i < params.length; i++) {
                ps.setObject(i + 1, params[i]);
            }
            rs = ps.executeQuery();
            if (rs.next())
                t = mapToBean(rs, getBeanClass());
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (ps != null)
                    ps.close();
                if (rs != null)
                    rs.close();
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return t;
    }

    /**
     * 查詢多條數據
     *
     * @param sql    執行的SQL語句
     * @param params SQL語句佔位符值
     * @return Bean對象的List集合, 無查詢結果時返回null
     */
    final protected List<T> select(String sql, Object... params) {
        List<T> list = new ArrayList<>(8);
        Connection conn = getConnection();
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = conn.prepareStatement(getSql(sql)); // 將#{}佔位符替換爲?
            for (int i = 0; i < params.length; i++) {
                ps.setObject(i + 1, params[i]);
            }
            rs = ps.executeQuery();
            while (rs.next()) // 將查詢結果加入list
                list.add(mapToBean(rs, getBeanClass()));
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (ps != null)
                    ps.close();
                if (rs != null)
                    rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (list.size() == 0)
            return null;
        return list;
    }

    /**
     * 向數據庫插入數據
     *
     * @param sql 傳入的帶#{}通配符的SQL語句
     * @param t   傳入的泛型Bean類
     */
    final protected void insert(String sql, T t) {
        try {
            beanToDataBase(sql, t);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 向數據庫更新內容
     *
     * @param sql 傳入的帶#{}通配符的SQL語句
     * @param t   傳入的泛型Bean類
     */
    final protected void update(String sql, T t) {
        try {
            beanToDataBase(sql, t);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 向數據庫刪除內容
     *
     * @param sql 傳入的帶#{}通配符的SQL語句
     * @param t   傳入的泛型Bean類
     */
    final protected void delete(String sql, T t) {
        try {
            beanToDataBase(sql, t);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 映射一條數據到Bean中
     *
     * @param rs        ResultSet對象
     * @param beanClass Bean對象
     * @return 返回一個不爲空的Bean對象
     */
    private T mapToBean(ResultSet rs, Class<T> beanClass) {
        List<String> list = getColumnNames(rs); // 結果集中所有表名
        T t = null; // 創建泛型實例對象
        try {
            t = beanClass.newInstance();
            for (String colName : list) {
                String methodName = "set" + firstUpperCase(colName); // 獲取方法名
                Field field = beanClass.getDeclaredField(colName); // 獲取字段名
                Class<?> type = field.getType(); // 獲取字段類型
                Object value = rs.getObject(colName); // 獲取傳入值
                Method method = beanClass.getDeclaredMethod(methodName, type);
                // 類型轉換
                if (value != "" && value != null) {
                    if (value.getClass().getSimpleName().equals("BigDecimal") // 值不爲空時,轉換BigDecimal爲Integer類型
                            && type.toString().equals("class java.lang.Integer")) {
                        value = Integer.parseInt(value.toString());
                    }
                } else {
                    field.getType().cast(value);// 如果爲空,直接轉換類型
                }
                method.invoke(t, value); // 調用set方法
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return t;
    }

    /**
     * 將傳入的泛型Bean中的字段賦值給SQL語句中的佔位符,並執行他們
     *
     * @param sql 帶#{}通配符的SQL語句
     * @param t   泛型Bean對象
     * @throws SQLException 數據庫異常
     */
    private void beanToDataBase(String sql, T t) throws SQLException {
        Class<?> beanClass = t.getClass();
        List<String> list = getParms(sql);
        sql = getSql(sql); // 將SQL中的#{}佔位符改爲?
        Connection con = getConnection();
        PreparedStatement ps = null;
        try {
            ps = con.prepareStatement(sql);
            for (int i = 0; i < list.size(); i++) {
                String colnName = list.get(i);
                String methodName = "get" + firstUpperCase(colnName); // 方法名
                Method method = beanClass.getDeclaredMethod(methodName);
                Object value = method.invoke(t);
                ps.setObject(i + 1, value);
            }
            ps.execute();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } finally {
            if (ps != null)
                ps.close();
            con.close();
        }
    }

    /**
     * 獲取所有查詢的列名
     *
     * @param rs ResultSet對象
     * @return 列名的List集合
     */
    private List<String> getColumnNames(ResultSet rs) {
        List<String> list = new ArrayList<>(8);
        ResultSetMetaData rsm;
        int columnCount;
        try {
            rsm = rs.getMetaData();
            columnCount = rsm.getColumnCount();
            for (int i = 0; i < columnCount; i++) {
                list.add(rsm.getColumnName(i + 1)); // 獲取列名,並添加到list集合
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 獲取所有需要傳遞的參數列名<br>
     * 例如輸入:"insert into user(id,name) value(#{id},#{name})"<br>
     * 返回:"[id,name]"
     *
     * @param sql 傳入的SQL語句(帶#{}通配符)
     * @return 傳遞參數列名的List集合,不爲null
     */
    private List<String> getParms(String sql) {

        List<String> list = new ArrayList<>(8);
        Pattern p = Pattern.compile("[#]\\{\\w*[}]");
        Matcher m = p.matcher(sql);
        while (m.find()) {
            String str = m.group();
            String column = str.substring(2, m.group().length() - 1); // 獲取列名
            list.add(column);
        }
        return list;
    }

    /**
     * 首字母大寫
     *
     * @param str 傳入的字符串,如“name”
     * @return 首字母大寫的字符串,如“Name”
     */
    private String firstUpperCase(String str) {
        return str.substring(0, 1).toUpperCase() + str.substring(1);
    }

    /**
     * 將SQL語句中的#{}替換成"?"
     *
     * @param sql 帶#{}的SQL語句
     * @return 帶?的SQL語句
     */
    private String getSql(String sql) {
        return sql.replaceAll(("[#]\\{\\w*[}]"), "?");
    }

    /**
     * 獲取數據庫連接對象
     *
     * @return Connection對象
     */
    protected abstract Connection getConnection();

    /**
     * @return T的class屬性
     */
    protected abstract Class<T> getBeanClass();
}

DAO抽象類

package indi.nonoas.crm.dao;

import java.sql.Connection;

import indi.nonoas.crm.utils.DBopener;
import per.nonoas.orm.MyOrmUtil;

/**
 * Dao層父類
 * 
 * @author Nonoas
 * @param <T> Bean類泛型
 */
public abstract class MyDao<T> extends MyOrmUtil<T> {

	@Override
	protected Connection getConnection() {
		return DBopener.getConnection();
	}

	@Override
	protected abstract Class<T> getBeanClass();

}

使用案例

package indi.nonoas.crm.dao;

import java.util.ArrayList;

import indi.nonoas.crm.bean.GoodsBean;

/**
 * 商品信息的DAO
 * 
 * @author Nonoas
 *
 */
public class GoodsDao extends MyDao<GoodsBean> {

	private static final String SELECT_ALL = "select * from goods_info";
	private static final String SELECT_BY_FILTRATE = "select * from goods_info where (id like #{id} or name like #{name}) and type like #{type}";
	private static final String INSERT_INFO = "insert into goods_info(id,name,sell_price,purchas_price,quantity,min_discount,deduction,deduction_rate,base_unit,type,photo) "
			+ "values(#{id},#{name},#{sell_price},#{purchas_price},#{quantity},#{min_discount},#{deduction},#{deduction_rate},#{base_unit},#{type},#{photo})";
	private static final String DELETE_BY_ID = "delete from goods_info where id=#{id}";
	private static final String UPDATE = "update goods_info set name=#{name},sell_price=#{sell_price},purchas_price=#{purchas_price},quantity=#{quantity},min_discount=#{min_discount},deduction=#{deduction},deduction_rate=#{deduction_rate},base_unit=#{base_unit},type=#{type},photo=#{photo} where id=#{id}";
//	private static final String 

	private static final GoodsDao INSTANCE = new GoodsDao();

	private GoodsDao() {
	}

	public static GoodsDao getInstence() {
		return INSTANCE;
	}

	/**
	 * 查詢所有的商品信息
	 * 
	 * @return GoodsBean的ArrayList集合,可爲null
	 */
	public ArrayList<GoodsBean> selectAll() {
		ArrayList<GoodsBean> list = null;
		list = (ArrayList<GoodsBean>) select(SELECT_ALL);
		return list;
	}

	/**
	 * 按條件篩選模糊查詢
	 * 
	 * @param id   商品編號
	 * @param name 商品名稱
	 * @param type 商品種類
	 * @return GoodsBean的ArrayList集合,可以爲null
	 */
	public ArrayList<GoodsBean> selectByFiltrate(String id, String name, String type) {
		ArrayList<GoodsBean> list = null;
		list = (ArrayList<GoodsBean>) select(SELECT_BY_FILTRATE, id, name, type);
		return list;
	}

	/**
	 * 刪除一條商品信息
	 * 
	 * @param bean GoodsBean對象
	 */
	public void deleteByID(GoodsBean bean) {
		delete(DELETE_BY_ID, bean);
	}

	/**
	 * 插入一條商品信息
	 * 
	 * @param bean GoodsBean對象
	 */
	public void insertInfo(GoodsBean bean) {
		insert(INSERT_INFO, bean);
	}

	/**
	 * 更新商品信息
	 * 
	 * @param goodsBean GoodsBean對象
	 */
	public void update(GoodsBean goodsBean) {
		update(UPDATE, goodsBean);
	}

	@Override
	protected Class<GoodsBean> getBeanClass() {
		return GoodsBean.class;
	}

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章