ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

mybatis详解学习之mybatis中非代理模式设置查询参数时是忽略类型的

2021-07-22 20:34:36  阅读:135  来源: 互联网

标签:null id 详解 org mybatis import 中非 public


非代理使用Mybatis

一、环境搭建

1、pom文件

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.mybatis.source.test</groupId>
	<artifactId>mybatis-pro</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<properties>
		<slf4j-api.version>1.7.25</slf4j-api.version>
		<logback.version>1.1.7</logback.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>ognl</groupId>
			<artifactId>ognl</artifactId>
			<version>3.0.8</version>
		</dependency>
		<dependency>
			<groupId>org.javassist</groupId>
			<artifactId>javassist</artifactId>
			<version>3.24.1-GA</version>
		</dependency>
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.3.0-SNAPSHOT</version>
		</dependency>

		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${slf4j-api.version}</version>
		</dependency>
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-core</artifactId>
			<version>${logback.version}</version>
		</dependency>
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-access</artifactId>
			<version>${logback.version}</version>
		</dependency>
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>${logback.version}</version>
		</dependency>

		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.17</version>
		</dependency>

		<dependency>
			<groupId>commons-logging</groupId>
			<artifactId>commons-logging</artifactId>
			<version>1.2</version>
		</dependency>
		<dependency>
			<groupId>org.apache.logging.log4j</groupId>
			<artifactId>log4j-core</artifactId>
			<version>2.13.3</version>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.16</version>
		</dependency>


	</dependencies>
</project>

2、Mybatis主配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <setting name="lazyLoadingEnabled" value="false"/>
    </settings>
    <typeAliases>
        <typeAlias alias="role" type="com.mybatis.learn.bean.Role"/>
    </typeAliases>
    <typeHandlers>
        <typeHandler jdbcType="VARCHAR" javaType="string" handler="com.mybatis.learn.handler.MyStringHandler"/>
    </typeHandlers>
    <!-- 定义数据库的信息,默认使用development数据库构建环境 -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://localhost:3306/project_crowd?serverTimezone=UTC" />
                <property name="username" value="root" />
                <property name="password" value="123456" />
            </dataSource>
        </environment>
    </environments>
    <!-- 定义映射器 -->
    <mappers>
        <package name="com.mybatis.learn.mapper" />
    </mappers>

</configuration>

3、日志配置文件

log4j.rootLogger=DEBUG,stdout
log4j.logger.org.mybatis=DUBUG
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.logDailyFile.layout.ConversionPattern = %5p %d %C:%m%n

