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]。

javamybatis框架 对小括号的使用

javamybatis框架 对小括号的使用

javamybatis框架对小括号的使用全文共四篇示例,供读者参考第一篇示例:在使用MyBatis框架时,我们经常会遇到需要使用小括号的情况。

小括号在Java语言中被广泛应用,它可以被用来表示方法的参数、条件语句、数学表达式等等。

在MyBatis框架中,小括号的使用也是必不可少的,它可以帮助我们更清晰地表达我们的SQL语句,同时也可以有效地避免歧义和错误。

我们要了解在MyBatis中小括号的常见用法。

在MyBatis的SQL 语句中,小括号通常被用来表示条件语句或者用来括住子查询等。

在进行复杂的查询时,我们可以使用小括号来明确表示查询条件的优先级,避免因为优先级问题导致查询结果错误。

小括号还可以用来进行逻辑运算,比如AND、OR等操作符的组合,方便我们编写更加灵活的SQL语句。

除了在SQL语句中的使用外,小括号在MyBatis的Mapper接口中也经常会出现。

在进行查询操作时,我们通常会在Mapper接口的方法中定义查询参数,这些参数往往是通过小括号的形式传递给SQL语句的,以便于MyBatis框架能够正确地将参数传递给数据库,并返回正确的查询结果。

小括号在MyBatis中还可以用来表示动态SQL语句。

在实际开发中,我们经常会遇到需要动态拼接SQL语句的情况,比如根据不同的条件来拼接查询语句,这时就可以使用MyBatis提供的动态SQL功能来实现。

在动态SQL中,小括号可以起到分组、逻辑判断的作用,方便我们根据不同的条件来动态生成SQL语句,避免写多个相似的SQL 语句。

小括号在MyBatis框架中扮演着重要的角色,它可以帮助我们更清晰地表达SQL语句,避免歧义和错误,提升开发效率。

通过合理地运用小括号,我们可以更轻松地编写复杂的SQL语句,实现灵活、高效的数据库操作。

在学习和使用MyBatis框架时,我们要深入了解小括号的使用规范,熟练掌握它的各种用法,以便更好地发挥MyBatis 框架的强大功能。

mybatis调用对象get方法

mybatis调用对象get方法

mybatis调用对象get方法一、概述MyBatis是一款优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射。

在MyBatis中,可以通过调用对象的get方法来获取相应的属性值。

本文档将介绍如何使用MyBatis调用对象get方法。

二、准备工作1.确保已经正确配置了MyBatis环境,包括MyBatis的配置文件和数据源等。

2.准备需要操作的对象,这些对象应该具有相应的get方法。

三、调用步骤1.建立与数据库的连接,并获取SqlSession对象。

2.创建Mapper接口,并实现相应的查询方法。

3.在查询方法中,通过SqlSession对象获取对象实例。

4.调用对象的get方法,获取需要操作的属性值。

5.根据需要,对获取的属性值进行处理或返回。

四、示例代码以下是一个简单的示例代码,演示了如何使用MyBatis调用对象的get方法:```java//建立SqlSession对象SqlSessionsession=sqlSessionFactory.openSession();try{//获取Mapper接口对象UserMappermapper=session.getMapper(UserMapper.class);//执行查询操作,获取对象实例Useruser=mapper.selectUser(1);//调用对象的get方法获取属性值Stringname=user.getName();intage=user.getAge();//处理获取的属性值,例如输出到控制台System.out.println("Name:"+name);System.out.println("Age:"+age);}finally{//关闭SqlSession对象session.close();}```五、注意事项1.在调用get方法之前,需要确保对象实例已经被正确加载到内存中。

MyBatis一对一映射初识教程

MyBatis一对一映射初识教程

MyBatis⼀对⼀映射初识教程MyBatis是⼀个⽀持普通SQL查询,存储过程和⾼级映射的优秀持久层框架。

MyBatis消除了⼏乎所有的JDBC代码和参数的⼿⼯设置以及对结果集的检索封装。

MyBatis可以使⽤简单的XML或注解⽤于配置和原始映射,将接⼝和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。

⼀对⼀映射在⽣活中,⼀对⼀的例⼦还是有的,⽐如啦,学⽣和⾝份证哦,或者在我国,实⾏的是⼀夫⼀妻制度哦。

那么我们以学⽣和⾝份证每个学⽣只有⼀张⾝份证,⽽每张⾝份证的主⼈当然只有⼀个啦。

