用Java反射機制模擬hibernateJDBC操作

yuan22003發表於2011-08-28
package org.keyuan.resolve;

import java.lang.annotation.Annotation;
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.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;

import org.apache.commons.beanutils.BeanUtils;
import org.keyuan.entity.Student;
import org.keyuan.util.DBConnectionUtil;

/**
 * 
 * 說明:使用java的反射機制模擬hibernate的session
 * 
 * @author KeYuan
 * 
 */
public class Session {
    private Connection conn = null;
    /**
     * 新增操作
     */
    public boolean save(Object entity) throws SecurityException,
            NoSuchMethodException, IllegalArgumentException,
            IllegalAccessException, SQLException, ClassNotFoundException {
        StringBuffer insertSql = new StringBuffer("insert into ");
        StringBuffer insertSqlValue = new StringBuffer();
        LinkedList<Object> insertParams = new LinkedList<Object>();
        Class<?> entityClass = entity.getClass();
        String tableName = getTableName(entityClass);
        insertSql.append(tableName);
        Field[] fields = entityClass.getDeclaredFields();
        insertSql.append("(");
        insertSqlValue.append(" values(");
        for (Field field : fields) {
            Annotation[] annotations = field.getAnnotations();
            String columnName = field.getName();
            // 查詢當前屬性上面是否有annotation註解
            Object[] findAnnotationResult = findAnnotation(annotations);
            Boolean isAnnotaionOverField = (Boolean) findAnnotationResult[0];
            // 如果在field中上面沒有找到annotation,繼續到get屬性上去找有沒有annotation
            if (!isAnnotaionOverField) {
                // 拼接出field的get屬性名
                String getMethodName = "get"
                        + columnName.substring(0, 1).toUpperCase()
                        + columnName.substring(1);
                Method method = entityClass.getMethod(getMethodName,
                        new Class[] {});
                // 同上判斷這個方法有沒有我們要找的annotation
                annotations = method.getAnnotations();
                findAnnotationResult = findAnnotation(annotations);
                isAnnotaionOverField = (Boolean) findAnnotationResult[0];
            }
            // 判斷通過前面兩步操作有沒有在當前的欄位上面找到有效的annotation
            if (!isAnnotaionOverField)
                continue;
            // 到這步說明在當前的欄位或欄位get屬性上面找到有效的annotation了
            // 拼接insert sql 語句
            String tempColumnName = (String) findAnnotationResult[1];
            if (tempColumnName != null && !"".equals(tempColumnName))
                columnName = tempColumnName;
            insertSql.append(columnName).append(",");// 前面列名部分
            insertSqlValue.append("?,"); // 後面?引數部分
            // 得到對應的欄位值並記錄,作為以後?部分值
            field.setAccessible(true);
            insertParams.add(field.get(entity));
        }
        insertSql.replace(insertSql.lastIndexOf(","), insertSql.length(), ")");
        insertSqlValue.replace(insertSqlValue.lastIndexOf(","), insertSqlValue
                .length(), ")");
        // 拼接兩部分的sql
        insertSql.append(insertSqlValue);
        System.out.println(insertSql);
        // 執行新增操作了
        conn = DBConnectionUtil.getConnection();
        PreparedStatement prep = conn.prepareStatement(insertSql.toString());
        int i = 1;
        for (Object param : insertParams) {
            if (param instanceof Date) {
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
                java.sql.Date date = java.sql.Date.valueOf(dateFormat
                        .format(param));
                prep.setDate(i, date);
            } else {
                prep.setObject(i, param);
            }
            i++;
        }
        if (prep.executeUpdate() > 0)
            return true;
        return false;
    }
    /**
     * 得到表的真實名
     */
    private String getTableName(Class<?> entityClass) {
        String tableName = entityClass.getSimpleName();
        if (entityClass.isAnnotationPresent(Entity.class)) {
            Entity entityAnnotation = entityClass.getAnnotation(Entity.class);
            String tempTableName = entityAnnotation.name();
            if (tempTableName != null && !"".equals(tempTableName))
                tableName = tempTableName;
        }
        return tableName;
    }
    /**
     * 查詢欄位或是屬性上面有沒有有效annotation
     */
    private Object[] findAnnotation(Annotation[] annotations) {
        Object[] resurlt = new Object[] { false, null };
        if (annotations.length == 0)
            return resurlt;
        for (Annotation annotation : annotations) {
            // 我們假定當他找到下列標籤中任何一個標籤就認為是要與資料庫對映的
            if (annotation instanceof Column) {
                resurlt[0] = true;
                Column column = (Column) annotation;
                String tempColumnName = column.name();
                if (tempColumnName != null && !"".equals(tempColumnName))
                    resurlt[1] = tempColumnName;
            }
        }
        return resurlt;
    }

