mybatis 对 #{ } 和 ${ }的不同处理方式

合集下载

mybatis对象传参数

mybatis对象传参数

mybatis对象传参数MyBatis 是一个流行的持久层框架,它允许开发人员使用 Java 对象来映射数据库操作。

在 MyBatis 中,传递参数给 SQL 语句可以通过多种方式实现,包括以下几种常见的方式:1. 单个参数:你可以直接将一个对象作为参数传递给 SQL 语句。

在 XML 映射文件中,你可以使用 #{propertyName} 的方式引用对象的属性,例如:xml.<select id="getUserById" parameterType="int" resultType="User">。

SELECT FROM users WHERE id = #{userId}。

</select>。

在这个例子中,userId 是传递给 SQL 语句的参数,它会被映射到传入的对象的属性上。

2. 多个参数:如果你需要传递多个参数,可以使用 @Param 注解为参数起别名,然后在 SQL 语句中引用这些别名。

例如:java.User getUserByIdAndName(@Param("id") int id,@Param("name") String name);xml.<select id="getUserByIdAndName" parameterType="map" resultType="User">。

SELECT FROM users WHERE id = #{id} AND name = #{name}。

</select>。

在这个例子中,id 和 name 分别是传递给 SQL 语句的参数别名,它们会被映射到传入的参数中。

3. 使用 Map:你也可以直接将一个 Map 对象作为参数传递给SQL 语句,然后在 SQL 语句中引用 Map 中的键。

07Mybatis的多表查询1----1对多和多对1---@Results注解用法总结

07Mybatis的多表查询1----1对多和多对1---@Results注解用法总结

07Mybatis的多表查询1----1对多和多对1---@Results注解⽤法总结1.表与表之间的关系及其举例表之间的关系有4种:⼀对多、多对⼀、⼀对⼀、多对多。

举例: (1)⽤户和订单就是⼀对多 ⼀个⽤户可以下多个订单 (2)订单和⽤户就是多对⼀ 多个订单属于同⼀个⽤户 (3)⼈和⾝份证号就是⼀对⼀ ⼀个⼈只能有⼀个⾝份证号 ⼀个⾝份证号只能属于⼀个⼈ (4)⽼师和学⽣之间就是多对多 ⼀个学⽣可以被多个⽼师教过 ⼀个⽼师可以交多个学⽣2.mybatis中的多表查询⽰例:⽤户和账户 ⼀个⽤户可以有多个账户 ⼀个账户只能属于⼀个⽤户(多个账户也可以属于同⼀个⽤户)步骤: 1、建⽴两张表:⽤户表,账户表 让⽤户表和账户表之间具备⼀对多的关系:需要使⽤外键在账户表中添加 2、建⽴两个实体类:⽤户实体类和账户实体类 让⽤户和账户的实体类能体现出来⼀对多的关系 3、建⽴两个配置⽂件 ⽤户的配置⽂件 账户的配置⽂件 4、实现配置: 当我们查询⽤户时,可以同时得到⽤户下所包含的账户信息 当我们查询账户时,可以同时得到账户的所属⽤户信息3.@Results注解⽤法总结:MyBatis中使⽤@Results注解来映射查询结果集到实体类属性。

(1)@Results的基本⽤法。

当数据库字段名与实体类对应的属性名不⼀致时,可以使⽤@Results映射来将其对应起来。

column为数据库字段名,porperty为实体类属性名,jdbcType为数据库字段数据类型,id为是否为主键。

@Select({"select id, name, class_id from my_student"})@Results({@Result(column="id", property="id", jdbcType=JdbcType.INTEGER, id=true),@Result(column="name", property="name", jdbcType=JdbcType.VARCHAR),@Result(column="class_id", property="classId", jdbcType=JdbcType.INTEGER)})List<Student> selectAll();如上所⽰的数据库字段名class_id与实体类属性名classId,就通过这种⽅式建⽴了映射关系。

Mybatis对oracle数据库进行foreach批量插入操作