数据库脚本:-- 删除数据库drop database if exists mybaits;-- 创建数据库create database if not exists mybatis default character set utf8;-- 选择数据库use mybatis;-- 删除数据表drop table if exists student ;drop table if exists card;-- 创建数据表create table card(cid int(255),num varchar(18),constraint pk_cid primary key (cid));create table student(sid int(255),sname varchar(32),scid int(255),constraint pk_sid primary key (sid),constraint fk_scid foreign key (scid) references card(cid));-- 增加测试数据insert into card (cid,num) values(1,'123456789012345678');insert into student (sid,sname,scid) values(1,'哈哈',1);新建⼀个one2one.Card.java类package one2one;import java.io.Serializable;/*** ⾝份证* @author Administrator**/@SuppressWarnings("serial")public class Card implements Serializable{private Integer cid;private String num;public Integer getCid() {return cid;}public void setCid(Integer cid) {this.cid = cid;}public String getNum() {return num;}public void setNum(String num) {this.num = num;}}新建one2one.Student.java类package one2one;import java.io.Serializable;/*** 学⽣* @author Administrator**/@SuppressWarnings("serial")public class Student implements Serializable{private Integer sid;private String sname;private Card card;public Integer getSid() {return sid;}public void setSid(Integer sid) {this.sid = sid;}public String getSname() {return sname;}public void setSname(String sname) {this.sname = sname;}public Card getCard() {return card;}public void setCard(Card card) {this.card = card;}}在one2one包下新建CardMapper.xml⽂件<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapper PUBLIC "-////DTD Mapper 3.0//EN""/dtd/mybatis-3-mapper.dtd"><mapper namespace="cardNameSpace"><resultMap type="one2one.Card" id="cardMap"><id column="cid" property="cid"/><result column="num" property="num"/></resultMap></mapper>同理,在one2one包下新建StudentMapper.xml⽂件<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapper PUBLIC "-////DTD Mapper 3.0//EN""/dtd/mybatis-3-mapper.dtd"><mapper namespace="studentNameSpace"><resultMap type="one2one.Student" id="studentMap"><id column="sid" property="sid"/><result column="sname" property="sname"/><!-- 关联字段不要写 --></resultMap><select id="findById" parameterType="integer" resultMap="studentMap">select s.sid,s.sname,c.cid,c.numfrom student s,card cwhere s.scid = c.cid and s.sid = #{sid}</select></mapper>在src下新建⼀个mybatis.cfg.xml⽂件,并包含StudentMapper.xml和CardMapper.xml⽂件<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE configuration PUBLIC "-////DTD Config 3.0//EN""/dtd/mybatis-3-config.dtd"><configuration><!-- 设置⼀个默认的环境信息 --><environments default="mysql_developer"><!-- 连接MySQL环境信息 --><environment id="mysql_developer"><!-- MyBatis使⽤jdbc事务管理器 --><transactionManager type="jdbc"/><!-- MyBatis使⽤连接池⽅式来获取连接对象 --><dataSource type="pooled"><!-- 配置与数据库交互的4个必要属性 --><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis"/><property name="username" value="root"/><property name="password" value="mysqladmin"/></dataSource></environment><!-- 连接Oracle环境信息 --><environment id="oracle_developer"><!-- MyBatis使⽤jdbc事务管理器 --><transactionManager type="jdbc"/><!-- MyBatis使⽤连接池⽅式来获取连接对象 --><dataSource type="pooled"><!-- 配置与数据库交互的4个必要属性 --><property name="driver" value="oracle.jdbc.driver.OracleDriver"/><property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/><property name="username" value="scott"/><property name="password" value="tiger"/></dataSource></environment></environments><!-- 加载映射⽂件 --><mappers><mapper resource="one2one/CardMapper.xml"/><mapper resource="one2one/StudentMapper.xml"/></mappers></configuration>在util包下新建⼀个⼯具类MyBatisUtil.java类package util;import java.io.IOException;import java.io.Reader;import java.sql.Connection;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;public class MyBatisUtil {private static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>(); public static SqlSessionFactory sqlSessionFactory ;//私有化构造⽅法private MyBatisUtil(){}//加载位于src/Mybatis.cfg.xmlstatic{try {Reader reader = Resources.getResourceAsReader("mybatis.cfg.xml"); sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader);} catch (IOException e) {e.printStackTrace();}}/*** 获取SQLSession* @return*/public static SqlSession getSqlSession(){//从当前线程中获取SqlSession对象SqlSession sqlSession = threadLocal.get();if(sqlSession == null){if(sqlSessionFactory != null){sqlSession = sqlSessionFactory.openSession();//讲sqlSession与当前线程绑定在⼀起threadLocal.set(sqlSession);}}return sqlSession;}/*** 关闭SqlSession 并与当前线程分开*/public static void closeSqlSession(){//从当前线程中获取SqlSession对象SqlSession sqlSession = threadLocal.get();//如果SqlSession对象⾮空if(sqlSession != null){//关闭SqlSession对象sqlSession.close();//分离当前线程与SqlSession的关系threadLocal.remove();}}//测试public static void main(String[] args) {SqlSession sqlSession = MyBatisUtil.getSqlSession();Connection conn= sqlSession.getConnection();System.out.println(conn != null ?"连接成功":"连接失败");}}新建持久层类StuentCardDAO.java类package one2one;import org.apache.ibatis.session.SqlSession;import org.junit.Test;import util.MyBatisUtil;/*** 持久层* @author Administrator**/public class StudentCardDAO {/*** 查询1号学⽣的信息与⾝份证信息* @param id* @return* @throws Exception*/public Student findById(Integer id) throws Exception{SqlSession sqlSession = null;try {sqlSession = MyBatisUtil.getSqlSession();return sqlSession.selectOne("studentNameSpace.findById", id);} catch (Exception e) {e.printStackTrace();throw e;}finally{MyBatisUtil.closeSqlSession();}}//测试查询1号学⽣的信息与⾝份证信息@Testpublic void testFindById() throws Exception{StudentCardDAO dao = new StudentCardDAO();Student student = dao.findById(1);System.out.println(student.getSid()+":"+student.getSname() }}这时我们只能查询1号学⽣的姓名,但是我们不能去查询它的⾝份号号,因为此时的card属性的值为null,从StudentMapper.xml中可以看出<select id="findById" parameterType="integer" resultMap="studentMap">MyBatis在解析这⼀句的时候只能将查询的数据封装到sid,sname中,所以怎么办?在StudentMapper.xml中的<resultMap type="one2one.Card" id="cardMap"><id column="cid" property="cid"/><result column="num" property="num"/></resultMap>增加<!--引⼊CardMapper.xml⽂件中的映射信息property表⽰Student的关联属性--><association property="card" resultMap="cardNameSpace.cardMap"/>那么此时的StudentMapper.xml的完整内容如下:<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapper PUBLIC "-////DTD Mapper 3.0//EN""/dtd/mybatis-3-mapper.dtd"><mapper namespace="studentNameSpace"><resultMap type="one2one.Student" id="studentMap"><id column="sid" property="sid"/><result column="sname" property="sname"/><!--引⼊CardMapper.xml⽂件中的映射信息property表⽰Student的关联属性--><association property="card" resultMap="cardNameSpace.cardMap"/></resultMap><select id="findById" parameterType="integer" resultMap="studentMap">select s.sid,s.sname,c.cid,c.numfrom student s,card cwhere s.scid = c.cid and s.sid = #{sid}</select></mapper>现在可以测试学⽣的⾝份证号码了将持久层类StuentCardDAO.java类的测试⽅法改为//测试查询1号学⽣的信息与⾝份证信息@Testpublic void testFindById() throws Exception{StudentCardDAO dao = new StudentCardDAO();Student student = dao.findById(1);System.out.println(student.getSid()+":"+student.getSname()+":"+student.getCard().getNum());}同理在StudentDAO.java类中增加查询“哈哈”学⽣的信息与⾝份证信息的⽅法/*** 查询“哈哈”学⽣的信息与⾝份证信息* @param name* @return* @throws Exception*/public Student findByName(String name) throws Exception{SqlSession sqlSession = null;try {sqlSession = MyBatisUtil.getSqlSession();return sqlSession.selectOne("studentNameSpace.findByName", name);} catch (Exception e) {e.printStackTrace();throw e;}finally{MyBatisUtil.closeSqlSession();}}并增加测试⽅法哦//测试查询“哈哈”学⽣的信息与⾝份证信息@Testpublic void testFindByName() throws Exception{StudentCardDAO dao = new StudentCardDAO();Student student = dao.findByName("哈哈");System.out.println(student.getSid()+":"+student.getSname()+":"+student.getCard().getNum());}当然如果你现在就测试,你会死的很惨,因为你没有在StudentMapper.xml⽂件中配置<select>哦,所以在StudentMapper.xml ⽂件中增加<select>配置信息<select id="findByName" parameterType="string" resultMap="studentMap">select s.sid,s.sname,c.cid,c.numfrom student s,card cwhere s.scid = c.cid and s.sname = #{sname}</select>这样就可以测试成功了。