4、mapper配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mybatis.source.test.mapper.RoleMapper">
	<resultMap type="role" id="roleMap">
		<id column="id" property="id" javaType="long" jdbcType="BIGINT" />
		<result column="role_name" property="roleName" javaType="string" jdbcType="VARCHAR" />
		<result column="note" property="note" typeHandler="com.mybatis.source.test.handler.MyStringHandler" />
	</resultMap>
	
	<select id="queryRolesByCondition" parameterType="com.mybatis.source.test.bean.Role" resultMap="roleMap">
		select * from role where
        1=1
        <if test="id!=null">
            and id=#{id,jdbcType=BIGINT}
        </if>
        <if test="roleName!=null">
            and role_name=#{roleName,jdbcType=BIGINT}
        </if>
        <if test="note!=null">
            and note=#{note,jdbcType=BIGINT}
        </if>
        and tenant_id=#{tenantId,jdbcType=VARCHAR}
	</select>
	
	<select id="getRole" parameterType="long" resultMap="roleMap">
		select
		id,role_name as roleName,note from role where id=#{id}
	</select>
	<select id="findRole" parameterType="long" resultMap="roleMap">
		select
		id,role_name,note from role where role_name like CONCAT('%',#{roleName
		javaType=string,
		jdbcType=VARCHAR,typeHandler=com.mybatis.source.test.handler.MyStringHandler},'%')
	</select>
	<insert id="insertRole" parameterType="role">
		insert into
		role(role_name,note) value(#{roleName},#{note})
	</insert>
	<delete id="deleteRole" parameterType="long">
		delete from role where
		id=#{id}
	</delete>
</mapper>

5、mapper接口

package com.mybatis.source.test.mapper;

import java.util.List;

import com.mybatis.source.test.bean.Role;

public interface RoleMapper {
	public Role getRole(Long id);
    public Role findRole(String roleName);
    public int deleteRole(Long id);
    public int insertRole(Role role);
    
    public List<Role> queryRolesByCondition(Role role);
}

二、非代理方式代码执行

1、测试代码

package com.mybatis.source.test.Main;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import com.mybatis.source.test.bean.Role;
import com.mybatis.source.test.mapper.RoleMapper;

public class Main {
	public static void main(String[] args) {
		String resource = "mybatis-config.xml";
		InputStream inputStream = null;
		try {
			inputStream = Resources.getResourceAsStream(resource);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		SqlSessionFactory sqlSessionFactory = null;
		sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		SqlSession sqlSession = null;
		try {
			sqlSession = sqlSessionFactory.openSession();

			Map<String,Object> param=new HashMap<>();
			param.put("id", 1);
			List<Role> list = sqlSession.selectList("com.mybatis.source.test.mapper.RoleMapper.queryRolesByCondition", param);

			sqlSession.commit();

		} catch (Exception e) {
			sqlSession.rollback();
			e.printStackTrace();
		} finally {
			sqlSession.close();
		}
	}
}

2、执行结果

com.mybatis.source.test.mapper.RoleMapper.queryRolesByCondition - ==> 
Preparing: select * from role where 1=1 and id=? and tenant_id=? 
com.mybatis.source.test.mapper.RoleMapper.queryRolesByCondition - ==> Parameters: 1(Integer), null
com.mybatis.source.test.mapper.RoleMapper.queryRolesByCondition - <==      Total: 0

3、结果分析

RoleMapper.queryRolesByCondition接口的入参是Role,但是在测试代码中,我们传入的是Map对象,发现代码也能运行。

其原因是因为参数值的获取是通过MetaObject工具类来获取的,代码如下:

//设置参数
  @Override
  public void setParameters(PreparedStatement ps) throws SQLException {
    ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    if (parameterMappings != null) {
      //循环设参数
      for (int i = 0; i < parameterMappings.size(); i++) {
        ParameterMapping parameterMapping = parameterMappings.get(i);
        if (parameterMapping.getMode() != ParameterMode.OUT) {
          //如果不是OUT,才设进去
          Object value;
          String propertyName = parameterMapping.getProperty();
          if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
            //若有额外的参数, 设为额外的参数
            value = boundSql.getAdditionalParameter(propertyName);
          } else if (parameterObject == null) {
            //若参数为null,直接设null
            value = null;
          } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
            //若参数有相应的TypeHandler,直接设object
            value = parameterObject;
          } else {
            //除此以外,MetaObject.getValue反射取得值设进去
            MetaObject metaObject = configuration.newMetaObject(parameterObject);
            value = metaObject.getValue(propertyName);
          }
          TypeHandler typeHandler = parameterMapping.getTypeHandler();
          JdbcType jdbcType = parameterMapping.getJdbcType();
          if (value == null && jdbcType == null) {
            //不同类型的set方法不同,所以委派给子类的setParameter方法
            jdbcType = configuration.getJdbcTypeForNull();
          }
          typeHandler.setParameter(ps, i + 1, value, jdbcType);
        }
      }
    }
  }

4、MetaObject测试

采用MetaObject工具类,并不关心对象是什么样的类型,只要给出对象中有什么属性,就可以通过工具类拿到对象对应的属性的值

package com.mybatis.learn.main;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

class Person{
    private String name;
    private String address;

    public Person(String name, String address) {
        this.name = name;
        this.address = address;
    }
}
public class MetaObjectTest {
    static SqlSessionFactory sqlSessionFactory = null;

    static{
        String resource = "mybatis-config.xml";
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    public static void main(String[] args) {
        List<String> fieldNameList=new ArrayList<>();
        fieldNameList.add("name");
        fieldNameList.add("address");
        Map<String,String> map=new HashMap<>();
        map.put("name","张三");
        map.put("address","杭州市");
        //可以访问map中属性为name与address的值
        printFieldValue(map,fieldNameList);
        System.out.println("+++++++++++++++++++++++++");
        Person person=new Person("王五","北京市");
        // 可以访问对象中属性为name与address的值
        printFieldValue(person,fieldNameList);

    }

    public static void printFieldValue(Object obj, List<String> fieldNames){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        Configuration configuration = sqlSession.getConfiguration();
        MetaObject metaObject=configuration.newMetaObject(obj);
        for (String fieldName:fieldNames){
            Object value = metaObject.getValue(fieldName);
            System.out.println(value);
        }
    }
    
    // 模拟MetaObject对象的getValue方法
     public static void printFieldByReflect(Object obj, List<String> fieldNames){
        if(obj instanceof Map){
            Map<String,Object> map=( Map<String,Object>)obj;
            for(String fieldName:fieldNames){
                System.out.println(map.get(fieldName));
            }

        }else if(obj instanceof Collection){

        }else if(obj != null && obj.getClass().isArray()){

        }else{
            Class<?> aClass = obj.getClass();
            for(String fieldName:fieldNames){
                try{
                    Field field = aClass.getDeclaredField(fieldName);
                    field.setAccessible(true);
                    Object o = field.get(obj);
                    System.out.println(o);

                }catch (Exception e){
                    e.printStackTrace();
                }

            }
        }


    }


}

所以在Mybatis对象设置参数值时,一般并不会去校验对象的类型,只关注对象中是否有相应的属性。

标签:null,id,详解,org,mybatis,import,中非,public
来源: https://www.cnblogs.com/cplinux/p/15046110.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有