用实例聊聊Springreflect范型

    技术2022-05-11  44

    接触反射和范型有一段时间了,刚好有空,就写了个结合Sring的DI,加上反射和范型,写了个测试例子,朋友们多多指教!

    以下是代码

    -----------------------------------------------------------------------------------------------------------------------------

    package com.zhaoda.test.spring.po;

    /** * PO,数据库也是根据这个类来设计的. * * @author 罗文强 * */public class People {

        private Integer id;

        private String name;

        private Integer age;

        /**     * @return 年龄     */    public Integer getAge() {        return age;    }

        /**     * @param age     *            设置年龄     */    public void setAge(Integer age) {        this.age = age;    }

        /**     * @return ID     */    public Integer getId() {        return id;    }

        /**     * @param id     *            设置ID     */    public void setId(Integer id) {        this.id = id;    }

        /**     * @return 名字     */    public String getName() {        return name;    }

        /**     * @param name     *            设置名字     */    public void setName(String name) {        this.name = name;    }}-----------------------------------------------------------------------------------------------------------------------------

    package com.zhaoda.test.spring.dao;

    import java.util.List;

    import com.zhaoda.test.spring.po.People;

    /** * 对{@link People}进行操作的接口 *  * @author 罗文强 *  */public interface PeopleDao {

        /**     * 添加一个人     *      * @param p     *            数据库中未存在而需要添加的人     */    public void add(People p);

        /**     * 修改一个人的信息     *      * @param p     *            需要更新的人     */    public void update(People p);

        /**     * 删除一个人的资料     *      * @param p     *            需要删除的人     */    public void delete(People p);

        /**     * 查询所有的人     *      * @return 所有符合{@link People}类的对象     */    public List<People> findAll();

        /**     * 根据ID查询人     *      * @param p     * @return ID对应的人     */    public People findById(People p);    // 如果有需要根据条件来查询的,可以使用自定义的条件对象来实现动态生成SQL}-----------------------------------------------------------------------------------------------------------------------------

    package com.zhaoda.test.spring.dao.impl;

    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.sql.Types;import java.util.Date;import java.util.LinkedList;import java.util.List;

    import org.springframework.jdbc.core.support.JdbcDaoSupport;

    import com.zhaoda.test.spring.dao.PeopleDao;import com.zhaoda.test.spring.exception.UnknowDataType;import com.zhaoda.test.spring.po.People;

    /** * DAO,{@link JdbcDaoSupport}依赖了{@link java.sql.DataSource}. * 所以,在用的时候,必须提供依赖实现 *  * @author 罗文强 *  */public class PeopleDaoImpl extends JdbcDaoSupport implements PeopleDao {

        /*     * @see com.zhaoda.test.spring.dao.PeopleDao#add(com.zhaoda.test.spring.People)     */    public void add(People p) {        String sql = "insert into tb_test_people(id, name, age) "                + "select isnull(max(id), 0) + 1, ?, ? from tb_test_people";        Object[] os = new Object[2];        os[0] = p.getName();        os[1] = p.getAge();        // 使用Spring的JdbcTemplate()更新数据库        int result = getJdbcTemplate().update(sql, os);        System.out.println("受影响行数: " + result);    }

        /*     * (non-Javadoc)     *      * @see com.zhaoda.test.spring.dao.PeopleDao#delete(com.zhaoda.test.spring.People)     */    public void delete(People p) {        String sql = "delete tb_test_people where id = ?";        Object[] os = new Object[1];        os[0] = p.getId();        // 使用Spring的JdbcTemplate()更新数据库        int result = getJdbcTemplate().update(sql, os);        System.out.println("受影响行数: " + result);    }

        /*     * (non-Javadoc)     *      * @see com.zhaoda.test.spring.dao.PeopleDao#findAll()     */    public List<People> findAll() {        Connection connection = null;        List<People> result = new LinkedList<People>();        try {            String sql = "select id, name, age from tb_test_people";            // 这里不用Spring的JdbcTemplate的查询,因为我们要使用结果集            connection = getJdbcTemplate().getDataSource().getConnection();            ResultSet rs = connection.createStatement().executeQuery(sql);            while (rs.next()) {                // 调用setValue方法,这个方法是用反射和范型进行设置值的.                People temp = setValue(People.class, rs);                result.add(temp);            }        } catch (SQLException e) {            e.printStackTrace();        } finally {            try {                if (connection != null && !connection.isClosed()) {                    connection.close();                }            } catch (SQLException e) {                e.printStackTrace();            }        }        return result;    }

        /*     * (non-Javadoc)     *      * @see com.zhaoda.test.spring.dao.PeopleDao#findById(com.zhaoda.test.spring.People)     */    public People findById(People p) {        String sql = "select id, name, age from tb_test_people where id = ?";        Connection connection = null;        try {            // 这里不用Spring的JdbcTemplate的查询,因为我们要使用结果集            connection = getJdbcTemplate().getDataSource().getConnection();            PreparedStatement ps = connection.prepareStatement(sql);            ps.setInt(1, p.getId());            ResultSet rs = ps.executeQuery();            if (rs.next()) {                // 调用setValue方法,这个方法是用反射和范型进行设置值的.                p = setValue(People.class, rs);                return p;            }            rs.close();            ps.close();        } catch (SQLException e) {            e.printStackTrace();        } finally {            try {                if (connection != null && !connection.isClosed()) {                    connection.close();                }            } catch (SQLException e) {                e.printStackTrace();            }        }        return null;    }

        /*     * (non-Javadoc)     *      * @see com.zhaoda.test.spring.dao.PeopleDao#update(com.zhaoda.test.spring.People)     */    public void update(People p) {        String sql = "update tb_test_people set name = ?, age = ? where id = ?";        Object[] os = new Object[3];        os[0] = p.getName();        os[1] = p.getAge();        os[2] = p.getId();        int result = getJdbcTemplate().update(sql, os);        System.out.println("受影响行数: " + result);    }

        /**     * 通过反射设置对象的值的公用方法.     *      * @param <T>     *            通过类的无参数构造器产生一个实例     * @param c     *            类     * @param rs     *            调用了rs.next()后的rs     * @return 类的实例,并且已经封装了值.     */    private <T> T setValue(Class<T> c, ResultSet rs) {        T o = null;        try {            // 初始化类的实例            o = c.newInstance();            // 取得结果集的元数据            ResultSetMetaData metaData = rs.getMetaData();            // 遍历元数据,取得每个列的名称和数据类型            for (int i = 1; i <= metaData.getColumnCount(); i++) {                // 列名                String columnName = metaData.getColumnName(i);                // 数据类型                int columnType = metaData.getColumnType(i);                // 列的值                Object columnValue = rs.getObject(columnName);                // 字符串的列数据类型,这个是SQL的数据类型                String columnTypeName = metaData.getColumnTypeName(i);                // 构造需要操作的方法名称                String methodName = "set"                        + columnName.substring(0, 1).toUpperCase()                        + columnName.substring(1, columnName.length());                Method method = null;                // 根据数据类型,得到相应的方法.                switch (columnType) {                case Types.TIMESTAMP: {                    method = c.getMethod(methodName, Date.class);                    break;                }                case Types.BIGINT: {                    method = c.getMethod(methodName, Integer.class);                    break;                }                case Types.INTEGER: {                    method = c.getMethod(methodName, Integer.class);                    break;                }                case Types.VARCHAR: {                    method = c.getMethod(methodName, String.class);                    break;                }                case Types.CHAR: {                    method = c.getMethod(methodName, String.class);                    break;                }                default: {                    throw new UnknowDataType("不支持数据类型: " + columnTypeName);                }                }                // 调用方法,关于这个方法更详细的信息可以参考API                method.invoke(o, columnValue);            }        } catch (SQLException e) {            e.printStackTrace();        } catch (IllegalAccessException e) {            e.printStackTrace();        } catch (SecurityException e) {            e.printStackTrace();        } catch (NoSuchMethodException e) {            e.printStackTrace();        } catch (IllegalArgumentException e) {            e.printStackTrace();        } catch (InvocationTargetException e) {            e.printStackTrace();        } catch (InstantiationException e) {            e.printStackTrace();        }        return o;    }}-----------------------------------------------------------------------------------------------------------------------------

    package com.zhaoda.test.spring.exception;

    /** * 未知数据类型异常 *  * @author 罗文强 *  */public class UnknowDataType extends RuntimeException {

        /**     *      */    private static final long serialVersionUID = 2354064628190018064L;

        private Integer errorCode;

        public UnknowDataType(Integer errorCode) {        super();        this.errorCode = errorCode;    }

        public UnknowDataType() {        super();    }

        public UnknowDataType(String message, Throwable cause) {        super(message, cause);    }

        public UnknowDataType(String message, Integer errorCode, Throwable cause) {        super(message, cause);        this.errorCode = errorCode;    }

        public UnknowDataType(String message, Integer errorCode) {        super(message);        this.errorCode = errorCode;    }

        public UnknowDataType(String message) {        super(message);    }

        public UnknowDataType(Throwable cause) {        super(cause);    }

        /**     * @return 错误代码     */    public Integer getErrorCode() {        return errorCode;    }

        /**     * @param errorCode     *            设置错误代码     */    public void setErrorCode(Integer errorCode) {        this.errorCode = errorCode;    }}-----------------------------------------------------------------------------------------------------------------------------

    <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

    <beans>    <!-- 初始化一个数据源,因为这里设计的数据库操作需要用到 -->    <bean id="dataSource"        class="org.springframework.jdbc.datasource.DriverManagerDataSource">        <!-- 给数据源的属性注入值 -->        <property name="driverClassName"            value='net.sourceforge.jtds.jdbc.Driver' />        <property name="url"            value="jdbc:jtds:sqlserver://127.0.0.1/test" />        <property name="username" value="sa" />        <property name="password" value="123456" />    </bean>    <!-- DAO依赖于数据源 -->    <bean id="peopleDao"        class="com.zhaoda.test.spring.dao.impl.PeopleDaoImpl">        <!-- 这里给DAO注入数据源 -->        <property name="dataSource">            <ref bean="dataSource" />        </property>    </bean></beans>-----------------------------------------------------------------------------------------------------------------------------

    package com.zhaoda.test.spring;

    import java.util.Iterator;

    import junit.framework.TestCase;

    import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;

    import com.zhaoda.test.spring.dao.PeopleDao;import com.zhaoda.test.spring.po.People;

    /** * 测试Spring,这里还用到了Java的范型和反射 *  * @author 罗文强 *  */public class DaoTest extends TestCase {

        private static ApplicationContext ctx = null;

        /**     * @param arg0     */    public DaoTest(String arg0) {        super(arg0);    }

        /*     * (non-Javadoc)     *      * @see junit.framework.TestCase#setUp()     */    protected void setUp() throws Exception {        String file = "applicationContext.xml";        ctx = new ClassPathXmlApplicationContext(file);        super.setUp();    }

        /*     * (non-Javadoc)     *      * @see junit.framework.TestCase#tearDown()     */    protected void tearDown() throws Exception {        super.tearDown();    }

        public void testAdd() {        PeopleDao dao = getBean(PeopleDao.class, "peopleDao");        People p = new People();        p.setAge(10);        p.setName("老张");        dao.add(p);    }

        public void testFindById() {        PeopleDao dao = getBean(PeopleDao.class, "peopleDao");        People p = new People();        p.setId(1);        p = dao.findById(p);        System.out.println(p.getId());        System.out.println(p.getName());        System.out.println(p.getAge());    }

        public void testFindAll() {        PeopleDao dao = getBean(PeopleDao.class, "peopleDao");        Iterator<People> ps = dao.findAll().iterator();        while (ps.hasNext()) {            People p = ps.next();            System.out.println(p.getId());            System.out.println(p.getName());            System.out.println(p.getAge());        }    }

        public void testUpdate() {        PeopleDao dao = getBean(PeopleDao.class, "peopleDao");        People p = new People();        p.setId(1);        p.setAge(10);        p.setName("老张第一");        dao.update(p);    }

        public void testDelete() {        PeopleDao dao = getBean(PeopleDao.class, "peopleDao");        People p = new People();        p.setId(5);        dao.delete(p);    }    /**     * 这个就是根据范型来自动强制转型的方法了.     *      * @param <T>     * @param c     * @param name     * @return     */    @SuppressWarnings("unchecked")    private <T> T getBean(Class<T> c, String name) {        Object o = ctx.getBean(name);        return (T) o;    }}

     


    最新回复(0)