`
yeshaoting
  • 浏览: 684401 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

[反射机制]简单实现ORM

    博客分类:
  • J2SE
 
阅读更多

 

12. 利用反射机制完成对象关系映射

反射机制实现简单的半自动化ORM(Object Retional Mapping)

 

半自动化ibatis,却刚好解决了这个问题。这里的半自动化,是相对Hibernate等提供了全面的数据库封装机制的全自动化ORM 实现而言,全自动ORM 实现了 POJO 和数据库表之间的映射,以及 SQL 的自动生成和执行。而ibatis 的着力点,则在于POJO SQL之间的映射关系。也就是说,ibatis 并不会为程序员在运行期自动生成 SQL 执行。具体的 SQL 需要程序员编写,然后通过映射配置文件,将SQL所需的参数,以及返回的结果字段映射到指定 POJO

摘自:【百度百科 词条:ibatis

 

完成的功能:

a. 数据表到POJO的映射,POJO属性名与数据表字段名可不一致。当数据表字段名发生修改时,无须通过硬编码方式修改POJO代码,修改配置文件POJO属性到数据表的字段映射即可完成,达到松耦合目的。

b. 数据库SQL语句放在配置文件中,由相关接口调用,某些情况下,数据库操作发生变化时,能够很方便的修改SQL语句。感觉有点类似于将SQL语句写到数据库存储过程中。

c. 所有SQL语句放在一起便于集中管理,增强代码复用性、易于修改、维护。例如:某条业务逻辑相关的SQL语句在多处有使用到,传统情况下需要在将SQL语句内嵌到程序代码中多次,每次的书写导致繁琐,复用性差。另外,当业务逻辑变更时,相应的SQL语句需要做一定的修改,此时内嵌程序代码中的SQL语句又会出现维护难题,不易修改、维护。

d. 相对全自动化来说,半自动化更加灵活。程序员能根据需要方便地修改SQL语句。

 

实现过程:

1. 自定义数据源配置文件data-source-config.xml

简单提出一些约束条件(对于完成的框架被称作文档类型定义dtd)。这些约束在解析该数据源配置文件时用到。

ORM配置文件标签类型说明:

 

       <sqlMap>对象关系映射根标签

       <data-source>数据源配置文件地址

       <resultMap>对象关系映射:用于将数据表的字段映射到对象属性

       <result>单条对象关系映射

       <statement>增查改删(CRUD)SQL语句

      

       标签属性说明:

       <resultClass>标签属性: id, class

       <statement>标签属性: id, parameterClass, resultClass

       <result>标签属性: property(对象属性), column(数据表字段)

      

       配置ORM几点约束:

       1. 有且只有一个<sqlMap>标签

       2. 标签拼写大小写敏感,目前最多三级标签

       3. 出现多个 id 的标签,以第一个为准

       4. 不同的标签可以用相同的 id 属性值

       5. SQL语句必须用#包裹

       6. <statement>,<resultMap>标签必须用 id,resultClass 属性

       7. 没有参数的可以不设置 parameterClass 属性

       8. parameterClass,resultClass 属性,对于基本类型,要求输入其包装类完全限定名称

      

       parameterClass,resultClass支持类型

       1. 所有基本数据类型java.lang.Integer,java.lang.Long,java.lang.Float

       2. 复合类型java.lang.String,java.util.Map,java.util.List,java.util.Date

       3. 自定义映射类型

 

<?xml version="1.0" encoding="UTF-8"?>

 

<!-- quote from sql-map-config.xml of ibatis 2.0 -->

<sqlMap>

   

    <data-source config="com/iteye/jarg/resources/data-source-config.xml" />

     

    <!--

       映射表字段columnBean属性property

     -->

 

    <resultMap id="User2"       class="com.iteye.jarg.test.User2">

       <result property="id"       column="id" />

       <result property="name"      column="username" />

       <result property="pwd"  column="password" />

    </resultMap>

   

   

    <!-- 用户自定义类型 -->

    <statement id="query" parameterClass="com.iteye.jarg.test.User2" resultClass="User2">

       select *

       from user

       where id = #id# and username = #name# and password = #pwd#

    </statement>

 

<!-- 以下返回单条记录 -->  

    <statement id="queryUserById" parameterClass="java.lang.Integer" resultClass="com.iteye.jarg.test.User">

       select *

       from user

       where id = #id#

    </statement>

   

    <!-- 参数可以使用复合类型,只取出需要的,对应的数据 -->

    <statement id="queryUserById2" parameterClass="java.util.Map" resultClass="User2">

       select *

       from user

       where id = #id#

    </statement>

   

    ...

   

    <statement id="queryUserWithList" parameterClass="java.util.List" resultClass="com.iteye.jarg.test.User">

       select *

       from user

       where username = #username# and password = #password#

    </statement>

 

   

<!-- 以下返回多条记录 -->

 

    <statement id="queryUsersById" parameterClass="java.lang.Integer" resultClass="com.iteye.jarg.test.User">

       select *

       from user

       where id != #id#

    </statement>

      

    <statement id="queryUsersWithMap" parameterClass="java.util.Map" resultClass="User2">

       select *

       from user

       where username != #username# or password != #password#

    </statement>

   

    ...

   

    <statement id="queryAllUser" resultClass="com.iteye.jarg.test.User">

       select *

       from user

    </statement>

   

</sqlMap>

 

2. 定义程序中用到的相关常量

这些常量大部分是在解析上面的xml文档时用到。由于基本类型在反射时需要用到它们的包装类生成 Class 类实例,所以配置文件中属性 parameterClassresultClass 要求输入基本类型的完全限定名称。因此,对于基本类型的数据类型包含包装类型字符串和基本类型字符串,包装类型字符串在前,基本类型字符串在后,用空格隔开。映射类型用com.iteye.jarg.test.ResultMap类来表示。类型集为了方便类型匹配,找出对应的参数类型。

 

关键代码:

 

    /**

     * Copyright (c) 2011 Trusted Software and Mobile Computing(TSMC)

     * All right reserved.

     *

     * Created on Aug 20, 2011 4:00:36 PM

     * http://jarg.iteye.com/

     * Author: Jarg Yee <yeshaoting@gmail.com>

     */

   

    /** 对象关系映射配置文件路径 */

    private static final String CONFIG = "mapper-config.xml";

   

    /** 配置文件根节点 */

    private static Element root = null;

   

    /** 配置文件节点名 */

    private static final String NODE_DATA_SOURCE = "data-source";

    private static final String NODE_TYPE_ALIAS = "typeAlias";

    private static final String NODE_RESULT_MAP = "resultMap";

    private static final String NODE_PARAMETER_MAP = "parameterMap";

    private static final String NODE_PROPERTY = "property";

    private static final String NODE_STATEMENT = "statement";

    private static final String NODE_PARAMETER = "parameter";

    private static final String NODE_RESULT = "result";

   

    /** 配置文件节点属性名 */

    private static final String ATT_CONFIG = "config";

    private static final String ATT_NAME = "name";

    private static final String ATT_VALUE = "value";

    private static final String ATT_ID = "id";

    private static final String ATT_CLASS = "class";

    private static final String ATT_PROPERTY = "property";

    private static final String ATT_COLUMN = "column";

    private static final String ATT_PARAMETER_CLASS = "parameterClass";

    private static final String ATT_PARAMETER_MAP = "parameterMap";

    private static final String ATT_RESULT_CLASS = "resultClass";

    private static final String ATT_RESULT_MAP = "resultMap";

   

    /** 反射机制获取方法名前缀 */

    private static final String PREFIX_SET = "set";

    private static final String PREFIX_GET = "get";

   

    /** 数据类型 */

    private static final String TYPE_BYTE = "java.lang.Byte byte";

    private static final String TYPE_BOOLEAN = "java.lang.Boolean boolean";

    private static final String TYPE_CHAR = "java.lang.Character char";

    private static final String TYPE_SHORT = "java.lang.Short short";

    private static final String TYPE_INT = "java.lang.Integer int";

    private static final String TYPE_LONG = "java.lang.Long long";

    private static final String TYPE_FLOAT = "java.lang.Float float";

    private static final String TYPE_DOUBLE = "java.lang.Double double";

    private static final String TYPE_Date = "java.util.Date";

    private static final String TYPE_STRING = "java.lang.String";

    private static final String TYPE_OBJECT = "java.lang.Object";

    private static final String TYPE_MAP = "java.util.Map";

    private static final String TYPE_LIST = "java.util.List";

   

    private static final String TYPE_PARAMETER_MAP = "com.iteye.jarg.test.ParameterMap";

    private static final String TYPE_RESULT_MAP = "com.iteye.jarg.test.ResultMap";

   

    /** 类型集 */

    private static final String[] TYPE = {

       TYPE_BYTE, TYPE_BOOLEAN, TYPE_CHAR, TYPE_SHORT, TYPE_INT, TYPE_LONG,

       TYPE_FLOAT, TYPE_DOUBLE, TYPE_Date, TYPE_STRING, TYPE_OBJECT, TYPE_MAP,

       TYPE_LIST, TYPE_PARAMETER_MAP, TYPE_RESULT_MAP

    };

   

    /** 获取数据库连接 */

    private Connection conn = null;

 

 

3. 初始化预编译SQL语句

这一步是用来解析SQL语句标签<statement>,获取相应的预编译SQL语句编号,参数类型,结果集类型,SQL语句,放于SqlMapStatement实例中。

 

关键代码:

 

/**

 * TODO SQL语句声明实体

 */

public class SqlMapStatement

{

    private String sql;

    private String id;

   

    private Class<?> parameterClass;

    private String resultClass;

   

    ...

 

}

 

 

4. 获取预编译SQL语句

<statement>标签中的SQL语句转换成真正的预编译SQL语句。这一步就是将#号包裹的输入参数替换成?(预编译SQL语句中代表一个参数)。利用正则表达式#[0-9a-zA-Z]*#,将开始#username##password#等替换成?。

 

关键代码:

 

       //利用正则表达式,#包围的字符串规制成?,形成预编译的SQL语句形式.

       String statement = sqlMapStatement.getSql();

       String sql = statement.replaceAll("#[0-9a-zA-Z]*#", "?");

      

       PreparedStatement pstmt = conn.prepareStatement(sql);

 

 

5. 获取预编译声明实例

5.1 获取参数个数

根据预编译SQL语句中问号(?)个数来确定。

关键代码:

 

    /**

     * 获出预编译SQL语句参数个数

     * */

    private int getParameterNum(String sql)

    {

       int count = 0;

       for(int i=0; i<sql.length(); i++)

       {

           if(sql.charAt(i) == '?')

           {

              count = count + 1;

           }

       }

       return count;

    }

   

 

5.2 设置预编译SQL语句中的参数值

_        多个参数情况

需要用到复合类型(java.util.Map,java.util.List)、自定义映射类型(如:上面配置文件提到的User2)或自定义类类型(如:上面配置文件提到的com.iteye.jarg.test.User)。根据原始预编译SQL语句(<statement>标签下的文本值)中由#包裹的参数名,从复合类型,自定义类类型中取出对应参数名的数值或根据参数出现先后顺序从 java.util.List 中依次取出数值。

最后,通过 java.sql.PreParedStatement.setObject(int index, Object obj) 方法设置预编译SQL语句第index个参数,这一方法会根据 obj 的原始类型完成相对应的设置。

 

void setObject(int parameterIndex,

               Object x)

               throws SQLException

使用给定对象设置指定参数的值。第二个参数必须是类型 Object;所以,应该对内置类型使用 java.lang 的等效对象。 JDBC 规范指定了一个从 Java Object 类型到 SQL 类型的标准映射关系。在发送到数据库之前,给定参数将被转换为相应 SQL 类型。

 

_        一个参数情况

匹配数据类型集数据类型与SqlMapStatement实例中输入参数类型(<statement>标签属性parameterClass)

最后,通过 java.sql.PreParedStatement.setObject(int index, Object obj) 方法设置预编译SQL语句第index个参数,这一方法会根据 obj 的原始类型完成相对应的设置。

 

注:基本数据类型(如:java.lang.Integer),需要通过反射机制将输入参数转换成对应的基本数据类型。例如:输入参数类型为java.lang.Integer参数,需要先调用java.lang.Integer类的parseInt(String obj)方法,返回对应类型的数值,再调用 java.sql.PreParedStatement.setObject(int index, Object obj) 方法。

 

另外,一个参数的参数类型若不是简单数据类型而复合数据类型或自定义映射类型的话,会通过从复合数据类型或自定映射类型中取出合适的数据作为该参数值填充。如:取出 java.util.Map 或 自定义类类型 中对应参数名的数值;取出 java.util.List 的第一个数值等。

 

5.3 返回 PreparedStatement 实例

该实例到此已经完成预编译SQL语句中参数设置。

 

关键代码:

 

    //count=0时不需要设置参数

    int count = getParameterNum(sql);   //通过获取sql语句中的 ? 数目确定参数个数

   

    if(count != 0)

    {

    /**

     * 输入参数填充预编译SQL语句

     *

     * parameterClass,resultClass支持类型

     * 1. 简单数据类型java.lang.Integer,java.lang.Long,java.lang.Float,java.lang.String

     * 2. 复合类型java.util.Map,java.util.List

     * 3. 自定义映射类型,自定义类类型

     * */

    if(count == 1)

    {

        for(int i=0; i<11; i++)

        {

            if(sqlMapStatement.getParameterClass().getName().trim().equals(TYPE[i].split(" ")[0].trim()))

            {

               int size = TYPE[i].split(" ").length;  //是否包含基本类型包装类 基本类型

              

               Class<?> clazz = Class.forName(TYPE[i].split(" ")[0]);

               if(size==2)

               {

                   //还得将参数值转换成对应的基本类型

                   Method method = clazz.getMethod(getMethodName("parse",TYPE[i].split(" ")[1]), String.class);

                   Object obj = method.invoke(clazz, paramObject.toString());

                   pstmt.setObject(1, obj);

                  

                   return pstmt;

               }

               if(size==1)

               {

                   pstmt.setObject(1, paramObject.toString());

                   return pstmt;

               }

              

            }

        }

    }

   

    /**

     * 按顺序取出值作为输入参数 - List

     * */

     if(sqlMapStatement.getParameterClass().getName().equals(TYPE_LIST))

    {

        List list = (List)paramObject;

        for(int i=0; i<count; i++)

        {

            pstmt.setObject(i+1, list.get(i));

        }

        return pstmt;

    }

   

    /**

     * 按关键字取出值作为输入参数 - Map

     * */

    else if(sqlMapStatement.getParameterClass().getName().equals(TYPE_MAP))

    {

        Map model = (Map)paramObject;

       

        /**

         * 首先查找 # 包围的字符串,同时trim()去除前后的空白

         * */

        //"#[0-9a-zA-Z]*#"

        Pattern p = Pattern.compile("#[0-9a-zA-Z]*#");

        Matcher m = p.matcher(statement);

       

        int index = 1;

        while (m.find())

        {

            String key = m.group().replaceAll("#", "").trim();

            System.out.println("key:" + key);

            Object value = model.get(key);

            pstmt.setObject(index++, value);

           

        }

        return pstmt;

    }

   

    /**

     * 按属性名取出值作为输入参数 - 用户自定义的映射

     * */

    else if(sqlMapStatement.getParameterClass().getName().equals(TYPE_PARAMETER_MAP))

    {

        //占不支持自定义参数映射

        return pstmt;

    }

   

    /**

     * 按属性名取出值作为输入参数 - 用户自定义的类型

     * */

    //用户自定义的类型

    else

    {

        Class<?> clazz = Class.forName(paramObject.getClass().getName());

       

        /**

         * 首先查找 # 包围的字符串,同时trim()去除前后的空白

         * */

        //"#[0-9a-zA-Z]*#"

        Pattern p = Pattern.compile("#[0-9a-zA-Z]*#");

        Matcher m = p.matcher(statement);

       

        int index = 1;

        while (m.find())

        {             

            String key = m.group().replaceAll("#", "").trim();

            Method method = clazz.getDeclaredMethod(getMethodName("get", key));

            Object value = method.invoke(paramObject);

            pstmt.setObject(index++, value);

        }

        return pstmt;

    }

    }

    return pstmt;

 

6. 执行预编译SQL语句

返回执行的结果集。

 

关键代码:

 

    ResultSet rs = pstmt.executeQuery();

 

 

7. 获取结果集

根据配置文件中定义的结果类型,获取查询结果集。

 

7.1 查看是否存在映射类型

解析配置文件,查找是否有 id 属性值与结果集类型相同的<resultMap>标签。若存在的话,将<resultMap>标签的子标签<result>对应的值设置到ResultMap实例中;否则,返回 null ,表示不存在对应的映射类型。

 

关键代码:

 

    private ResultMap isResultMapExist(String className) throws Exception

    {

       ResultMap resultMap = null;

      

//     System.out.println("className:" + className);

      

       List<Element> resultMapElements = root.getChildren(NODE_RESULT_MAP);

       if(resultMapElements.size() == 0)

       {

           throw new Exception("未配置" + NODE_RESULT_MAP + "节点");

       }

      

       /**

        * 查找<resultMap>节点

        * */

       for(int i=0; i<resultMapElements.size(); i++)

       {

           Element resultMapElement = resultMapElements.get(i);

          

           if(resultMapElement.getAttributeValue(ATT_ID).equals(className))

           {

              resultMap = new ResultMap();

              resultMap.setClassName(resultMapElement.getAttributeValue(ATT_CLASS));

              List<Element> resultElements = resultMapElement.getChildren(NODE_RESULT);

              if(resultElements.size() == 0)

              {

                  throw new Exception("未配置" + NODE_RESULT + "节点");

              }

             

              /**

               * 查找<result>节点

               * */

              for(int j=0; j<resultElements.size(); j++)

              {

                  Element result = resultElements.get(j);

                  resultMap.set(result.getAttributeValue(ATT_COLUMN), result.getAttributeValue(ATT_PROPERTY));

              }

           }

       }

       return resultMap;

    }

 

 

7.2 根据映射存在与否创建 Class 实例

先查看结果集是否是自定义的映射类型,若是则创建 com.iteye.jarg.test.ResultMap 类型的 Class 类实例;否则创建结果集定义的结果类型的 Class 类实例。

 

7.3 设置结果集

从结果集中获取表字段信息,然后根据字段名,通过反射机制,调用对应的setter方法,将结果设置到对应的实例(结果集)中。

 

注:对于配置文件中定义的结果集类型是自定义的映射类型,需要先将表字段名转换成映射名。如:将表字段名 username 映射到com.iteye.jarg.test.User2 中字段 name

 

注:对于查询结果集包含多条语句的情况,只需将下面代码中 if(rs !=null && rs.next()) 修改为 while(rs !=null && rs.next()) ,另外,用一个 java.util.List 实例保存多条结果。

 

关键代码:

 

    if(rs != null && rs.next())

    {

       /**

        * 根据映射存在与否创建 Class 实例

        * 结果包装成输出类型

        * */

       Class<?> clazz = null;

       ResultMap resultMap = isResultMapExist(sqlMapStatement.getResultClass());

       if(resultMap == null)

           clazz = Class.forName(sqlMapStatement.getResultClass());

       else

           clazz = Class.forName(resultMap.getClassName());

      

       obj = clazz.newInstance();  //保存转换后的结果集

      

       ResultSetMetaData metaData = rs.getMetaData();   //从结果集中获取表字段信息

       for(int i=1; i<=metaData.getColumnCount(); i++)

       {

           String fieldName = metaData.getColumnName(i);

          

           /**

            * 先查看用户自定义映射,若不存在这一类型的映射类型则直接创建

            * 通过表名能找到对象中函数名

            * */

           if(resultMap != null)

           {

              /**

                * 将数据表字段转换成对应的映射类属性

               * */

              String fieldName2 = convert(sqlMapStatement.getResultClass(), fieldName);

             

              Field field = obj.getClass().getDeclaredField(fieldName2);

              Method method = obj.getClass().getDeclaredMethod(getMethodName(PREFIX_SET, fieldName2), field.getType());

              method.invoke(obj, rs.getObject(fieldName));

             

           }

           else

           {

              Field field = clazz.getDeclaredField(fieldName);

              Method method = clazz.getDeclaredMethod(getMethodName(PREFIX_SET, metaData.getColumnName(i)), field.getType());

              method.invoke(obj, rs.getObject(fieldName));

           }

       }

    }

 

 

8. 数据库查询用户接口

只简单做了数据库单条结果、多条结果查询功能,其他数据库操作类同。

通过反射机制,调用各结果集类型中的 display() 方法输出结果。

 

关键代码:

   

    /**

     * 查询,返回 Object 对象

     * @param id String - SQL语句编号

     * @param paramObject - 查询参数

     * @throws SQLException

     * */

    public Object queryForObject(String id, Object paramObject) throws Exception

    {

       System.out.println(id);

       Object obj = sqlMapConfig.queryForObject(id, paramObject);

       if(obj == null)

       {

           System.out.println("**** 结果集为空 ****");

            System.out.println("--------------------------");

           return null;

       }

      

       Method method = obj.getClass().getMethod("display");

       method.invoke(obj);

       //((User)obj).display();

       return obj;

    }

      

    /**

     * 查询,返回 List 对象

     * @param id String - SQL语句编号

     * @param paramObject - 查询参数

     * @throws Exception

     * */

    public List queryForList(String id, Object paramObject) throws Exception

    {

       System.out.println(id);

       List list = sqlMapConfig.queryForList(id, paramObject);

      

       if(list.size() == 0)

       {

           System.out.println("**** 结果集为空 ****");

            System.out.println("--------------------------");

           return null;

       }

      

       for(int i=0; i<list.size(); i++)

       {

           Method method = list.get(i).getClass().getMethod("display");

           method.invoke(list.get(i));

           //((User)list.get(i)).display();

       }

       return list;

    }

   

 

9. 测试语句

测试单条结果、多条结果返回情况;复杂类型参数情况,自定义映射类型结果情况;多个输入参数情况。

 

获取数据库连接方法:[反射机制]建立数据库连接]

 

关键代码:

 

    public static void main(String[] args) throws Exception

    {

       User user = new User();

       user.setId(1);

       user.setUsername("jarg");

       user.setPassword("jarg");

      

       User2 user2 = new User2();

       user2.setId(2);

       user2.setName("yeshaoting");

       user2.setPwd("yeshaoting");

      

       Map<String, String> model = new HashMap<String, String>();

       model.put("id", "3");

       model.put("username", "admin");

       model.put("password", "admin");

      

       List<Object> list = new ArrayList<Object>();

       list.add("admin");

       list.add("admin");

      

       SqlMapBuilder builder = SqlMapBuilder.build("com/iteye/jarg/resources/mapper-config.xml");

      

       Object obj = null;

      

       //query

       obj = builder.queryForObject("query", user2);

      

       //queryUserById2

       obj = builder.queryForObject("queryUserById2", model);

      

       //queryUserById, queryUserByUsername, queryUserWithMap, queryUserWithList

       obj = builder.queryForObject("queryUserById", 1);

       obj = builder.queryForObject("queryUserByUsername", "yeshaoting");

       obj = builder.queryForObject("queryUserWithMap", model);

       obj = builder.queryForObject("queryUserWithList", list);

       obj = builder.queryForObject("queryUser", null);

      

       //queryUsersById, queryUsersByUsername, queryUsersWithMap, queryUsersWithList, queryAllUser

       obj = builder.queryForList("queryUsersById", 1);

       obj = builder.queryForList("queryUsersByUsername", "yeshaoting");

       obj = builder.queryForList("queryUsersWithMap", model);

       obj = builder.queryForList("queryUsersWithList", list);

       obj = builder.queryForList("queryAllUser", null);

      

    }

 

输出结果:

query

id: 2

name:  yeshaoting

pwd:   yeshaoting

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

queryUserById2

key:id

id: 3

name:  admin

pwd:   admin

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

queryUserById

id: 1

username:  jarg

password:  jarg

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

queryUserByUsername

id: 2

username:  yeshaoting

password:  yeshaoting

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

queryUserWithMap

key:username

key:password

id: 3

name:  admin

pwd:   admin

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

queryUserWithList

id: 3

username:  admin

password:  admin

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

queryUser

id: 2

username:  yeshaoting

password:  yeshaoting

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

queryUsersById

id: 2

username:  yeshaoting

password:  yeshaoting

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

id: 3

username:  admin

password:  admin

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

queryUsersByUsername

id: 1

username:  jarg

password:  jarg

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

id: 3

username:  admin

password:  admin

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

queryUsersWithMap

key:username

key:password

id: 1

name:  jarg

pwd:   jarg

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

id: 2

name:  yeshaoting

pwd:   yeshaoting

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

queryUsersWithList

id: 1

username:  jarg

password:  jarg

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

id: 2

username:  yeshaoting

password:  yeshaoting

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

queryAllUser

id: 1

username:  jarg

password:  jarg

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

id: 2

username:  yeshaoting

password:  yeshaoting

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

id: 3

username:  admin

password:  admin

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

 

 

1
1
分享到:
评论

相关推荐

    基于Java动态代理和反射机制实现ORM

    在Java中,基于动态代理和反射机制实现ORM可以提高代码的可维护性和灵活性。本篇文章将深入探讨如何在Java环境下,结合MySQL数据库,利用动态代理和反射技术来实现简单的ORM框架。 首先,我们需要了解动态代理和...

    .net 简单实现orm实例

    本实例将通过反射机制简单实现一个ORM功能,帮助理解其工作原理。 首先,我们要了解反射在.NET中的作用。反射允许程序在运行时检查自身的信息,如类型、属性、方法等,并且能够动态地创建和执行代码。在ORM中,反射...

    C#根据反射和特性实现ORM映射实例分析

    ## C#中的反射和特性实现ORM映射详解 ### (一)反射 反射是.NET框架提供的一种强大的机制,它允许程序在运行时动态地获取类型信息并操作类型。简单来说,反射就是程序在运行时检查自身的能力,能够获取类型的信息...

    C# 通过反射初探ORM框架的实现原理(详解)

    C# 通过反射初探ORM框架的实现原理 在本文中,我们将探讨C# 通过反射初探ORM...在C#中,我们可以使用反射机制来实现简单的ORM框架,通过反射机制,我们可以动态地获取对象的属性和方法,并且可以进行与之相关的调用。

    自定义Orm框架的实现

    这通常通过反射机制完成。 3. **会话工厂(SessionFactory)**:类似Hibernate的SessionFactory,负责创建Session对象,Session是对数据库的一次会话,可以进行CRUD操作。 4. **Session接口**:设计Session接口,...

    反射的应用 一个简单的ORM.rar

    本示例是一个基于C#语言的简单ORM实现,通过反射机制来实现这一功能。下面我们将详细探讨反射、ORM以及它们在这个简单应用中的运用。 **反射**是.NET Framework提供的一种强大特性,允许在运行时检查类型信息,包括...

    基于java 简易ORM 框架实现(二)

    在本篇“基于Java简易ORM框架实现(二)”中,我们将深入探讨如何构建一个简单的对象关系映射(Object-Relational Mapping,ORM)框架。ORM框架是Java开发中常用的一种技术,它允许开发者以面向对象的方式操作数据库,...

    ORM机制 本人的项目开发经验

    3. **JAVA ORM在.NET中的应用问题**:如果尝试将JAVA的ORM设计移植到.NET,可能会遇到每次修改都需要调整反射机制的问题。ORM框架如NickLee.ODRM提供了一个无反射机制的对象层,减少了因修改导致的副作用,使得对象...

    K-ORM 自定义ORM工具

    本文将详细探讨一个名为“K-ORM”的自定义ORM工具,该工具基于JDBC和Java反射机制实现,旨在提供简单易用的数据操作接口。 首先,我们要理解JDBC(Java Database Connectivity)在其中的角色。JDBC是Java平台上的...

    使用java的反射机制来模拟hibernater的jdbc操作

    在本案例中,我们将探讨如何利用反射机制来模拟Hibernate的JDBC操作,实现数据库的增删改查(CRUD)功能,以及简单的分页封装。 首先,让我们了解什么是Hibernate。Hibernate是一个强大的对象关系映射(ORM)框架,...

    Java反射机制

    以下是一个简单的Java反射机制的示例代码,该示例展示了如何使用反射来获取一个类的所有方法,并打印出来: ```java import java.lang.reflect.Method; public class DumpMethods { public static void main...

    反射的使用

    在Java中,反射机制主要通过java.lang.Class类、java.lang.reflect包中的类(如Constructor、Method、Field)来实现。本文将深入探讨Java反射的基本概念、用途、优缺点以及如何使用。 一、什么是Java反射 Java反射...

    自定义Dao,反射实现

    这种方法适用于小型项目或对性能有较高要求的场景,同时也为学习Java反射机制提供了实践机会。 通过这个自定义Dao的例子,我们可以看到在实际开发中如何结合设计模式和语言特性来解决问题。同时,标签“源码”和...

    利用反射实现的持久层工具类(学习)

    本文将深入探讨如何利用反射机制来实现一个简单的持久层工具类,以供学习和参考。 反射是Java提供的一种强大的动态类型特性,它允许我们在运行时检查类的信息,包括类名、属性、方法等,并能够动态地创建对象和调用...

    ehui excel orm框架

    这一框架利用Java的反射机制和Apache POI库,提供了便捷的API,使得开发者可以像操作数据库一样操作Excel文件。 **2. Apache POI的运用** Apache POI是Apache软件基金会的一个开源项目,专门用于读写Microsoft ...

    java反射机制给实体类相同字段自动赋值实例

    在上述的"java反射机制给实体类相同字段自动赋值实例"中,我们看到如何利用反射来实现两个实体类之间相同字段的自动赋值。下面将详细解释这一过程。 1. **创建工具类**: - 在提供的代码中,定义了一个名为`Class...

    java 反射实例,大量注释,简单易懂

    Java反射是Java编程语言中的一个重要特性,它允许程序在...学习这个示例,你可以更好地掌握Java反射机制,如何实例化对象,调用方法以及访问字段。通过实践,你将能够灵活地应用反射到实际项目中,解决动态编程的需求。

Global site tag (gtag.js) - Google Analytics