mappers 映射器的兩種映射方案:
要定義 SQL 映射語句先要告訴 MyBatis 到哪裏去找到這些語句。 Java 在這方面沒有提供一個很好的方法, 所以最佳的方式是用mappers 映射器告訴 MyBatis 到哪裏去找映射文件。mappers 映射器提供了兩種映射方案,一是直接指定相應的mapper .xml文件,二是指定與mapper .xml相關聯的接口。例如:
<mappers>
<!--指定mapper.xml的相對路徑-->
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<!--指定mapper.xml的絕對路徑-->
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
</mappers>
<mappers>
<!--指定相關聯的接口的全限定路徑-->
<mapper class="org.mybatis.builder.AuthorMapper"/>
<!--指定包下所有相關聯的接口-->
<package name="org.mybatis.builder"/>
</mappers>
前面所述俱是用的第一種方案,第一種方案適用於傳統的DAO封裝。下面介紹一下第二種方案,第二種方案纔是Mybatis推薦的方案,因爲它具有很多優點,其中最顯著的優點在於:
- 調用sql命令時,直接調用接口中的方法,由程序內部自動關聯mapper.xml文件中對應的sql命令,因此不用再寫冗長的namespace;
- 在第一種方案中,調用sql命令時只能傳入一個參數,如果要傳入多個參數還得用對象或集合將其封裝,而第二種方案中由於調用的是接口中聲明的方法,既然是方法那麼就可以傳入多個參數。
但是第二種方案有以下兩個要求:
- 接口和映射文件必須在同一個包中;
- 接口和映射文件除去文件後綴其文件名必須相同。
第二種方案適用於動態代理DAO開發,是Mybatis推薦的方案,動態代理對接口和映射文件也有幾個要求:
- 接口中聲明的方法名必須和映射文件中對應的sql的id一致;
- 接口中聲明的方法參數必須和映射文件中對應的sql的parameterType一致;
- 接口中聲明的方法返回值必須和映射文件中對應的sql的resultType一致。
例:
1、在MySQl中建表,在相應的web項目的src目錄下,新建包與實體類:
此處用上一篇博客的flower表,包名“cn.jingpengchong.pojo”及包下的Flower.java
2、在src目錄下,新建包與mapper.xml文件:
包名“cn.jingpengchong.mapper”,文件“FlowerMapper.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="cn.jingpengchong.mapper.FlowerMapper">
<!-- 根據價格和產地查找花 -->
<select id="selByPriPro" resultType="flower">
<!-- 用#{0}/#{param1}接收第一個參數,用#{1}/#{param2}接收第一個參數 -->
select * from flower where price = #{0} and production = #{1}
</select>
</mapper>
3、在src目錄下,新建XML映射配置文件:
文件“mybatis.xml”文件如下:
<?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>
<!--給Flower類設置別名,這樣在聲明該類類型時直接寫“Flower”或“flower”即可-->
<typeAliases>
<package name="cn.jingpengchong.pojo"/>
</typeAliases>
<environments default="default">
<environment id="default">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/ssm"/>
<property name="username" value="root"/>
<property name="password" value="1234"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--將該包下文件名相同的接口的方法和xml文件的sql命令一一關聯起來-->
<package name="cn.jingpengchong.mapper"/>
</mappers>
</configuration>
4、在mapper.xml文件所在包下新建接口,接口名要與對應的mapper.xml文件名相同:
在包“cn.jingpengchong.mapper”下新建接口“FlowerMapper.java”:
package cn.jingpengchong.mapper;
import java.util.List;
import cn.jingpengchong.pojo.Flower;
public interface FlowerMapper {
/**
* 根據價格和產地查詢花
* selByPriPro:方法名要與對應xml文件中對應方法的id相同
* pri:價格price
* pro:產地production
*/
List<Flower> selByPriPro(double pri, String pro);
}
5、新建測試類:
這裏在“cn.jingpengchong.test”包下新建了一個“Test.java”文件:
package cn.jingpengchong.test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
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 cn.jingpengchong.mapper.FlowerMapper;
import cn.jingpengchong.pojo.Flower;
public class Test {
public static void main(String[] args) throws IOException {
InputStream is = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession session = factory.openSession();
FlowerMapper mapper = session.getMapper(FlowerMapper.class);
List<Flower> list = mapper.selByPriPro(4, "南美阿根廷");
for (Flower flower : list) {
System.out.println(flower);
}
}
}
運行結果如下:
附:mapper.xml文件中SQL命令的參數接收
1、#{0}、#{1}、#{2}…:用於獲取第1、2、3…個參數;
2、#{param1}、#{param2}、#{param3}…:用於獲取第1、2、3…個參數;
3、上面的#{}不能換成${},因爲除了獲取Map集合中的元素或對象中的屬性值,${}中的內容都會被sql簡單的作爲字符串拼接;
4、可以用“@Param()”註解將參數封裝成Map集合,如果想要用下面的方法獲取參數:
<select id="selByPriPro" resultType="flower">
select * from flower where price = #{price} and production = #{production}
</select>
那麼接口中聲明的方法應該加上對應的註解:
List<Flower> selByPriPro(@Param("price") double pri, @Param("production") String pro);
修改完畢運行測試類仍然正確,結果如下:
這種方式是將註解中傳入的參數作爲key,將後面的參數作爲value封裝成了一個Map集合傳給了mapper.xml文件,但即便如此,把#{}換成${}仍然會出錯:
可以在日誌中看到接收字符串參數時單/雙引號丟失了,這也是在開發中用#{},而不用${}的原因!