mybatis中对logback.xml的使用详解

mybatis中对logback.xml的使用详解

mybatis中对logback.xml的使⽤详解***********************************************详解<configuration> and <logger>******************************************⼀:根节点<configuration>包含的属性:scan:当此属性设置为true时,配置⽂件如果发⽣改变,将会被重新加载,默认值为true。

scanPeriod:设置监测配置⽂件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。

当scan为true时,此属性⽣效。

默认的时间间隔为1分钟。

debug:当此属性设置为true时,将打印出logback内部⽇志信息,实时查看logback运⾏状态。

默认值为false。

例如:Xml代码1. <configuration scan="true"scanPeriod="60 seconds"debug="false">2. <!-- 其他配置省略-->3. </configuration>⼆:根节点<configuration>的⼦节点:2.1设置上下⽂名称:<contextName>每个logger都关联到logger上下⽂,默认上下⽂名称为“default”。

但可以使⽤<contextName>设置成其他名字,⽤于区分不同应⽤程序的记录。

⼀旦设置,不能修改。

Xml代码1. <configuration scan="true"scanPeriod="60 seconds"debug="false">2. <contextName>myAppName</contextName>3. <!-- 其他配置省略-->4. </configuration>2.2设置变量: <property>⽤来定义变量值的标签,<property> 有两个属性,name和value;其中name的值是变量的名称,value的值时变量定义的值。

