每個線程都應該有它自己的SqlSession實例。SqlSession的實例不能共享使用,它是線程不安全的
配置文件
(已下載IDEA Mybatis插件 ---- MyBatis plugin)
-
SqlMapConfig.xml
mybatis的全局配置文件,配置了mybatis的運行環(huán)境等信息
-
配置的內(nèi)容和順序如下:
properties(屬性) ---- 用resource屬性加載外部配置文件
typeAliases(類型別名)---- 給類起別名
-
environments(環(huán)境集合屬性對象)
- environment(環(huán)境子屬性對象)
- transactionManager(事務管理)
- dataSource(數(shù)據(jù)源)
-
mappers(映射器)
<mapper resource=" " /> ---- 使用相對于xml路徑的資源
-
<mapper class=" " /> ---- 使用mapper接口類路徑
此種方法要求mapper接口名稱和mapper映射文件名稱相同,且放在同一個目錄中
-
<package name=" "/> ---- 注冊指定包下的所有mapper接口
此種方法要求mapper接口名稱和mapper映射文件名稱相同,且放在同一個目錄中
idea maven 需要額外配置
<build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> <include>**/*.properties</include> </includes> <filtering>true</filtering> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.xml</include> <include>**/*.properties</include> </includes> </resource> </resources> </build>
<?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> <!--引入外部配置文件--> <properties resource="jdbc.properties"/> <typeAliases> <!-- 單個別名定義 --> <typeAlias alias="user" type="cn.itcast.mybatis.pojo.User" /> <!-- 批量別名定義,掃描整個包下的類,別名為類名(大小寫不敏感) --> <package name="cn.haha.mybatis.entity" /> <package name="其它包" /> </typeAliases> <!-- 和spring整合后 environments配置將廢除 --> <environments default="development"> <environment id="development"> <!-- 使用jdbc事務管理 --> <transactionManager type="JDBC"/> <!-- 數(shù)據(jù)庫連接池 --> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments> <!-- 加載映射文件 --> <mappers> <mapper resource="mapper/User.xml"></mapper> </mappers> </configuration> -
-
mapper.xml
sql映射文件,文件中配置了操作數(shù)據(jù)庫的sql語句。此文件需要在SqlMapConfig.xml中加載,
#{} ---- 占位符${} ---- 字符串拼接,${}里面?zhèn)鬟f簡單類型時必須寫value即${value},傳遞pojo對象或pojo包裝對象則需要寫對象對應屬性<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- 命名空間 --> <mapper namespace="user"> <!-- 配置sql語句 sql id:通過namespace.id查找到當前sql語句;parameterType:傳入?yún)?shù)類 型;resultType:返回結(jié)果類型 --> <select id="findUserById" parameterType="Integer" resultType="com.lirui.mybatis.dao.User"> SELECT * FROM user WHERE id=#{IDENTITY } </select> <insert id="insertUser" parameterType="com.lirui.mybatis.dao.User"> <!-- selectKey 標簽實現(xiàn)主鍵返回 --> <!-- keyColumn:主鍵對應的表中的哪一列 --> <!-- keyProperty:主鍵對應的pojo中的哪一個屬性 --> <!-- order:設置在執(zhí)行insert語句前執(zhí)行查詢id的sql,孩紙在執(zhí)行insert語句之后執(zhí)行查詢id的 sql --> <!-- resultType:設置返回的id的類型 --> <selectKey keyColumn="id" keyProperty="id" order="AFTER" resultType="Integer"> SELECT LAST_INSERT_ID() </selectKey> INSERT INTO user (username,birthday,sex,address) VALUES (#{username},#{birthday},# {sex},#{address}) </insert> </mapper> -
測試
String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(); ...... sqlSession.commit(); sqlSession.close();
Mapper動態(tài)代理方式
只需要編寫Mapper接口(相當于Dao接口),由Mybatis框架根據(jù)接口定義創(chuàng)建接口的動態(tài)代理對象
- Mapper接口開發(fā)需要遵循以下規(guī)范:
- Mapper.xml文件中的namespace與mapper接口的類路徑相同。
- Mapper接口方法名和Mapper.xml中定義的每個statement的id相同
- Mapper接口方法的輸入?yún)?shù)類型和mapper.xml中定義的每個sql 的parameterType的類型相同
- Mapper接口方法的輸出參數(shù)類型和mapper.xml中定義的每個sql的resultType的類型相同
public interface UserMapper {
User findUserById(Integer id);
}
<mapper namespace="com.lirui.mybatis.mapper.UserMapper">
<select id="findUserById" parameterType="Integer" resultType="com.lirui.mybatis.bean.User">
SELECT * FROM user WHERE id=#{id}
</select>
</mapper>
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.findUserById(1);
System.out.println(user);
輸入映射及輸出映射
-
parameterType
-
傳遞簡單類型
#{...}${value} -
傳遞pojo對象
#{pojo對象屬性}${pojo對象屬性} -
傳遞pojo包裝對象
#{pojo對象屬性}${pojo對象屬性} -
傳遞多參數(shù)
- 接口
@Param("record") Orders record - xml文件
parameterType="map"#{record.xxx}
- 接口
-
-
resultType
指定將查詢結(jié)果映射為pojo,但需要pojo的屬性名和sql查詢的列名一致方可映射成功
- 輸出簡單類型
- 輸出pojo對象
- 輸出pojo列表
-
resultMap
如果sql查詢字段名和pojo的屬性名不一致,可以通過resultMap將字段名和屬性名作一個對應關系 ,resultMap實質(zhì)上還需要將查詢結(jié)果映射到pojo對象中。resultMap可以實現(xiàn)將查詢結(jié)果映射為復雜類型的pojo
<mapper namespace="com.xxx.mapper.OrderMapper"> <resultMap id="orderMap" type="Order"> <result property="userId" column="user_id"/> </resultMap> <select id="listOfOrder" resultMap="orderMap"> SELECT id, user_id, number, createtime, note FROM orders </select> </mapper>
動態(tài)Sql
通過mybatis提供的各種標簽方法實現(xiàn)動態(tài)拼接sql
-
if標簽
<if> xxx </if><select id="queryUserByWhere" parameterType="User" resultType="User"> SELECT * FROM user WHERE 1=1 <if test="sex!=null and sex!=''"> AND sex=#{sex} </if> <if test="username!=null and username!=''"> AND username LIKE "%"#{username}"%" </if> </select> -
where標簽
<where> xxx </where>可以自動添加where,同時處理sql語句中第一個and關鍵字
<select id="queryUserByWhere" parameterType="User" resultType="User"> SELECT * FROM user <!-- where標簽可以自動添加where關鍵字,同時處理sql語句中第一個前and關鍵字 --> <where> <if test="sex!=null and sex!=''"> AND sex=#{sex} </if> <if test="username!=null and username!=''"> AND username LIKE "%"#{username}"%" </if> </where> </select> -
SQL片段標簽
<sql> xxx </sql><include> xxx </include>Sql中可將重復的sql提取出來,使用時用include引用即可,最終達到sql重用的目的。
如果要使用別的Mapper.xml配置的sql片段,可以在include標簽屬性refid值添加對應的Mapper.xml的namespace
<select id="queryUserByWhere" parameterType="User" resultType="User"> <!-- 使用include標簽加載sql片段;refid是sql片段id --> SELECT <include refid="userContent"/> FROM user <!-- where標簽可以自動添加where關鍵字,同時處理sql語句中第一個and關鍵字 --> <where> <if test="sex!=null and sex!=''"> AND sex=#{sex} </if> <if test="username!=null and username!=''"> AND username LIKE "%"#{username}"%" </if> </where> </select> <sql id="userContent"> id, username, birthday, sex, address </sql> -
foreach標簽
<foreach> xxx </foreach>向sql傳遞數(shù)組或List,mybatis使用foreach解析
<sql id="userContent"> id, username, birthday, sex, address </sql> <select id="queryUserByIds" parameterType="QueryVo" resultType="User"> SELECT <include refid="userContent"/> FROM user <where> <!-- foreach標簽,進行遍歷 --> <!-- collection:遍歷的集合,這里是QueryVo的ids屬性 --> <!-- item:遍歷的項目,可以隨便寫,,但是和后面的#{}里面要一致 --> <!-- open:在前面添加的sql片段 --> <!-- close:在結(jié)尾處添加的sql片段 --> <!-- separator:指定遍歷的元素之間使用的分隔符 --> <foreach collection="ids" item="id" open="id in (" close=")" separator=","> ${id} </foreach> </where> </select>
關聯(lián)查詢
一對一查詢
-
ResultType
定義專門的pojo類作為輸出類型,pojo類中定義了sql查詢結(jié)果集所有的字段
-
ResultMap
根據(jù)表的關系,改造pojo對象,使用resultMap描述對象之間的關系
-
定義對象
class Many{
class One; } -
xml配置
<resultMap id="ManyMapper" type="Many"> <!-- 進行關聯(lián)查詢是,對象參數(shù)與列的對應不能省略,否則返回為null --> <id column="xxx" property="xxx"/> <result property="xxx" column="xxx"/> <association property="xxx" javaType="One"> <id property="id" column="userId"/> <result property="username" column="username"/> </association></resultMap>
<select id="xxx" resultMap="orderMap">
select xxx from Many m left join One o on m.id=o.id;
</select>
-
-
-
一對多查詢
-
定義對象
class One{ List<Many> list; } -
xml配置
<resultMap id="OneMapper" type="One"> <id property="xxx" column="xxx"/> <result property="xxx" column="xxx"/> <collection property="xxx" ofType="Many"> <id column="xxx" property="xxx"/> <result property="xxx" column="xxx"/> </collection> </resultMap> <select id="xxx" resultMap="OneMapper"> SELECT xxx FROM `One` o LEFT JOIN `Many` m ON o.id = m.id </select>
-
Sping與mybatis整合
Spring與mybatis整合,負責數(shù)據(jù)庫池及SessionFactory的創(chuàng)建,不管已下哪種方式都要配置數(shù)據(jù)庫池及SessionFactory
<!--加載配置文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--連接池-->
<!--數(shù)據(jù)源-->
<bean name="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxTotal" value="10"/>
<property name="maxIdle" value="5"/>
</bean>
<!--工廠方法-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="dataSource" ref="dataSource"/>
</bean>
//mybatis-config.xml
<!--bean起別名-->
<typeAliases>
<package name="com.lirui.mybatis.bean"/>
</typeAliases>
<!--mapper代理時使用,mapper接口映射mapper.xml文件,在同個文件夾下才能實現(xiàn)-->
<mappers>
<package name="com.lirui.mybatis.mapper"/>
</mappers>
-
傳統(tǒng)dao開發(fā)方式
原始的DAO開發(fā)接口+實現(xiàn)類來完成。需要dao實現(xiàn)類需要繼承SqlsessionDaoSupport類
-
spring生成實現(xiàn)類
<bean id="userDao" class="com.mybatis.dao.UserDaoImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean> -
實現(xiàn)類中調(diào)用執(zhí)行
SqlSession sqlSession = super.getSqlSession(); User user = sqlSession.selectOne("queryUserById", id);
-
-
手動配置mapper代理
創(chuàng)建mapper代理接口
實現(xiàn)接口與xml文件之前的關系映射
-
spring生成實現(xiàn)類
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> <!-- 配置Mapper接口 --> <property name="mapperInterface" value="cn.mybatis.mapper.UserMapper" /> <!-- 配置sqlSessionFactory --> <property name="sqlSessionFactory" ref="sqlSessionFactory" /> </bean> -
Service中調(diào)用執(zhí)行
ApplicationContext context=ClassPathXmlApplicationContext("classpath:applicationContext.xml"); UserMapper userMapper = this.context.getBean("userMapper"); User user = userMapper.queryUserById(1);
-
掃描方式配置mapper代理
創(chuàng)建mapper代理接口
實現(xiàn)接口與xml文件之前的關系映射
-
spring生成實現(xiàn)類
<!--Session綁定到接口--> <!-- Mapper代理的方式開發(fā)方式二,掃描包方式配置代理 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!-- 配置Mapper接口 --> <property name="basePackage" value="com.lirui.mybatis.mapper"/> </bean> -
Service中調(diào)用執(zhí)行
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); UserMapper userMapper=applicationContext.getBean(UserMapper.class); System.out.printf(String.valueOf(userMapper.findUserById(10)));