每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能共享使用,它是线程不安全的
配置文件
(已下载IDEA Mybatis插件 ---- MyBatis plugin)
-
SqlMapConfig.xml
mybatis的全局配置文件,配置了mybatis的运行环境等信息
-
配置的内容和顺序如下:
properties(属性) ---- 用resource属性加载外部配置文件
typeAliases(类型别名)---- 给类起别名
-
environments(环境集合属性对象)
- environment(环境子属性对象)
- transactionManager(事务管理)
- dataSource(数据源)
-
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"/> <!-- 数据库连接池 --> <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映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载,
#{} ---- 占位符
${} ---- 字符串拼接,${}里面传递简单类型时必须写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:传入参数类 型;resultType:返回结果类型 --> <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 标签实现主键返回 --> <!-- keyColumn:主键对应的表中的哪一列 --> <!-- keyProperty:主键对应的pojo中的哪一个属性 --> <!-- order:设置在执行insert语句前执行查询id的sql,孩纸在执行insert语句之后执行查询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动态代理方式
只需要编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象
- Mapper接口开发需要遵循以下规范:
- Mapper.xml文件中的namespace与mapper接口的类路径相同。
- Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
- Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
- Mapper接口方法的输出参数类型和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对象属性}
-
传递多参数
- 接口
@Param("record") Orders record
- xml文件
parameterType="map"
#{record.xxx}
- 接口
-
-
resultType
指定将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功
- 输出简单类型
- 输出pojo对象
- 输出pojo列表
-
resultMap
如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中。resultMap可以实现将查询结果映射为复杂类型的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>
动态Sql
通过mybatis提供的各种标签方法实现动态拼接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传递数组或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:在结尾处添加的sql片段 --> <!-- separator:指定遍历的元素之间使用的分隔符 --> <foreach collection="ids" item="id" open="id in (" close=")" separator=","> ${id} </foreach> </where> </select>
关联查询
一对一查询
-
ResultType
定义专门的pojo类作为输出类型,pojo类中定义了sql查询结果集所有的字段
-
ResultMap
根据表的关系,改造pojo对象,使用resultMap描述对象之间的关系
-
定义对象
class Many{
class One; }
-
xml配置
<resultMap id="ManyMapper" type="Many"> <!-- 进行关联查询是,对象参数与列的对应不能省略,否则返回为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整合,负责数据库池及SessionFactory的创建,不管已下哪种方式都要配置数据库池及SessionFactory
<!--加载配置文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--连接池-->
<!--数据源-->
<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文件,在同个文件夹下才能实现-->
<mappers>
<package name="com.lirui.mybatis.mapper"/>
</mappers>
-
传统dao开发方式
原始的DAO开发接口+实现类来完成。需要dao实现类需要继承SqlsessionDaoSupport类
-
spring生成实现类
<bean id="userDao" class="com.mybatis.dao.UserDaoImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean>
-
实现类中调用执行
SqlSession sqlSession = super.getSqlSession(); User user = sqlSession.selectOne("queryUserById", id);
-
-
手动配置mapper代理
创建mapper代理接口
实现接口与xml文件之前的关系映射
-
spring生成实现类
<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中调用执行
ApplicationContext context=ClassPathXmlApplicationContext("classpath:applicationContext.xml"); UserMapper userMapper = this.context.getBean("userMapper"); User user = userMapper.queryUserById(1);
-
扫描方式配置mapper代理
创建mapper代理接口
实现接口与xml文件之前的关系映射
-
spring生成实现类
<!--Session绑定到接口--> <!-- Mapper代理的方式开发方式二,扫描包方式配置代理 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!-- 配置Mapper接口 --> <property name="basePackage" value="com.lirui.mybatis.mapper"/> </bean>
-
Service中调用执行
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); UserMapper userMapper=applicationContext.getBean(UserMapper.class); System.out.printf(String.valueOf(userMapper.findUserById(10)));