1、单个参数
mybatis不做特殊处理,只需要用 #{参数名} 取出参数值就可以了 。
<?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.pjf.mybatis.dao.HotelMapper"> <!-- public Hotel getHotel(Integer i); --> <select id="getHotel" resultType="com.pjf.mybatis.po.Hotel"> select * from hotel where <!-- 这里#{id}可以写成任何值如 #{abc}--> id=#{id} </select> </mapper>
注:事实上这里#{id},参数名id可以写任何值,因为只有传了一个参数。
2、多个参数
mybatis会做特殊处理。 多个参数会被封装成 一个map。需要用 #{key} 取出参数值, key是param1, param2.....或者0、1、2索引值 。
首先举个例子,理所当然,很容易认为是这样去取参数值,直接写#{id}和#{price}
<?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.pjf.mybatis.dao.HotelMapper"> <!-- public Hotel getHotel(Integer i,Integer j); --> <select id="getHotel" resultType="com.pjf.mybatis.po.Hotel"> select * from hotel where id=#{id} and price =#{price} </select> </mapper>
这样是不对的,运行之后发现报错了
Caused by: org.apache.ibatis.binding.BindingException: Parameter 'id' not found. Available parameters are [arg1, arg0, param1, param2]
事实上,多个参数时,mybatis会做特殊处理,多个参数会被封装成map,需要用 #{key} 取出参数值, key是param1, param2.....或者0、1、2索引值 。
改成下面这样就正确了。
<?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.pjf.mybatis.dao.HotelMapper"> <!-- public Hotel getHotel(Integer i,Integer j); --> <select id="getHotel" resultType="com.pjf.mybatis.po.Hotel"> select * from hotel where id=#{param1} and price =#{param2} </select> </mapper>
3、命名参数
事实上,人们还是习惯使用#{id}和#{price}而不是#{param1}和#{param2},当然mybatis也提供了解决办法,通过@param("key")明确指定封装map中的key,就可以通过#{key}取出参数值了,@param("key")写在hotelMapper接口上。
public interface HotelMapper { public Hotel getHotel(@Param("id")Integer i,@Param("price")Integer j); }
这时候就可以通过#{id}和#{price}取出参数值了。
<?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.pjf.mybatis.dao.HotelMapper"> <!-- public Hotel getHotel(@Param("id")Integer i,@Param("price")Integer j); --> <select id="getHotel" resultType="com.pjf.mybatis.po.Hotel"> select* from hotel where id=#{id} and price =#{price} </select> </mapper>
4、POJO
如果多个参数正好是我们业务逻辑的数据模型,我们就可以直接传入pojo;#{属性名}:取出传入的pojo的属性值。
hotelMapper接口
package com.pjf.mybatis.dao; import java.util.Map; import org.apache.ibatis.annotations.Param; import com.pjf.mybatis.po.Hotel; public interface HotelMapper { //直接传入hotel业务模型 public void insertHotel(Hotel hotel); }
5、map
如果多个参数不是业务模型中的数据,没有对应的pojo,不经常使用,为了方便,我们也可以传入map。 #{key}:取出map中对应的值
hotelMapper接口
package com.pjf.mybatis.dao; import java.util.Map; import org.apache.ibatis.annotations.Param; import com.pjf.mybatis.po.Hotel; public interface HotelMapper { public Hotel getHotel(Map<String,Integer> map); }
hotelMapper.xml
<?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.pjf.mybatis.dao.HotelMapper"> <!-- public Hotel getHotel(@Param("id")Integer i,@Param("price")Integer j); --> <select id="getHotel" resultType="com.pjf.mybatis.po.Hotel"> select * from hotel where id=#{id} and price =#{price} </select> </mapper>
测试类
public class TestHotel { public SqlSessionFactory sqlSessionFactory() throws IOException { String resource = "mybatis_config.xml"; InputStream is = Resources.getResourceAsStream(resource); SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is); return sessionFactory; } @Test public void getHotel() throws IOException { SqlSessionFactory sessionFactory = sqlSessionFactory(); SqlSession session = sessionFactory.openSession(); HotelMapper hotelMapper = session.getMapper(HotelMapper.class); System.out.println(hotelMapper.getClass()); //手动封装一个map传入 Map map =new HashMap<>(); map.put("id", 1001); map.put("price", 997); Hotel hotel = hotelMapper.getHotel(map); System.out.println(hotel); session.close(); } }
6、对象参数
如果多个参数不是业务模型,但是有用的比较频繁时,这时候我们可以编写一个TO对象专门用来传递参数
package com.pjf.mybatis.po; public class HotelTo { private int id; private int price; public int getId() { return id; } public void setId(int id) { this.id = id; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } }
这时候接口就可以修改为
package com.pjf.mybatis.dao; import java.util.Map; import org.apache.ibatis.annotations.Param; import com.pjf.mybatis.po.Hotel; public interface HotelMapper { //传入HotelTo 模型 public void insertHotel(HotelTo hotelTo); }
7、例子
public Employee getEmp(@Param("id")Integer id,String lastName); 取值:id==>#{id/param1} lastName==>#{param2}
public Employee getEmp(Integer id,@Param("e")Employee emp); 取值:id==>#{param1} lastName===>#{param2.lastName/e.lastName}
8、${} 与 #{} 的区别
举例说明
1 select * from user where name = "dato"; 2 3 select * from user where name = #{name}; 4 5 select * from user where name = ${name};
一般情况下,我们都不会注意到这里面有什么不一样的地方。因为这些sql都可以达到我们的目的,去查询名字叫dato的用户。
区别
动态 SQL 是 mybatis 的强大特性之一,也是它优于其他 ORM 框架的一个重要原因。mybatis 在对 sql 语句进行预编译之前,会对 sql 进行动态解析,解析为一个 BoundSql 对象,也是在此处对动态 SQL 进行处理的。在动态 SQL 解析阶段, #{ } 和 ${ } 会有不同的表现
select * from user where name = #{name};
#{} 在动态解析的时候, 会解析成一个参数标记符。就是解析之后的语句是:
select * from user where name = ?;
那么我们使用 ${}的时候
select * from user where name = ${name};
${}在动态解析的时候,会将我们传入的参数当做String字符串填充到我们的语句中,就会变成下面的语句
select * from user where name = "dato";
预编译之前的 SQL 语句已经不包含变量了,完全已经是常量数据了。相当于我们普通没有变量的sql了。
综上所得, ${ } 变量的替换阶段是在动态 SQL 解析阶段,而 #{ }变量的替换是在 DBMS 中。
这是 #{} 和 ${} 我们能看到的主要的区别,除此之外,还有以下区别:
- #方式能够很大程度防止sql注入。
- $方式无法防止Sql注入。
- $方式一般用于传入数据库对象,例如传入表名.
- 一般能用#的就别用$.