mybatis对char类型非空处理 -回复

mybatis对char类型非空处理 -回复

mybatis对char类型非空处理-回复MyBatis是一个优秀的Java持久层框架,它提供了简单且规范的方法来进行数据库操作。

在使用MyBatis操作数据库时,我们经常会遇到char 类型的非空处理问题。

本文将一步一步回答“mybatis对char类型非空处理”的主题,帮助读者了解如何在MyBatis中处理char类型字段的非空问题。

第一步:了解char类型字段的特点和用法在数据库中,char类型字段是一种用来存储字符的数据类型。

相比于varchar类型,char类型在存储时会对字符串进行固定长度的截取,不足长度的部分会用空格进行填充。

在表设计时,我们需要考虑字段的长度和是否允许为空的问题。

第二步:配置MyBatis的类型处理器在MyBatis 的配置文件(一般为mybatis-config.xml)中,可以配置类型处理器来解决char类型字段的非空问题。

类型处理器是MyBatis 的一个重要概念,它负责在从数据库中取出数据时将其转化为Java 对象,以及在将数据插入到数据库时将其转化为数据库可识别的类型。

对于char类型字段,我们可以自定义一个类型处理器,通过继承org.apache.ibatis.type.BaseTypeHandler 类并实现其中的方法来处理非空问题。

在处理char类型字段时,我们需要重写BaseTypeHandler中的getNullableResult 方法和setNonNullParameter 方法。

在getNullableResult 方法中,我们可以判断数据库返回的char类型字段是否为空(即是否包含空格),若为空则返回空字符串(或其他默认值),若不为空则返回相应的字符串。

在setNonNullParameter 方法中,我们可以将Java 对象的属性值转化为数据库中等价的类型。

配置自定义的类型处理器时,需要在MyBatis 的配置文件中添加如下代码:<typeHandlers><typeHandlerhandler="com.example.handlers.CharTypeHandler"javaType="String" jdbcType="CHAR"/></typeHandlers>这样,当MyBatis 需要处理char 类型字段时,就会调用我们自定义的类型处理器。

mybatis对条件test内特殊字符处理

mybatis对条件test内特殊字符处理

mybatis对条件test内特殊字符处理MyBatis是一种优秀的数据访问框架,但在处理特殊字符的情况下,开发人员可能会遇到一些问题。

本文将探讨在MyBatis中如何处理条件测试中的特殊字符。

在MyBatis中,条件测试是通过`<if>`元素来实现的。

在`<if>`元素中,我们可以使用各种条件表达式来构建条件测试。