    /**
     *  修改操作
     */
    public boolean update(Object entity) throws SecurityException,
            NoSuchMethodException, IllegalArgumentException,
            IllegalAccessException, ClassNotFoundException, SQLException {
        // update stuInfo stu set stu.stuName1='ddd' where stu.stuid=43
        StringBuffer updateSql = new StringBuffer("update ");
        LinkedList<Object> updateParams = new LinkedList<Object>();
        String primaryKeyColumn = "";
        Integer primaryParam = null;
        Class<?> entityClass = entity.getClass();
        String tableName = getTableName(entityClass);

        updateSql.append(tableName).append(" tab set ");
        Field[] fields = entityClass.getDeclaredFields();
        for (Field field : fields) {
            String columnName = field.getName();
            Annotation[] annotations = field.getAnnotations();
            // 判斷是否是主鍵
            boolean isfindPrimarykey = false;
            for (Annotation annotation : annotations) {
                if (annotation instanceof Id) {
                    primaryKeyColumn = field.getName();
                    field.setAccessible(true);
                    primaryParam = (Integer) field.get(entity);
                    isfindPrimarykey = true;
                    break;
                }

            }
            if (isfindPrimarykey)
                continue;
            Object[] findAnnotationResult = findAnnotation(annotations);
            boolean isAnnotaionOverField = (Boolean) findAnnotationResult[0];
            if (!isAnnotaionOverField) {
                String getMethodName = "get"
                        + columnName.substring(0, 1).toUpperCase()
                        + columnName.substring(1);
                Method method = entityClass.getMethod(getMethodName,
                        new Class[] {});
                annotations = method.getAnnotations();
                findAnnotationResult = findAnnotation(annotations);
                isAnnotaionOverField = (Boolean) findAnnotationResult[0];
            }
            if (!isAnnotaionOverField)
                continue;
            String tempColumnName = (String) findAnnotationResult[1];
            if (tempColumnName != null && !"".equals(tempColumnName))
                columnName = tempColumnName;
            updateSql.append("tab.").append(columnName).append("=?,");
            field.setAccessible(true);
            updateParams.add(field.get(entity));
        }
        updateSql.replace(updateSql.lastIndexOf(","), updateSql.length(), "");
        updateSql.append(" where tab.").append(primaryKeyColumn).append("=?");
        System.out.println(updateSql);

        conn = DBConnectionUtil.getConnection();
        PreparedStatement prep = conn.prepareStatement(updateSql.toString());
        int i = 1;
        for (Object param : updateParams) {
            if (param instanceof Date) {
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
                java.sql.Date date = java.sql.Date.valueOf(dateFormat
                        .format(param));
                prep.setDate(i, date);
            } else {
                prep.setObject(i, param);
            }
            i++;
        }
        prep.setInt(i, primaryParam);
        if (prep.executeUpdate() > 0)
            return true;
        return false;
    }

    /**
     *  刪除操作
     */
    public boolean delete(Object entity) throws IllegalArgumentException,
            IllegalAccessException, ClassNotFoundException, SQLException {
        // delete from stuInfo stu where stu.stuid=43
        StringBuffer deleteSql = new StringBuffer("delete from ");
        Integer primaryParam = null;
        Class<?> entityClass = entity.getClass();
        String tableName = getTableName(entityClass);
        deleteSql.append(tableName).append(" tab ").append("where ");
        Field[] fields = entityClass.getDeclaredFields();
        for (Field field : fields) {
            Annotation[] annotations = field.getAnnotations();
            boolean isfindPrimary = false;
            for (Annotation annotation : annotations) {
                if (annotation instanceof Id) {
                    deleteSql.append("tab.").append(field.getName()).append(
                            "=?");
                    field.setAccessible(true);
                    primaryParam = (Integer) field.get(entity);
                    isfindPrimary = true;
                    break;
                }
            }
            if (isfindPrimary)
                break;
        }
        conn = DBConnectionUtil.getConnection();
        System.out.println(deleteSql.toString());
        PreparedStatement prep = conn.prepareStatement(deleteSql.toString());
        prep.setInt(1, primaryParam);
        if (prep.executeUpdate() > 0)
            return true;
        return false;
    }