Mybatis对oracle数据库进行foreach批量插入操作

Mybatis对oracle数据库进⾏foreach批量插⼊操作MySQL⽀持的语法INSERT INTO `tableX` (`a`,`b`,`c`,`d`,`e`) VALUES<foreach collection ="list" item="param" index= "index" separator =",">(param.a,param.b,param.c,param.d,param.e)</foreach>oracle语法insert into tableX(a,b,c)select*from (select1,2,3from dualunionselect4,5,6from dual) t在使⽤mybatis时,oracle需要写成下⾯格式<foreach collection="list" item="file" index="index" separator="UNION">最近做⼀个批量导⼊的需求,将多条记录批量插⼊数据库中。

解决思路:在程序中封装⼀个List集合对象,然后把该集合中的实体插⼊到数据库中,因为项⽬使⽤了MyBatis,所以打算使⽤MyBatis的foreach功能进⾏批量插⼊。

期间遇到了“SQL 命令未正确结束 ”的错误,最终解决,记录下来供以后查阅和学习。

⾸先,在⽹上参考了有关Mybatis的foreach insert的,具体如下:foreach的主要⽤在构建in条件中,它可以在SQL语句中进⾏迭代⼀个集合。

foreach元素的属性主要有 item,index,collection,open,separator,close。

item表⽰集合中每⼀个元素进⾏迭代时的别名,index指定⼀个名字,⽤于表⽰在迭代过程中,每次迭代到的位置,open表⽰该语句以什么开始,separator表⽰在每次进⾏迭代之间以什么符号作为分隔符,close表⽰以什么结束,在使⽤foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须指定的,但是在不同情况下,该属性的值是不⼀样的,主要有⼀下3种情况:1.如果传⼊的是单参数且参数类型是⼀个List的时候,collection属性值为list2.如果传⼊的是单参数且参数类型是⼀个array数组的时候,collection的属性值为array3.如果传⼊的参数是多个的时候,我们就需要把它们封装成⼀个Map了,当然单参数也可以封装成map然后,照葫芦画瓢写了如下的xml⽂件,xxxMapper.xml⽂件:<insert id="addSupCity" parameterType="java.util.List"><selectKey keyProperty="cityId" order="BEFORE" resultType="String"><![CDATA[SELECT SEQ_OCL_SUPCITY.NEXTVAL FROM dual]]></selectKey>INSERT INTO T_OCL_SUPCITY(CITY_ID,CITY_CODE, CITY_NAME, AREA_DESC, SUP_ID, STAT)VALUES<foreach collection="list" item="item" index="index" separator=",">(#{item.cityId,jdbcType=VARCHAR},#{item.cityCode,jdbcType=VARCHAR},#{item.cityName,jdbcType=VARCHAR},#{item.areaDesc,jdbcType=VARCHAR},#{item.supId,jdbcType=VARCHAR},#{item.stat,jdbcType=VARCHAR})</foreach></insert>但是运⾏起来后就⼀直报错,报错信息如下:### SQL: INSERT INTO T_OCL_SUPCITY(CITY_ID,CITY_CODE, CITY_NAME, AREA_DESC, SUP_ID, STAT) VALUES (?,?,?,?,?),(?,?,?,?,?)### Cause: java.sql.SQLSyntaxErrorException: ORA-00933: SQL 命令未正确结束把SQL复制出来在PL/SQL中运⾏也是报同样的错,如上也可以看出,使⽤批量插⼊执⾏的SQL语句等价于: INSERT INTOT_OCL_SUPCITY (CITY_ID,CITY_CODE, CITY_NAME, AREA_DESC, SUP_ID, STAT) VALUES (?,?,?,?,?),(?,?,?,?,?),⽽在oracle中⽤insert into xxx values (xxx,xxx),(xxx,xxx) 这种语法是通不过的。

【Mybatis】Mybatis实战2(一对一、一对多、多对多的设计及实现,高级特性及二级缓存)

【Mybatis】Mybatis实战2(一对一、一对多、多对多的设计及实现,高级特性及二级缓存)

【Mybatis】Mybatis实战2(⼀对⼀、⼀对多、多对多的设计及实现,⾼级特性及⼆级缓存)6).多表查询-“⼀对多”(表设计、实体设计、DAO(mapper)设计)(1)关联关系操作(⼀对多)①表设计:以员⼯和部门表为例思想: 1个员⼯对应1个部门,1个部门对应多个员⼯添加数据原则:先添加没有外键的数据(部门信息),再添加存在外键的数据(员⼯信息)注意:将外键添加在n的⼀⽅部门表:create table t_dept(id varchar2(36) primary key,name varchar2(50));员⼯表:create table t_emp(id varchar2(36) primary key,name varchar2(50),age number(3),salary number(10,2),dept_id references t_dept(id));②实体设计a. 在实体中添加关系属性,来表⽰实体之间的关系(对应表数据的关系)b. 在N的⼀⽅添加1的⼀个关系属性。

