#{}占位符与${}拼接符如何在MyBatis中使用

#{}占位符与${}拼接符如何在MyBatis中使用?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

1、关于#{}占位符

先来看以下的示例,该示例是MyBatis中的SQL映射配置文件(Mapper配置文件),在该配置中使用了#{}占位符。






SELECT*FROMtb_userWHEREid=#{id}




INSERTINTOtb_user(user_name,blog_url,remark)
VALUES(#{userName},#{blogUrl},#{remark});

在SQL映射配置文章中,输入参数需要用占位符来标识对应的位置。

在传统的JDBC编程中,占位符用“?”来标识,然后在加载SQL之前按照“?”的位置设置参数。

而“#{}”在MyBatis中也代表一种占位符,该符号接受输入参数,在大括号中编写参数名称来接受对应参数。

“#{}”接受的输入参数的类型可以是简单类型、普通JavaBean或者HashMap。

当接受简单类型时,“#{}”中可以写“value”或者其他任意名称。

如果接受的是JavaBean,它会通过OGNL读取对象中的属性值。

2、关于${}拼接符

再来看以下的示例,该示例是MyBatis中的SQL映射配置文件(Mapper配置文件),在该配置中使用了${}拼接符。






SELECT*FROMtb_userWHEREuser_nameLIKE'%${value}%'

在SQL映射配置文件中,有时候需要拼接SQL语句。例如在模糊查询的时候,就需要在查询条件的两侧拼接两个“%”字符串,这个时候如果使用“#{}”占位符是不行的。在MyBatis中,“${}”在SQL配置文件中代表一个“拼接符号”,可以在原有SQL语句上拼接新的符合SQL语法的语句。

但是要注意的是,使用“${}”拼接的SQL语句,会引起SQL注入,所以一般不建议使用“${}”。

“${}”接受输入参数的类型可以是简单类型、普通JavaBean或者HashMap。

当接受简单类型时,“${}”中只能写“value”,而不能写其他任意名称。

如果接受的是JavaBean,它会通过OGNL读取对象中的属性值。

另外,在MyBatis 3.4.2之后,还可以在“${}”拼接符中设置一个默认值,格式如下:

${属性:默认值}

即在所需引入的属性名的后面添加“:”引号,然后紧跟着填写属性不存在或为空时的默认值。

【示例】设置“${}”拼接符的默认值。

(1)创建数据库连接的属性文件(db.properties)

在src目录下创建db.propertie属性文件,并使用“#”符号将属性项jdbc.username和jdbc.password注释掉,表示这两个属性项未进行配置。

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/db_admin?useSSL=false&
#jdbc.username=root
#jdbc.password=123456

(2)启用拼接符默认值的配置

要使用“${}”拼接符中设置一个默认值,需要在properties标签中设置启用拼接符默认值的配置项。

在MyBatis配置文件(mybatis-config.xml)中,使用标签加载数据库连接属性文件(db.properties),并在该标签中设置启用拼接符默认值的配置项,该配置如下:





注意:在MyBatis配置文件(mybatis-config.xml)中,标签的配置必须写在标签的上面,因为MyBatis中的配置,不但有类型限制,还有顺序限制。

必须按照:、…顺序排放。

(3)编写数据库配置信息,并使用“${}”拼接符的默认值。

说明:

由于在db.propertie属性文件中,已经将jdbc.username和jdbc.password属性项注释掉了,然后在上面的配置信息中,给username和password配置项中的“${}”拼接符中设置默认值,这样程序在启动时,就会读取默认值。

补充:MyBatis映射——SQL占位符及传参

简介

本篇主要讲述Mybatis映射SQL通过#{}获取引入类型参数的属性值及通过@Param注解指定名称传参。

关于占位符与字符拼接:

占位符:占位符就是在某个地方占领一个位置,把它单独作为某个东西,比如这里就是把它作为 值。

#{}表示一个占位符号,通过#{}可以实现 preparedStatement 向占 位符中设置值, 自动进行 java

类型和 jdbc 类型转换。#{}可以有效防止 sql 注入。 #{}可以接 收简单类型值或 pojo 属性值。 如果 parameterType 传输单个简单类型值,#{} 括号中可以是 value 或其它名称。

字符拼接:字符拼接就是简单的对字符串拼接。没有特殊的其它含义。

表 示 拼 接 s q l 串 , 通 过 可 以 将 p a r a m e t e r T y p e 传 入 的 内 容 拼 接 在 s q l 中 且 不 进 行 j d b c 类 型 转 换 , 可 以 将 p a r a m e t e r T y p e 传 入 的 内 容 拼 接 在 s q l 中 且 不 进 行 j d b c 类 型 转 换 , 可 以 接 收 简 单 类 型 值 或 p o j o 属 性 值 , 如 果 p a r a m e t e r T y p e 传 输 单 个 简 单 类 型 值 , {}表示拼接 sql 串,通过可以将parameterType传入的内容拼接在sql中且不进行jdbc类型转换,可以将parameterType传入的内容拼接在sql中且不进行jdbc类型转换,{}可以接收简单类型值或 pojo 属性值,如果 parameterType 传输单个简单类型值,表示拼接sql串,通过可以将parameterType传入的内容拼接在sql中且不进行jdbc类型转换,可以将parameterType传入的内容拼接在sql中且不进行jdbc类型转换,可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,{}括号中只能是 value。

关于@Param:

在用注解来简化xml配置的时候(比如Mybatis的Mapper.xml映射文件中的sql参数引入);

@Param注解的作用是给参数命名,参数命名后就能根据名字得到参数值,正确的将参数传入sql语句中(一般通过#{}的方式,${}会有sql注入的问题)。

#{}: 解析为一个 JDBC 预编译语句(prepared statement)的参数标记符,一个 #{ } 被解析为一个参数占位符 。 ${}: 仅仅为一个纯碎的 string 替换,在动态 SQL 解析阶段将会进行变量替换。

MyBatis 的真正强大在于它的映射语句

Mapper.xml映射文件中定义了操作数据库的sql,每个sql是一个statement,映射文件是mybatis的核心。

映射文件中有很多属性,常用的就是parameterType(输入类型)、resultType(输出类型)、resultMap()、rparameterMap()。

实例步骤

先建好实体类Teacher和接口类

Teacher类

packagecom.lanou3g.mybaties.bean;
importlombok.Getter;
importlombok.Setter;
@Getter
@Setter
publicclassTeacher{
privateIntegerid;
privateStringtname;
privateIntegerage;
privateIntegersalary;
publicTeacher(){}
@Override
publicStringtoString(){
return"Teacher{"+
"id="+id+
",tname='"+tname+'\''+
",salary="+salary+
",remark='"+remark+'\''+
",age="+age+
'}';
}
privateStringremark;
publicTeacher(Integerid,Stringtname,Integerage,Integersalary,Stringremark){
this.id=id;
this.tname=tname;
this.age=age;
this.salary=salary;
this.remark=remark;
}
publicTeacher(Integerid){
this.id=id;
}
}

接口类

packagecom.lanou3g.mybaties.dao;
importcom.lanou3g.mybaties.bean.Teacher;
importorg.apache.ibatis.annotations.Param;
importjava.util.List;
publicinterfaceTeacherDao{
ListqueryAll();
TeacherqueryById(intid);
TeacherqueryByIdAndAge(@Param("id")intid,@Param("age")intage);
intinsertTeacher(Teacherteacher);
intinsertTeacherByParam(@Param("tname")Stringtname,@Param("age")intage);
intupdateTeacherById(Teacherteacher);
intdeleteTeacherById(intid);
}

主要还是xml配置文件的配置,下面是 mybatis_conf.xml文件,它主要引入外部的properties文件(用于配置数据源)、定义类型别名(全局)、配置多套环境的数据库连接参数及引入哪些Mapper映射文件等

mybatis_conf.xml配置文件


































TeacherMapper.xml映射文件










select*fromteacher;



select*fromteacherwhereid=#{id};



select*fromteacherwhereid=#{id}andage<=#{age};




insertintoteacher(tname)values(#{tname});


insertintoteacher(tname,age)values(#{tname},#{age});


updateteachersettname=#{tname},age=#{age}whereid=#{id}


deletefromteacherwhereid=#{id};

前面完成后,就要测试了。不过在测试时需要实例化创建对象,因要实现多个方法,在这先建MyBatisTools.java工具类,其主要进行封装Mybatis初始化操作,要求支持创建多env sqlSessionFactory,整个应用生命周期内相同env的sqlSessionFactory对象只有一个(这个类不要过于探究,会用即可)。

MyBatisTools.java

packagecom.lanou3g.mybaties;
importlombok.extern.slf4j.Slf4j;
importorg.apache.ibatis.io.Resources;
importorg.apache.ibatis.session.ExecutorType;
importorg.apache.ibatis.session.SqlSession;
importorg.apache.ibatis.session.SqlSessionFactory;
importorg.apache.ibatis.session.SqlSessionFactoryBuilder;
importjava.io.InputStream;
importjava.util.concurrent.ConcurrentHashMap;
/**
*封装Mybatis初始化操作
*支持创建多envsqlSessionFactory
*整个应用生命周期内相同env的sqlSessionFactory对象只有一个
*/
@Slf4j
publicclassMyBatisTools{
privatestaticConcurrentHashMapfactoryMap=newMyConcurrentHashMap();
privatestaticMyBatisToolsmyBatisTools;
privateMyBatisTools(){}
publicstaticMyBatisToolsgetInstance(){
if(myBatisTools==null){
synchronized(MyBatisTools.class){
if(myBatisTools==null){
myBatisTools=newMyBatisTools();
}
}
}
log.debug("当前一共有:"+factoryMap.size()+"个SqlSessionFactory实例");
log.debug("他们分别是:"+factoryMap);
returnmyBatisTools;
}
publicSqlSessionFactorygetSessionFactory(Stringenv){
try{
//1.读入配置文件
InputStreamin=Resources.getResourceAsStream("mybatis_conf.xml");
//2.构建SqlSessionFactory(用于获取sqlSession)
SqlSessionFactorysessionFactory=null;
synchronized(factoryMap){
if(factoryMap.containsKey(env)){
returnfactoryMap.get(env);
}else{
sessionFactory=newSqlSessionFactoryBuilder().build(in,env);
factoryMap.put(env,sessionFactory);
}
}
returnsessionFactory;
}catch(Exceptione){
log.error("初始化SqlSessionFactory失败",e);
returnnull;
}
}
publicSqlSessionopenSession(){
returngetSessionFactory(null).openSession();
}
publicSqlSessionopenSession(booleanautoCommit){
returngetSessionFactory(null).openSession(autoCommit);
}
publicSqlSessionopenSession(ExecutorTypeexecutorType,booleanautoCommit){
returngetSessionFactory(null).openSession(executorType,autoCommit);
}
}
/**
*继承原生ConcurrentHashMap,处理nullkey问题
*/
classMyConcurrentHashMapextendsConcurrentHashMap{
@Override
publicObjectput(Objectkey,Objectvalue){
if(key==null){
key="null";
}
returnsuper.put(key,value);
}
@Override
publicbooleancontainsKey(Objectkey){
if(key==null){
key="null";
}
returnsuper.containsKey(key);
}
@Override
publicObjectget(Objectkey){
if(key==null){
key="null";
}
returnsuper.get(key);
}
}

最后就是测试,在AppTest类测试

AppTest

@Slf4j
publicclassAppTest
{
/**
*RigorousTest:-)
*/
TeacherDaoteacherDao=null;
@Before
publicvoidsetUp(){
teacherDao=MyBatisTools.getInstance().openSession(true).getMapper(TeacherDao.class);
}
/**
*练习查询多个库(用到了多环境配置)
*/
@Test
publicvoidtextqueryById(){
Teacherteacher=teacherDao.queryById(1);
System.out.println(teacher);
}
@Test
publicvoidtext(){
Listteachers=teacherDao.queryAll();
System.out.println(teachers);
}
/**
*多个参数查询语句
*/
@Test
publicvoidtestQueryByIdAndAge(){
TeacherteacherList=teacherDao.queryByIdAndAge(1,65);
log.info("查询结果:"+teacherList);
}
@Test
publicvoidtestInsert(){
//新增Teacher表
System.out.println("--------------插入前:");
ListteacherList=teacherDao.queryAll();
System.out.println(teacherList);
intret=teacherDao.insertTeacher(newTeacher("好人"));
log.info("影响的行数:"+ret);
//比较low的写法(不推荐)
//intret=teacherDao.insertTeacherByParam("哈哈哥",99);
//log.info("影响的行数:"+ret);
System.out.println("--------------插入后:");
teacherList=teacherDao.queryAll();
System.out.println(teacherList);
}
@Test
publicvoidtestUpdate(){
Teacherteacher=newTeacher();
teacher.setId(6);
teacher.setAge(99);
teacher.setTname("乔巴老师");
introws=teacherDao.updateTeacherById(teacher);
log.info("更新行数:"+rows);
}
@Test
publicvoidtestDelete(){
introws=teacherDao.deleteTeacherById(13);
log.info("删除行数:"+rows);
}
@Test
publicvoidtestinsertTeacherByParam(){
introw=teacherDao.insertTeacherByParam("hh",22);
System.out.println(row);
}
}

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注恰卡编程网行业资讯频道,感谢您对恰卡编程网的支持。

发布于 2021-02-24 07:35:16
分享
海报
170
上一篇:如何在laravel5.6框架中对数值进行转换 下一篇:如何在matplotlib中使用pyplot模块设置标题
目录

    推荐阅读

    忘记密码?

    图形验证码