这些条件表达式可以是简单的比较运算,也可以是复杂的逻辑运算。

然而,当我们在条件测试中使用特殊字符时,可能会遇到一些问题。

特殊字符可能会被解析为XML或SQL的关键字,导致语法错误或SQL注入的风险。

为了解决这个问题,MyBatis提供了一些方法来处理特殊字符。

下面是一些常用的解决方案:1.使用转义字符:在条件测试中,可以使用转义字符来转义特殊字符。

转义字符是用反斜杠(\)进行表示的,它可以将特殊字符转换为普通字符。

例如,如果需要在条件测试中使用等于号(=),可以使用`\=`来表示。

2.使用CDATA包裹特殊字符:CDATA是XML中的一个特殊结构,它可以将文本内容作为纯文本而不需要进行XML解析。

在MyBatis的条件测试中,可以使用CDATA将特殊字符包裹起来,告诉解析器将其作为纯文本对待。

例如,可以使用`<![CDATA[=]]>`来表示等于号。

3.使用占位符:在条件测试中,可以使用占位符来表示特殊字符。

占位符是一种变量的替代方式,可以在条件测试中动态地设置特殊字符。

这样,特殊字符将被替换为变量值,从而避免了特殊字符被解析的问题。

例如,可以使用`#{EQUAL}`来表示等于号。

4.使用SQL语句的转义函数:某些数据库提供了转义函数,可以用于处理特殊字符。

在MyBatis的条件测试中,可以使用这些函数来转义特殊字符。

例如,可以使用`CONCAT`函数来连接字符串,将特殊字符作为参数传递给函数。

以上是几种常见的处理特殊字符的方法,在实际开发中可以根据具体情况选择合适的方法。

mybatis对char类型非空处理 -回复

mybatis对char类型非空处理 -回复

mybatis对char类型非空处理-回复MyBatis是一个开源的持久层框架,它提供了许多方便的特性来简化数据库操作。

其中之一是对于char类型的非空处理。

在本文中,我们将深入探讨MyBatis对char类型非空处理的方法和技巧。

第一步:了解char类型的特性在数据库中,char类型是一种固定长度的字符类型,意味着它总是具有固定的长度,无论实际使用的字符数是多少。

例如,如果我们定义了一个char(10)类型的列,那么无论实际存储的字符串是"abc"还是"abc123",都会被自动填充到固定长度的10个字符。

第二步:配置MyBatis的类型处理器在使用MyBatis进行数据查询和操作时,我们需要为char类型配置一个合适的类型处理器。

类型处理器是一个接口,用于将Java类型和数据库类型相互转换。

MyBatis提供了一些默认的类型处理器,但默认的char 类型处理器不支持非空处理。

为了解决这个问题,我们可以自定义一个类型处理器,实现对char类型的非空处理。

可以通过实现TypeHandler接口,或者继承BaseTypeHandler类来实现。

下面是一个示例:javapublic class CustomCharTypeHandler extends BaseTypeHandler<Character> {@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, Character parameter, JdbcType jdbcType) throws SQLException { ps.setString(i, parameter.toString().trim());}@Overridepublic Character getNullableResult(ResultSet rs, String columnName) throws SQLException {String value = rs.getString(columnName);if (value == null value.trim().isEmpty()) {return null;}return value.charAt(0);}@Overridepublic Character getNullableResult(ResultSet rs, int columnIndex) throws SQLException {String value = rs.getString(columnIndex);if (value == null value.trim().isEmpty()) {return null;}return value.charAt(0);}@Overridepublic Character getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {String value = cs.getString(columnIndex);if (value == null value.trim().isEmpty()) {return null;}return value.charAt(0);}}在上述代码中,setNonNullParameter()方法用于在将Java对象设置到PreparedStatement中时,将char类型转换为String类型,并去除两端的空格。

使用mybatis让entity和数据库字段对应

使用mybatis让entity和数据库字段对应

使用mybatis让entity和数据库字段对应要使用MyBatis让Entity和数据库字段对应,需要进行以下步骤:
1. 创建数据库表:首先,在数据库中创建一个表,该表应包含与Entity属性相对应的列。

2. 创建Entity类:创建一个Java类来表示数据库表的一行数据。

在这个类中,可以定义与数据库表中列相对应的属性,并为这些属性提供setter和getter方法。

3. 创建Mapper接口:创建一个接口来定义与数据库交互的方法。