c. 在1的⼀⽅添加N的⼀个List的关系属性DAO:(MyBatis如何查询两张表信息)需求1:查询员⼯信息(⼯号,名字,年龄,薪资,所属部门的编号和名称)根据员⼯⼯号?DAO接⼝⽅法:public Emp selectById(String id);Mapper⽂件:①SQL:select e.id,,e.age,e.salary,d.id, from t_emp e left join t_dept d on e.dept_id = d.id where e.id = '5';②参数③将查询结果映射成⼀个实体对象特点: 如果关系属性是”1” ,使⽤ <association></association>需求2:根据id查询部门信息,及其内部的所有员⼯信息?DAO接⼝⽅法:public Dept selectById(String id);Mapper⽂件中①SQL:select d.id,,e.id as eid, as ename,e.age as eage,e.salary as salary from t_dept d left join t_emp e on d.id = e.dept_idwhere d.id = ?;②参数绑定③结果映射:ReusultMap映射集合关系属性特点: 关系属性是”n”个的集合 ,使⽤ <collection></ collection >7).多表查询-“⼀对⼀”(表设计、实体设计、DAO(mapper)设计)关联关系操作(⼀对⼀)例如:需求: 学⽣电脑管理系统①库表设计表⽰1对1的关系a. 添加外键(那张表添加都可以)①从业务的⾓度分析,后添加的数据对应的表。

mybatis中字段与实体匹配规则

mybatis中字段与实体匹配规则

mybatis中字段与实体匹配规则MyBatis是一个持久层框架,可以将数据库表中的数据映射到Java对象上,并提供了丰富的SQL操作方法,使得开发者能够更简便地进行数据库操作。

在MyBatis中,字段与实体的匹配规则是很重要的,它影响着数据的映射、查询、更新等操作。

下面将详细介绍MyBatis中字段与实体的匹配规则。

1. 实体类的命名规范:在MyBatis中,实体类一般与数据库表进行一对一的映射。

为了方便理解和维护,实体类的命名应该与数据库表的命名保持一致。

一般情况下,实体类名采用驼峰命名法,而数据库表名采用下划线命名法。

例如,数据库表名为"user_info",则对应的实体类名为"UserInfo"。

2. 字段与属性的映射规则:MyBatis中的字段与实体类中的属性进行映射。

一般情况下,字段名采用下划线命名法,而属性名采用驼峰命名法。

例如,数据库表的字段名为"user_name",则对应的实体类的属性名为"userName"。

如果字段名与属性名不一致,可以通过在属性上使用@Results注解进行映射。

3. 数据类型的转换规则:MyBatis会根据实体类中属性的类型自动进行数据类型的转换。

MyBatis支持的数据类型包括基本数据类型、包装类、String、Date等。

在映射过程中,如果数据库表中的数据类型与实体类中属性的类型不匹配,MyBatis会自动进行类型转换。

4. 实体类中的关联关系:当数据库中存在表之间的关联关系时,实体类之间也应该有对应的关联关系。