    /**
     * 根據Id查詢某個實體物件
     */
    public <T> T get(Class<T> entityClass, Integer id)
            throws ClassNotFoundException, SQLException,
            InstantiationException, IllegalAccessException, SecurityException,
            NoSuchMethodException, IllegalArgumentException,
            InvocationTargetException {
        T entity = null;
        StringBuffer selectByIdSql = new StringBuffer("select * from ");
        String tableName = getTableName(entityClass);
        selectByIdSql.append(tableName).append(" tab where tab.");
        Field[] fields = entityClass.getDeclaredFields();
        for (Field field : fields) {
            Annotation[] annotations = field.getAnnotations();
            boolean isfindPrimaryfield = false;
            String columnName = field.getName();
            for (Annotation annotation : annotations) {
                if (annotation instanceof Id) {
                    selectByIdSql.append(columnName).append("=?");
                    isfindPrimaryfield = true;
                    break;
                }
            }
            if (!isfindPrimaryfield) {
                String getMethodName = "get"
                        + columnName.substring(0, 1).toUpperCase()
                        + columnName.substring(1);
                Method getMethod = entityClass.getMethod(getMethodName,
                        new Class[] {});
                annotations = getMethod.getAnnotations();
                for (Annotation annotation : annotations) {
                    if (annotation instanceof Id) {
                        selectByIdSql.append(columnName).append("=?");
                        isfindPrimaryfield = true;
                        break;
                    }
                }
            }
            if (isfindPrimaryfield)
                break;

        }
        System.out.println(selectByIdSql.toString());
        conn = DBConnectionUtil.getConnection();
        PreparedStatement prep = conn
                .prepareStatement(selectByIdSql.toString());
        prep.setInt(1, id);
        ResultSet result = prep.executeQuery();
        while (result.next()) {
            entity = setData2Entity(entityClass, fields, result);
        }
        return entity;
    }
    /**
     *裝result中的資料據,用反射加入到對應的實體中 
     */
    private <T> T setData2Entity(Class<T> entityClass, Field[] fields,
            ResultSet result) throws InstantiationException,
            IllegalAccessException, NoSuchMethodException, SQLException,
            InvocationTargetException {
        // 把資料組拼到物件中去
        T entity = entityClass.newInstance();
        for (Field field : fields) {
            String fieldName = field.getName();
            String columnName = fieldName;
            Annotation[] annotations = field.getAnnotations();
            Object[] findAnnotationResult = findAnnotation(annotations);
            boolean isfindAnotation = (Boolean) findAnnotationResult[0];
            if (!isfindAnotation) {
                String getMethodName = "get"
                        + fieldName.substring(0, 1).toUpperCase()
                        + fieldName.substring(1);
                Method method = entityClass.getMethod(getMethodName,
                        new Class[] {});
                annotations = method.getAnnotations();
                findAnnotationResult = findAnnotation(annotations);
                isfindAnotation = (Boolean) findAnnotationResult[0];
            }
            String tempColumnName = (String) findAnnotationResult[1];
            if (tempColumnName != null && !"".equals(tempColumnName))
                columnName = tempColumnName;
            Object value = result.getObject(columnName);
            BeanUtils.setProperty(entity, fieldName, value);
        }
        return entity;
    }

    /**
     * 分頁查詢所有記錄
     **/
    public <T> List<T> getPaging(Class<T> entityClass, int firstIndex,
            int maxResult) throws ClassNotFoundException, SQLException,
            InstantiationException, IllegalAccessException,
            NoSuchMethodException, InvocationTargetException {
        List<T> results = new ArrayList<T>();
        StringBuffer pageIngSql = new StringBuffer(
                "select * from (select rownum rn,tab.* from ");
        String tableName = getTableName(entityClass);
        pageIngSql.append(tableName).append(" tab ) where rn between ? and ?");
        System.out.println(pageIngSql.toString());
        conn = DBConnectionUtil.getConnection();
        PreparedStatement prep = conn.prepareStatement(pageIngSql.toString());

        prep.setInt(1, firstIndex);
        prep.setInt(2, firstIndex + maxResult);
        ResultSet result = prep.executeQuery();
        Field[] fields = entityClass.getDeclaredFields();
        while (result.next()) {
            T entity = setData2Entity(entityClass, fields, result);
            results.add(entity);
        }
        return results;
    }