在接口中,可以使用注解或XML来定义SQL查询语句,并指定参数和返回类型。

4. 配置Mapper接口:在MyBatis配置文件中,配置Mapper接口的位置和名称,以便MyBatis能够找到它们。

5. 实现Mapper接口:创建一个类来实现Mapper接口,实现其中定义的方法。

在这些方法中,使用MyBatis的SQL查询语句来执行数据库操作,并将查询结果映射到Entity对象中。

6. 配置MyBatis:在MyBatis配置文件中,配置数据库连接信息和其他相关属性,以便MyBatis能够正确连接到数据库并执行相应的数据库操作。

7. 运行程序:最后,使用MyBatis的SqlSessionFactory来获取数据库会话,并使用该会话执行数据库操作。

通过以上步骤,就可以使用MyBatis让Entity和数据库字段对应了。

每当从数据库获取数据时,MyBatis会将查询结果映射到Entity对象中,使得操作数据库变得更加方便和直观。

Mybatis一对多对按结果嵌套处理

Mybatis一对多对按结果嵌套处理

Mybatis⼀对多对按结果嵌套处理实体类@Datapublic class Student { -- 学⽣private int id;private String name;private int tid;}@Datapublic class Teacher {-- ⽼师private int id;private String name;private List<Student> students;}新建学⽣mapper接⼝public interface TeacherMapper{//获取指定⽼师下的所有学⽣及⽼师的信息Teacher getTeacherById(@Param("tid")int id);}按结果嵌套处理在resources 下新建mapper.xml<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-////DTD Config 3.0//EN""/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.rzk.mapper.TeacherMapper"><!--按结果嵌套查询--><select id="getTeacherById" resultMap="getStudent">SELECT s.id sid, sname, tname,t.id tidfrom student s, teacher twhere s.tid = t.id and t.id = #{tid}</select><resultMap id="getStudent" type="Teacher"><result property="id" column="tid"/><result property="name" column="tname"/><!--复杂的属性,我们需要单独处理对象: association 集合: collectionjavaType="" 指定属性的类型!集合中的泛型信息,我们使⽤ofType获取--><collection property="students" ofType="Student"><result property="id" column="sid"/><result property="name" column="sname"/><result property="tid" column="tid"/></collection></resultMap></mapper>db.propersdriver=com.mysql.jdbc.Driverurl=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=UTF-8username=rootpassword=123456loggerlog4j.rootLogger=DEBUG,console,file#控制台输出的相关设置log4j.appender.console = org.apache.log4j.ConsoleAppenderlog4j.appender.console.Target = System.outlog4j.appender.console.Threshold=DEBUGyout = org.apache.log4j.PatternLayout#yout.ConversionPattern=[%c]-%m%nyout.ConversionPattern=%5p [%t] - %m%n#⽂件输出的相关设置log4j.appender.file = org.apache.log4j.RollingFileAppenderlog4j.appender.file.File=./log/rzk.loglog4j.appender.file.MaxFileSize=10mblog4j.appender.file.Threshold=DEBUGyout=org.apache.log4j.PatternLayoutyout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n#⽇志输出级别.mybatis=DEBUGlog4j.logger.java.sql=DEBUGlog4j.logger.java.sql.Statement=DEBUGlog4j.logger.java.sql.ResultSet=DEBUGlog4j.logger.java.sql.PreparedStatement=DEBUGmybatis-config.xml<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configurationPUBLIC "-////DTD Config 3.0//EN""/dtd/mybatis-3-config.dtd"><!--configguration核⼼配置⽂件--><configuration><!--导⼊外部配置⽂件--><properties resource="db.properties"/><!--标准⽇志⼯⼚实现--><!-- <settings><setting name="logImpl" value="STDOUT_LOGGING"/> </settings>--><settings><setting name="logImpl" value="LOG4J"/></settings><!--给实体类起别名--><typeAliases><package name="com.rzk.pojo" /></typeAliases><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="${driver}"/><property name="url" value="${url}"/><property name="username" value="${username}"/> <property name="password" value="${password}"/></dataSource></environment></environments><mappers><mapper resource="com/rzk/mapper/StudentMapper.xml"/> <mapper resource="com/rzk/mapper/TeacherMapper.xml"/> </mappers></configuration>测试结果总结1.关联 - association [多对⼀]2.集合 - collection [⼀对多]3.javaType & ofType1.javaType⽤来指定实体类中属性的类型2.ofType ⽤来指定映射到List或者集合中的pojo类型,泛型中约束类型。

关于mybatis拦截器,对结果集进行拦截

关于mybatis拦截器,对结果集进行拦截

关于mybatis拦截器,对结果集进⾏拦截 因业务需要,需将结果集序列化为json返回,于是,⽹上找了好久资料,都是关于拦截参数的处理,拦截Sql语法构建的处理,就是很少关于对拦截结果集的处理,于是⾃⼰简单的写了⼀个对结果集的处理,记录下。

⼀、MyBatis的框架设计图参考:/luanlouis/article/details/404229411.如何将结果集改成我们想要的格式呢? 1.1 由原理图我们可知,ResultSetHandler负责将resultSet转换为list,那么我们能不能在转换的时候加上⾃⼰的逻辑,我想应该是可以的,但是因为源码看不太懂,想想还是算了。

1public List<Object> handleResultSets(Statement stmt) throws SQLException {2final List<Object> multipleResults = new ArrayList<Object>();34int resultSetCount = 0;5 ResultSetWrapper rsw = getFirstResultSet(stmt);67 List<ResultMap> resultMaps = mappedStatement.getResultMaps();8int resultMapCount = resultMaps.size();9 validateResultMapsCount(rsw, resultMapCount);1011while (rsw != null && resultMapCount > resultSetCount) {12 ResultMap resultMap = resultMaps.get(resultSetCount);1314//将resultSet15 handleResultSet(rsw, resultMap, multipleResults, null);16 rsw = getNextResultSet(stmt);17 cleanUpAfterHandlingResultSet();18 resultSetCount++;19 }2021 String[] resultSets = mappedStatement.getResulSets();22if (resultSets != null) {23while (rsw != null && resultSetCount < resultSets.length) {24 ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]);25if (parentMapping != null) {26 String nestedResultMapId = parentMapping.getNestedResultMapId();27 ResultMap resultMap = configuration.getResultMap(nestedResultMapId);28 handleResultSet(rsw, resultMap, null, parentMapping);29 }30 rsw = getNextResultSet(stmt);31 cleanUpAfterHandlingResultSet();32 resultSetCount++;33 }34 }3536return collapseSingleResultList(multipleResults);37 } 1.2 排除第⼀种⽅案,那么能不能跳过这个⽅法执⾏我们的⾃⼰的逻辑,答案是可以的,接下来我们会⽤到mybatis的拦截器。

mybatis一对多,多对一配置

mybatis一对多,多对一配置

mybatis一对多,多对一配置展开全文一. 简介:本实例使用顾客和订单的例子做说明: 一个顾客可以有多个订单, 一个订单只对应一个顾客二. 例子:1. 代码结构图:2. 建表语句:[sql] view plain copyprint?1.CREATE DATABASE test;2.E test;4.5.CREATE TABLE person(6.personId VARCHAR(36) PRIMARY KEY,7.personName VARCHAR(64),8.personAddress VARCHAR(128),9.personTel VARCHAR(11)10.);11.12.CREATE TABLE orders(13.orderId VARCHAR(36) PRIMARY KEY,14.orderNumber VARCHAR(20),15.orderPrice INT,16.pid VARCHAR(36)17.);18.19.INSERT INTO person VALUES('001', 'Jack', 'Wuhan', '12 34567');20.INSERT INTO orders VALUES('O_00001', '00001', 100, ' 001');21.INSERT INTO orders VALUES('O_00002', '00002', 200, ' 001');22.23.SELECT p.*, o.*24.FROM person p25.JOIN orders o ON (p.personId=o.pid)26.WHERE p.personId = '001'3. 顾客实体:[java] view plain copyprint?1./**2.* 客户实体3.*/4.public class Person {5.6.private String id;7.private String name;8.private String address;9.private String tel;10.11.private List<Order> orders;12.13.@Override14.public String toString() {15.return "{id: " + id + ", name: " + name + ", address: " + address + ", tel: " + tel + "}";16.}17.}4. 订单实体:[java] view plain copyprint?1./**2.* 订单实体3.*/4.public class Order {5.6.private String id;7.private String number;8.private int price;9.10.private Person person;11.12.@Override13.public String toString() {14.return "{id: " + id + ", number: " + number + ", price: " + price + "}";15.}16.17.}5. 一对多实体配置: Person.xml[html] view plain copyprint?1.<?xml version="1.0" encoding="UTF-8" ?>2.<!DOCTYPE mapper3.PUBLIC "-////DTD Mapper 3.0//EN"4."/dtd/mybatis-3-mapper.dtd">5.<mapper namespace="com.zdp.domain.Person">6.7.<resultMap type="Person" id="personBean">8.<id column="personId" property="id"/>9.<result column="personName" property="name"/>10.<result column="personAddress" property="address" />11.<result column="personT el" property="tel"/>12.13.<!-- 一对多的关系 -->14.<!-- property: 指的是集合属性的值, ofType:指的是集合中元素的类型 -->15.<collection property="orders" ofType="Order">16.<id column="orderId" property="id"/>17.<result column="orderNumber" property="number"/ >18.<result column="orderPrice" property="price"/>19.</collection>20.</resultMap>21.22.<!-- 根据id查询Person, 关联将Orders查询出来 -->23.<select id="selectPersonById" parameterType="string " resultMap="personBean">24.select p.*, o.* from person p, orders o where p.personId = o.pid and p.personId = #{id}25.</select>26.27.</mapper>6. 多对一实体配置:[html] view plain copyprint?1.<?xml version="1.0" encoding="UTF-8" ?>2.<!DOCTYPE mapper3.PUBLIC "-////DTD Mapper 3.0//EN"4."/dtd/mybatis-3-mapper.dtd">5.<mapper namespace="com.zdp.domain.Order">6.<resultMap type="Order" id="orderBean">7.<id column="orderId" property="id"/>8.<result column="orderNumber" property="number"/>9.<result column="orderPrice" property="price"/>10.11.<!-- 多对一的关系 -->12.<!-- property: 指的是属性的值, javaType:指的是属性的类型-->13.<association property="person" javaType="Person">14.<id column="personId" property="id"/>15.<result column="personName" property="name"/>16.<result column="personAddress" property="address" />17.<result column="personT el" property="tel"/>18.</association>19.</resultMap>20.21.<!-- 根据id查询Order, 关联将Person查询出来 -->22.<select id="selectOrderById" parameterType="string" resultMap="orderBean">23.select p.*, o.* from person p, orders o where p.personId = o.pid and o.orderId = #{id}24.</select>25.26.</mapper>7. 总配置: sqlMapConfig.xml[html] view plain copyprint?1.<?xml version="1.0" encoding="UTF-8" ?>2.<!DOCTYPE configuration3.PUBLIC "-////DTD Config 3.0//EN"4."/dtd/mybatis-3-config.dtd">5.<configuration>6.<typeAliases>7.<typeAlias type="com.zdp.domain.Person" alias="Person "/>8.<typeAlias type="com.zdp.domain.Order" alias="Order"/ >9.</typeAliases>10.<environments default="development">11.<environment id="development">12.<transactionManager type="JDBC" />13.<dataSource type="POOLED">14.<property name="driver" value="com.mysql.jdbc.Driv er" />15.<property name="url" value="jdbc:mysql://localhost/t est" />16.<property name="username" value="root" />17.<property name="password" value="root" />18.</dataSource>19.</environment>20.</environments>21.<mappers>22.<!-- 映射文件的位置 -->23.<mapper resource="com/zdp/domain/Person.xml" />24.<mapper resource="com/zdp/domain/Order.xml" />25.</mappers>26.</configuration>8. 测试文件:[java] view plain copyprint?1./**2.* 测试一对多和多对一3.*/4.public class MybatisTest {5.6.private SqlSessionFactory ssf;7.8.@Before9.public void initSF() throws Exception {10.String resource = "sqlMapConfig.xml";11.InputStream inputStream = Resources.getResourceAsS tream(resource);12.ssf = new SqlSessionFactoryBuilder().build(inputStrea m);13.}14.15.@Test//一对多关联查询16.public void selectPersonById()throws Exception{17.SqlSession session = ssf.openSession();18.Person person = session.selectOne("com.zdp.domain. Person.selectPersonById", "001");19.System.out.println(person.getOrders());20.}21.22.@Test//多对一关联查询23.public void selectOrderById()throws Exception{24.SqlSession session = ssf.openSession();25.Order order = session.selectOne("com.zdp.domain.Or der.selectOrderById", "O_00001");26.System.out.println(order.getPerson().getName());27.}28.}。

  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功能的具体实现就在此。

相关文档
最新文档