MyBatis提供了@One和@Many注解来表示一对一和一对多的关系。

通过关联关系,可以在查询时级联查询相关联的实体类。

5. 配置文件中的映射规则:除了上述的映射规则之外,MyBatis还提供了配置文件mybatis-config.xml和映射文件Mapper.xml来进一步规定字段与实体的映射规则。

mybatis映射对象原理

mybatis映射对象原理

Mybatis映射对象原理一、什么是Mybatis1.1 Mybatis的定义Mybatis是一种开源的Java持久化框架,它可以将SQL查询、存储过程和高级映射成对象的方法进行封装,使开发人员能够更加方便地进行数据库操作。

1.2 Mybatis的优势•灵活性:Mybatis允许开发人员使用原生的SQL查询,不需要强制转换为对象。

•易于学习:Mybatis的配置相对简单,易于理解和上手。

•可定制性:Mybatis支持自定义映射规则,可以灵活地进行对象和数据库的映射。

•可靠性:Mybatis具有良好的事务支持,能够保证数据的一致性和完整性。

二、Mybatis映射对象的概念2.1 映射对象的定义映射对象是指数据库表和Java对象之间的映射关系,通过指定映射规则,将数据库表中的字段和Java对象的属性进行一一对应,从而实现数据的存取和转换。

2.2 Mybatis映射对象的作用•简化数据库操作:通过映射对象,我们可以直接操作Java对象,而无需关注SQL查询和数据库细节。

•提高开发效率:映射对象可以自动生成SQL语句,减少手动编写SQL的工作量。

•提高代码可维护性:通过映射对象,我们可以将SQL语句和Java对象关联起来,便于代码的维护和修改。

三、Mybatis映射对象的配置3.1 配置文件Mybatis的映射对象配置主要通过XML文件进行,可以使用文本编辑器打开配置文件,对映射对象进行配置。

3.2 映射文件Mybatis的映射对象配置主要包括两个部分:SQL语句和结果映射。

3.2.1 SQL语句SQL语句是映射对象的核心部分,通过SQL语句,我们可以对数据库进行增删改查操作。

在映射文件中,可以使用预编译的SQL语句,也可以使用动态SQL语句。

3.2.2 结果映射结果映射是指数据库查询结果和Java对象之间的映射关系。

通过结果映射,我们可以将查询结果集中的列和Java对象的属性进行一一对应。

四、Mybatis映射对象的实现原理4.1 动态代理Mybatis的映射对象是通过动态代理技术实现的。

总结一下mybatis对多对多查询与增删改查的心得

总结一下mybatis对多对多查询与增删改查的心得

总结一下mybatis对多对多查询与增删改查的心得引言在实际的开发中,多对多关联关系是经常遇到的问题,而m yba t is作为一款高效的持久层框架,为我们提供了便捷的解决方案。

本文将总结一下通过m yb at is对多对多关系进行查询和增删改查的心得。

查询多对多关系在m yb at is中,查询多对多关系可以通过嵌套查询和关联表查询来实现。

嵌套查询嵌套查询是通过在映射文件中定义多个查询语句,并通过r esu l tM ap来关联结果,从而实现多对多关系的查询。

具体步骤如下:1.在映射文件中定义多个s el ec t语句,分别查询两个关联表的数据。

2.使用\<re su lt Map>标签定义一个结果映射,包括两个关联表的字段。

3.在主查询语句中使用\<co ll ec ti on>标签来引用结果映射和关联查询语句。

4.使用联合结果映射来获取最终查询结果。

关联表查询关联表查询是通过多表联查来实现多对多关系的查询。

具体步骤如下:1.在映射文件中编写多表联查的SQ L语句,使用J OI N语句关联两个关联表。

2.在\<s el ec t>标签中使用\<re su lt Ma p>定义结果映射,包括两个关联表的字段。

3.在J av a代码中编写相应的Ma pp er接口和Ma pp er.x ml文件。

4.调用Ma pp er接口中的方法来执行查询操作。