    /**
     * 得到總頁數
     */
    public <T> int getCount(Class<T> entityClass)
            throws ClassNotFoundException, SQLException {
        int count = 0;
        StringBuffer countSql = new StringBuffer("select count(*) count from ");
        String tableName = getTableName(entityClass);
        countSql.append(tableName);
        System.out.println(countSql.toString());
        conn = DBConnectionUtil.getConnection();
        PreparedStatement prep = conn.prepareStatement(countSql.toString());
        ResultSet result = prep.executeQuery();
        if (result.next()) {
            count = result.getInt("count");
        }
        return count;
    }
    //測試
    public static void main(String[] args) throws SecurityException,
            IllegalArgumentException, NoSuchMethodException,
            IllegalAccessException, SQLException, ClassNotFoundException,
            InstantiationException, InvocationTargetException {
        Session session = new Session();
        Student student = new Student();
        student.setStuId(2);
        student.setStuName("hhhh");
        student.setBirthday(new Date());
        /*
        if (session.save(student)) {
            System.out.println("新增成功");
        } else {
            System.out.println("新增失敗");
        }
        */
        /*
         * student.setStuId(43); 
         * if (session.update(student)) {
         *  System.out.println("修改成功"); 
         * } 
         * else {
         *  System.out.println("修改失敗");
         *   }
         */

        /*
         * student.setStuId(42); 
         * if (session.delete(student)) {
         *  System.out.println("刪除成功");
         *  } else { 
         *  System.out.println("刪除失敗");
         *   }
         */
        /*
         * 根據id查詢 student = session.get(Student.class, 41);
         * System.out.println(student.getStuId() + " name:" +
         * student.getStuName() + "  birthday:" + student.getBirthday());
         */

        /*
         * 分頁查詢
         */
        int currentPage = 1;
        int maxResult = 2;
        int count = session.getCount(Student.class);
        int countPage = count / maxResult == 0 ? count / maxResult : count
                / maxResult + 1;
        int firstIndex = (currentPage - 1) * maxResult+1;
        List<Student> pagingList = session.getPaging(Student.class,
                firstIndex, maxResult);
        System.out
                .println("總頁數:" + countPage + " \t 當前第 " + currentPage + " 頁");
        System.out.println("編號\t姓名\t出生年日");
        for (Student student2 : pagingList) {
            System.out.println(student2.getStuId() + "\t"
                    + student2.getStuName() + "\t" + student2.getBirthday());
        }   
    }
}
測試實體類:Student
package org.keyuan.entity;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;

@Entity(name="stuInfo")
public class Student {
    @Id
    private int stuId;
    private String stuName;
    private Date birthday;
    @Id
    public int getStuId() {
        return stuId;
    }
    public void setStuId(int stuId) {
        this.stuId = stuId;
    }
    @Column(name="stuName1")
    public String getStuName() {
        return stuName;
    }
    public void setStuName(String stuName) {
        this.stuName = stuName;
    }
    @Column(name="birthday") 
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
}
連線工具類:DbConnectionUtil
package org.keyuan.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DBConnectionUtil {
    private static final String DRIVER= "oracle.jdbc.driver.OracleDriver";
    private static final String URL = "jdbc:oracle:thin:@localhost:1521:KEYUAN";
    private static final String PASSWORD = "test";
    private static final String USER = "test";
    
    private static Class<?> driverClass;
    static{
        try {
            initDriver();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    private static void initDriver() throws ClassNotFoundException{
            driverClass=Class.forName(DRIVER);
    }
    public static Connection getConnection() throws ClassNotFoundException, SQLException{
        if(driverClass==null)
            initDriver();
      return DriverManager.getConnection(URL,USER,PASSWORD);
    }
}


相關文章