增删改查多对多关系m y ba ti s对多对多关系的增删改查操作也是通过多表关联来实现的。

增加记录要增加多对多关系的记录,需要进行以下操作:1.在映射文件中定义插入操作的SQ L语句,插入关联表的数据。

2.在J av a代码中编写相应的Ma pp er接口和Ma pp er.x ml文件。

3.调用Ma pp er接口中的方法来执行插入操作。

删除记录要删除多对多关系的记录,需要进行以下操作:1.在映射文件中定义删除操作的SQ L语句,删除关联表的数据。

mybatis对string类型判断比较groupcasewhenthen综合

mybatis对string类型判断比较groupcasewhenthen综合

mybatis对string类型判断⽐较groupcasewhenthen综合[quote]特别注意两点⼀个是where 的⽤法group的⽤法case when的⽤法<if test='hasLoanApplicationFlag == "1"'>这个对string的⽐较是单引号括起test后⾯的整串,然后 == 然后双引号括起⽐较的字符串内容[/quote][quote]<select id="querySalesmanAndLoanInfoList" parameterType="com.zyd.orders.placeorder.model.SalesmanDO"resultType="com.zyd.orders.placeorder.model.SalesmanDO">select T.salesmanId, T.salesmanCode, T.salesmanName, T.idNo, T.idType,T.phoneNo, T.channelId,T.registerDate, T.profession, T.email, T.sumLoanAppCount, T.sumInProgressCount, T.sumFailLoanCount,T.sumReleaseCount,T.sumReleaseAmount ,T.channelNamefrom(SELECTs.salesman_id as salesmanId,s.salesman_code as salesmanCode,s.salesman_name as salesmanName,s.id_no as idNo,s.id_type as idType,s.phone_no as phoneNo,s.channel_id as channelId,s.register_date as registerDate,s.profession as profession,s.email as email,s.login_total_times,count(case when ob.apply_status > 0 then ob.apply_status end) as sumLoanAppCount,count(case when ob.apply_status > 1 and ob.apply_status < 6 then ob.apply_status end) as sumInProgressCount,count(case when ob.apply_status = 7 then ob.apply_status end) as sumFailLoanCount,count(case when ob.release_status = 1 then ob.release_status end) as sumReleaseCount,sum(case when ob.release_status = 1 then ob.release_money end) as sumReleaseAmount,c.channel_name as channelNamefrom salesman s left join order_base obon s.salesman_id = er_idleft join channel_vendor con s.channel_id = c.channel_id<where><if test="salesmanId != null and salesmanId != ''">AND s.salesman_id = #{salesmanId}</if><if test="phoneNo != null and phoneNo != ''">AND s.phone_no = #{phoneNo}</if><if test="password != null and password != ''">AND s.password = #{password}</if><if test="salesmanName != null and salesmanName != ''">AND s.salesman_name = #{salesmanName}</if><if test="idNo != null and idNo != ''">AND s.id_no = #{idNo}</if><if test="cardNo != null and cardNo != ''">AND s.card_no = #{cardNo}</if><if test="loanApplicationCode != null and loanApplicationCode != ''">AND ob.id = #{loanApplicationCode}</if><if test="registerBeginDate != null">AND s.register_date >= #{registerBeginDate}</if><if test="registerEndDate != null">AND s.register_date <= #{registerEndDate}</if></where>group bys.salesman_id,s.salesman_code,s.salesman_name,s.id_no,s.id_type,s.phone_no,s.channel_id,s.register_date,s.profession,s.email,s.login_total_times ) T<where><if test='hasLoanApplicationFlag == "1"'>AND T.sumLoanAppCount > 0</if></where></select>[/quote][quote]select * from (SELECTs.salesman_id as salesmanId,s.salesman_name as salesmanName,s.id_no as idNo,s.id_type as idType,s.phone_no as phoneNo,s.channel_id as channelId,s.register_date as registerDate,s.profession as profession,s.email as email,count(case when ob.apply_status = 7 then ob.apply_status else 0 end) as reject_count,count(case when ob.apply_status > 1 and ob.apply_status < 6 then ob.apply_status else 0 end) as inprogress_count,count(case when ob.apply_status > 0 then ob.apply_status else 0 end) as total_count,count(case when ob.release_status = 1 then ob.apply_status else 0 end) as release_status,sum(case when ob.release_status = 1 then ob.release_money else 0 end) as total_release_amtfrom salesman s left join order_base obon s.salesman_id = er_idwhere s.salesman_id = 1group by s.salesman_id,s.salesman_name,s.id_no,s.id_type,s.phone_no,s.channel_id,s.register_date,s.profession,s.email) t[/quote]。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

mybatis 中使用sqlMap 进行sql 查询时,经常需要动态传递参数,例如我们需要根据用户的姓名来筛选用户时,sql 如下:select * from user where name = "ruhua";上述sql 中,我们希望name 后的参数"ruhua" 是动态可变的,即不同的时刻根据不同的姓名来查询用户。

在sqlMap 的xml 文件中使用如下的sql 可以实现动态传递参数name:select* from user where name = #{name};或者select* from user where name = '${name}';对于上述这种查询情况来说,使用#{ } 和${ } 的结果是相同的,但是在某些情况下,我们只能使用二者其一。

'#' 与'$'区别动态SQL是mybatis 的强大特性之一,也是它优于其他ORM 框架的一个重要原因。

mybatis 在对sql 语句进行预编译之前,会对sql 进行动态解析,解析为一个BoundSql 对象,也是在此处对动态SQL 进行处理的。

在动态SQL 解析阶段,#{ } 和${ } 会有不同的表现:#{ } 解析为一个JDBC 预编译语句(prepared statement)的参数标记符。

例如,sqlMap 中如下的sql 语句select * from user where name = #{name};解析为:select * from user where name = ?;一个#{ } 被解析为一个参数占位符?。

而,${ } 仅仅为一个纯碎的string 替换,在动态SQL 解析阶段将会进行变量替换例如,sqlMap 中如下的sqlselect * from user where name = '${name}';当我们传递的参数为"ruhua" 时,上述sql 的解析为:select * from user where name = "ruhua";预编译之前的SQL 语句已经不包含变量name 了。

综上所得,${ } 的变量的替换阶段是在动态SQL 解析阶段,而#{ }的变量的替换是在DBMS 中。

用法tips1、能使用#{ } 的地方就用#{ }首先这是为了性能考虑的,相同的预编译sql 可以重复利用。

其次,${ } 在预编译之前已经被变量替换了,这会存在sql 注入问题。

例如,如下的sql,select * from ${tableName} where name = #{name}假如,我们的参数tableName 为user; delete user; --,那么SQL 动态解析阶段之后,预编译之前的sql 将变为select * from user; delete user; -- where name = ?;--之后的语句将作为注释,不起作用,因此本来的一条查询语句偷偷的包含了一个删除表数据的SQL!2、表名作为变量时,必须使用${ }这是因为,表名是字符串,使用sql 占位符替换字符串时会带上单引号'',这会导致sql 语法错误,例如:select * from #{tableName} where name = #{name};预编译之后的sql 变为:select * from ? where name = ?;假设我们传入的参数为tableName = "user" , name = "ruhua",那么在占位符进行变量替换后,sql 语句变为select * from'user'where name='ruhua';上述sql 语句是存在语法错误的,表名不能加单引号''(注意,反引号``是可以的)。

sql预编译定义sql 预编译指的是数据库驱动在发送sql 语句和参数给DBMS 之前对sql 语句进行编译,这样DBMS 执行sql 时,就不需要重新编译。

为什么需要预编译JDBC 中使用对象PreparedStatement 来抽象预编译语句,使用预编译1.预编译阶段可以优化sql 的执行。

预编译之后的sql 多数情况下可以直接执行,DBMS 不需要再次编译,越复杂的sql,编译的复杂度将越大,预编译阶段可以合并多次操作为一个操作。

2.3.预编译语句对象可以重复利用。

把一个sql 预编译后产生的PreparedStatement 对象缓存下来,下次对于同一个sql,可以直接使用这个缓存的PreparedState 对象。

4.mybatis 默认情况下,将对所有的sql 进行预编译。

mysql预编译源码解析mysql 的预编译源码在com.mysql.jdbc.ConnectionImpl类中,如下:public synchronized java.sql.PreparedStatement prepareStatement(String s ql,int resultSetType, int resultSetConcurrency) throws SQLExc eption {checkClosed();//// FIXME: Create warnings if can't create results of the given// type or concurrency//PreparedStatement pStmt = null;boolean canServerPrepare = true;// 不同的数据库系统对sql进行语法转换String nativeSql = getProcessEscapeCodesForPrepStmts() ? nativ eSQL(sql): sql;// 判断是否可以进行服务器端预编译if(eServerPreparedStmts && getEmulateUnsupportedPstm ts()) {canServerPrepare = canHandleAsServerPreparedStatement(n ativeSql);}// 如果可以进行服务器端预编译if(eServerPreparedStmts && canServerPrepare) {// 是否缓存了PreparedStatement对象if(this.getCachePreparedStatements()) {synchronized(this.serverSideStatementCache) {// 从缓存中获取缓存的PreparedStatement对象pStmt = (com.mysql.jdbc.ServerPreparedStatement) this.serverSideStatementCache.remove(sql);if(pStmt != null) {// 缓存中存在对象时对原sqlStatement 进行参数清空等((com.mysql.jdbc.ServerPreparedStatement)pSt mt).setClosed(false);pStmt.clearParameters();}if(pStmt == null) {try{// 如果缓存中不存在,则调用服务器端(数据库)进行预编译pStmt = ServerPreparedStatement.getIn stance(getLoadBalanceSafeProxy(), nativeSql,this.database, resultSetType, re sultSetConcurrency);if(sql.length() < getPreparedStatementC acheSqlLimit()) {((com.mysql.jdbc.ServerPreparedStat ement)pStmt).isCached = true;}// 设置返回类型以及并发类型pStmt.setResultSetType(resultSetType);pStmt.setResultSetConcurrency(resultSetC oncurrency);} catch(SQLException sqlEx) {// Punt, if necessaryif(getEmulateUnsupportedPstmts()) {pStmt = (PreparedStatement) clien tPrepareStatement(nativeSql, resultSetType, resultSetConcurrency, false);if(sql.length() < getPreparedStatem entCacheSqlLimit()) {this.serverSideStatementCheckC ache.put(sql, Boolean.FALSE);}} else{throw sqlEx;}}}}} else{// 未启用缓存时,直接调用服务器端进行预编译try{pStmt = ServerPreparedStatement.getInstance(get LoadBalanceSafeProxy(), nativeSql,this.database, resultSetType, resultSetCo ncurrency);pStmt.setResultSetType(resultSetType);pStmt.setResultSetConcurrency(resultSetConcurrenc y);} catch(SQLException sqlEx) {// Punt, if necessaryif(getEmulateUnsupportedPstmts()) {pStmt = (PreparedStatement) clientPrepareS tatement(nativeSql, resultSetType, resultSetConcurrency, false);} else{throw sqlEx;}}}} else{// 不支持服务器端预编译时调用客户端预编译(不需要数据库connec tion )pStmt = (PreparedStatement) clientPrepareStatement(nativ eSql, resultSetType, resultSetConcurrency, false);}return pStmt;}流程图如下所示:mybatis之sql动态解析以及预编译源码mybatis sql 动态解析mybatis 在调用connection 进行sql 预编译之前,会对sql语句进行动态解析,动态解析主要包含如下的功能:∙占位符的处理∙∙动态sql的处理∙∙参数类型校验∙mybatis强大的动态SQL功能的具体实现就在此。

相关文档
最新文档