mybatis是什么?
mybatis是一人持久层框架,mybatis是一个不完全的ORM框架。sql语句需要程序员自己去编写,但是mybatis也有映射(输入参数映射、输出结果映射)。
mybatis入门门槛不高,学习成本低,让程序员把精力放在sql语句上,对sql语句优化非常方便,适用与需求变化较多项目,比如互联网项目。
mybatis框架执行过程:
1、配置mybatis的配置文件,SqlMapConfig.xml(名称不固定)
2、通过配置文件,加载mybatis运行环境,创建SqlSessionFactory会话工厂
SqlSessionFactory在实际使用时按单例方式。
3、通过SqlSessionFactory创建SqlSession
SqlSession是一个面向用户接口(提供操作数据库方法),实现对象是线程不安全的,建议sqlSession应用场合在方法体内。
4、调用sqlSession的方法去操作数据。
如果需要提交事务,需要执行SqlSession的commit()方法。
5、释放资源,关闭SqlSession
mybatis开发dao的方法:
1、原始dao 的方法
需要程序员编写dao接口和实现类
需要在dao实现类中注入一个SqlSessionFactory工厂。
2、mapper代理开发方法(建议使用)
只需要程序员编写mapper接口(就是dao接口)
程序员在编写mapper.xml(映射文件)和mapper.java需要遵循一个开发规范:
1、mapper.xml中namespace就是mapper.java的类全路径。
2、mapper.xml中statement的id和mapper.java中方法名一致。
3、mapper.xml中statement的parameterType指定输入参数的类型和mapper.java的方法输入 参数类型一致。
4、mapper.xml中statement的resultType指定输出结果的类型和mapper.java的方法返回值类型一致。
SqlMapConfig.xml配置文件:可以配置properties属性、别名、mapper加载。
输入映射:
parameterType:指定输入参数类型可以简单类型、pojo、hashmap。。
对于综合查询,建议parameterType使用包装的pojo,有利于系统 扩展。
输出映射:
resultType:
查询到的列名和resultType指定的pojo的属性名一致,才能映射成功。
reusltMap:
可以通过resultMap 完成一些高级映射。
如果查询到的列名和映射的pojo的属性名不一致时,通过resultMap设置列名和属性名之间的对应关系(映射关系)。可以完成映射。
高级映射:
将关联查询的列映射到一个pojo属性中。(一对一)
将关联查询的列映射到一个List<pojo>中。(一对多)
动态sql:(重点)
if判断(掌握) where foreach sql片段(掌握)
mybatis是一个持久层的框架,是apache下的顶级项目。
mybatis托管到goolecode下,再后来托管到github下(https://github.com/mybatis/mybatis-3/releases)。
mybatis让程序将主要精力放在sql上,通过mybatis提供的映射方式,自由灵活生成(半自动化,大部分需要程序员编写sql)满足需要sql语句。
mybatis可以将向 preparedStatement中的输入参数自动进行输入映射,将查询结果集灵活映射成java对象。(输出映射)
SqlMapConfig.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>
<!-- 和spring整合后 environments配置将废除-->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理,事务控制由mybatis-->
<transactionManager type="JDBC" />
<!-- 数据库连接池,由mybatis管理-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mybatis" />
<property name="username" value="root" />
<property name="password" value="852258" />
</dataSource>
</environment>
</environments>
<!-- 加载 映射文件 -->
<mappers>
<mapper resource="sqlmap/User.xml"/>
<!--通过resource方法一次加载一个映射文件 -->
<!-- <mapper resource="mapper/UserMapper.xml"/> -->
<!-- 通过mapper接口加载单个 映射文件
遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录 中
上边规范的前提是:使用的是mapper代理方法
-->
<!-- <mapper class="cn.itcast.mybatis.mapper.UserMapper"/> -->
<!-- 批量加载mapper
指定mapper接口的包名,mybatis自动扫描包下边所有mapper接口进行加载
遵循一些规范:需要将mapper接口类名和mapper.xml映射文件名称保持一致,且在一个目录 中
上边规范的前提是:使用的是mapper代理方法
-->
</mappers>
</configuration>
log4j.properties
# Global logging configuration
#在开发环境下日志级别要设置成DeBUG,生产环境设置成info或error
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
根据用户id(主键)查询用户信息
根据用户名称模糊查询用户信息
添加用户
删除 用户
更新用户
User.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">
<!-- namespace命名空间,作用就是对sql进行分类化管理,理解sql隔离
注意:使用mapper代理方法开发,namespace有特殊重要的作用
-->
<mapper namespace="test">
<!-- 在 映射文件中配置很多sql语句 -->
<!-- 需求:通过id查询用户表的记录 -->
<!-- 通过 select执行数据库查询
id:标识 映射文件中的 sql
将sql语句封装到mappedStatement对象中,所以将id称为statement的id
parameterType:指定输入 参数的类型,这里指定int型
#{}表示一个占位符号
#{id}:其中的id表示接收输入 的参数,参数名称就是id,如果输入 参数是简单类型,#{}中的参数名可以任意,可以value或其它名称
resultType:指定sql输出结果 的所映射的java对象类型,select指定resultType表示将单条记录映射成的java对象。
-->
<select id="findUserById" parameterType="int" resultType="com.zhang.mybatis.po.User">
SELECT * FROM USER WHERE id=#{value}
</select>
<!-- 根据用户名称模糊查询用户信息,可能返回多条
resultType:指定就是单条记录所映射的java对象 类型
${}:表示拼接sql串,将接收到参数的内容不加任何修饰拼接在sql中。
使用${}拼接sql,引起 sql注入
${value}:接收输入 参数的内容,如果传入类型是简单类型,${}中只能使用value
-->
<select id="findUserByName" parameterType="java.lang.String" resultType="com.zhang.mybatis.po.User">
SELECT * FROM USER WHERE username LIKE '%${value}%'
</select>
<!-- 添加用户
parameterType:指定输入 参数类型是pojo(包括 用户信息)
#{}中指定pojo的属性名,接收到pojo对象的属性值,mybatis通过OGNL获取对象的属性值
-->
<insert id="insertUser" parameterType="com.zhang.mybatis.po.User">
<!--
将插入数据的主键返回,返回到user对象中
SELECT LAST_INSERT_ID():得到刚insert进去记录的主键值,只适用与自增主键
keyProperty:将查询到主键值设置到parameterType指定的对象的哪个属性
order:SELECT LAST_INSERT_ID()执行顺序,相对于insert语句来说它的执行顺序
resultType:指定SELECT LAST_INSERT_ID()的结果类型
-->
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
SELECT LAST_INSERT_ID()
</selectKey>
insert into user(username,birthday,sex,address) value(#{username},#{birthday},#{sex},#{address})
<!--
使用mysql的uuid()生成主键
执行过程:
首先通过uuid()得到主键,将主键设置到user对象的id属性中
其次在insert执行时,从user对象中取出id属性值
-->
<!-- <selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">
SELECT uuid()
</selectKey>
insert into user(id,username,birthday,sex,address) value(#{id},#{username},#{birthday},#{sex},#{address}) -->
</insert>
<!-- 删除 用户
根据id删除用户,需要输入 id值
-->
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id=#{id}
</delete>
<!-- 根据id更新用户
分析:
需要传入用户的id
需要传入用户的更新信息
parameterType指定user对象,包括 id和更新信息,注意:id必须存在
#{id}:从输入 user对象中获取id属性值
-->
<update id="updateUser" parameterType="com.zhang.mybatis.po.User">
update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}
where id=#{id}
</update>
</mapper>
package com.zhang.mybatis.first;
import com.zhang.mybatis.po.User;
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 org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Date;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;
public class MybatisFirst {
public long getTime(String pattern) throws ParseException {
DateFormat format=new SimpleDateFormat("yyyy-MM-dd");
java.util.Date date=format.parse(pattern);
return date.getTime();
}
public SqlSession getSqlSession() throws IOException {
//sqlmap配置文件
String resource="SqlMapConfig.xml";
InputStream inputStream=Resources.getResourceAsStream(resource);
//创建会话工厂
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().
build(inputStream);
SqlSession sqlSession=sqlSessionFactory.openSession();
return sqlSession;
}
//根据id查询用户信息,得到一条记录结果
@Test
public void findUserByIdTest() throws IOException {
SqlSession sqlSession=getSqlSession();
User user=sqlSession.selectOne("test.findUserById",1);
System.out.println(user);
//释放资源
sqlSession.close();
}
//根据名称模糊查询用户列表
@Test
public void findUserByNameTest() throws IOException {
SqlSession sqlSession=getSqlSession();
List<User> users=sqlSession.selectList("test.findUserByName","小明");
System.out.println(users);
//释放资源
sqlSession.close();
}
@Test
public void insertUserTest() throws IOException, ParseException {
SqlSession sqlSession=getSqlSession();
long l=getTime("1997-5-13");
User user=new User();
user.setUsername("王博");
user.setBirthday(new Date(l));
user.setSex("男");
user.setAddress("宝鸡市");
sqlSession.insert("test.insertUser",user);
//提交事物
sqlSession.commit();
System.out.println(user.getId());
//释放资源
sqlSession.close();
}
@Test
public void deleteUser() throws IOException {
SqlSession sqlSession=getSqlSession();
sqlSession.delete("test.deleteUser",1);
sqlSession.commit();
sqlSession.close();
}
@Test
public void updateUser() throws IOException, ParseException {
SqlSession sqlSession=getSqlSession();
User user=new User();
user.setId(1);
user.setUsername("张大大");
user.setBirthday(new Date(getTime("1988-5-21")));
user.setSex("女");
user.setAddress("中国");
sqlSession.update("test.updateUser",user);
sqlSession.commit();
sqlSession.close();
}
}
#{}表示一个占位符号,#{}接收输入参数,类型可以是简单类型,pojo、hashmap。
如果接收简单类型,#{}中可以写成value或其它名称。
#{}接收pojo对象值,通过OGNL读取对象中的属性值,通过属性.属性.属性...的方式获取对象属性值。
${}表示一个拼接符号,会引用sql注入,所以不建议使用${}。
${}接收输入参数,类型可以是简单类型,pojo、hashmap。
如果接收简单类型,${}中只能写成value。
${}接收pojo对象值,通过OGNL读取对象中的属性值,通过属性.属性.属性...的方式获取对象属性值。
mybatis和hibernate本质区别和应用场景
hibernate:是一个标准ORM框架(对象关系映射)。入门门槛较高的,不需要程序写sql,sql语句自动生成了。
对sql语句进行优化、修改比较困难的。
应用场景:
适用与需求变化不多的中小型项目,比如:后台管理系统,erp、orm、oa。。
mybatis:专注是sql本身,需要程序员自己编写sql语句,sql修改、优化比较方便。mybatis是一个不完全 的ORM框架,虽然程序员自己写sql,mybatis 也可以实现映射(输入映射、输出映射)。
应用场景:
适用与需求变化较多的项目,比如:互联网项目。
企业进行技术选型,以低成本 高回报作为技术选型的原则,根据项目组的技术力量进行选择。
mybatis开发dao方法
SqlSessionFactoryBuilder
通过SqlSessionFactoryBuilder创建会话工厂SqlSessionFactory
将SqlSessionFactoryBuilder当成一个工具类使用即可,不需要使用单例管理SqlSessionFactoryBuilder。
在需要创建SqlSessionFactory时候,只需要new一次SqlSessionFactoryBuilder即可。
SqlSessionFactory
通过SqlSessionFactory创建SqlSession,使用单例模式管理sqlSessionFactory(工厂一旦创建,使用一个实例)。
将来mybatis和spring整合后,使用单例模式管理sqlSessionFactory。
SqlSession
SqlSession是一个面向用户(程序员)的接口。
SqlSession中提供了很多操作数据库的方法:如:selectOne(返回单个对象)、selectList(返回单个或多个对象)、。
SqlSession是线程不安全的,在SqlSesion实现类中除了有接口中的方法(操作数据库的方法)还有数据域属性。
SqlSession最佳应用场合在方法体内,定义成局部变量使用。
原始dao开发方法(程序员需要写dao接口和dao实现类)
程序员需要写dao接口和dao实现类。
需要向dao实现类中注入SqlSessionFactory,在方法体内通过SqlSessionFactory创建SqlSession
dao接口
package com.zhang.mybatis.dao;
import com.zhang.mybatis.po.User;
import java.util.List;
public interface UserDao {
/**
* 根据id查询用户
*/
User findUserById(int id) throws Exception;
/**
* 根据用户名或的用户列表
*/
List<User> findUserByName(String name) throws Exception;
/**
* 添加用户
*/
void insertUser(User user) throws Exception;
/**
* 根据id删除用户
*/
void deleteUser(int id) throws Exception;
}
dao接口实现类
package com.zhang.mybatis.dao;
import com.zhang.mybatis.po.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import java.util.List;
/**
* UserDao的实现类
*/
public class UserDaoIm implements UserDao{
private SqlSessionFactory sqlSessionFactory;
//注入工厂
public UserDaoIm(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
}
@Override
public User findUserById(int id) throws Exception {
//通过工厂创建SqlSession
SqlSession sqlSession=sqlSessionFactory.openSession();
User user=sqlSession.selectOne("test.findUserById",id);
//关闭会话
sqlSession.close();
return user;
}
@Override
public List<User> findUserByName(String name) throws Exception {
//通过工厂创建SqlSession
SqlSession sqlSession=sqlSessionFactory.openSession();
List<User> users=sqlSession.selectList("test.findUserByName",name);
//关闭会话
sqlSession.close();
return users;
}
@Override
public void insertUser(User user) throws Exception {
//通过工厂创建SqlSession
SqlSession sqlSession=sqlSessionFactory.openSession();
sqlSession.selectOne("test.insertUser",user);
//提交事物
sqlSession.commit();
//关闭会话
sqlSession.close();
}
@Override
public void deleteUser(int id) throws Exception {
//通过工厂创建SqlSession
SqlSession sqlSession=sqlSessionFactory.openSession();
sqlSession.selectOne("test.deleteUser",id);
//提交事物
sqlSession.commit();
//关闭会话
sqlSession.close();
}
}
测试代码
package com.zhang.mybatis.dao;
import com.zhang.mybatis.po.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Date;
import java.util.List;
public class UserDaoImTest {
private SqlSessionFactory sqlSessionFactory;
public UserDaoImTest() throws IOException {
String source= "SqlMapConfig.xml";
InputStream inputStream= Resources.getResourceAsStream(source);
sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void findUserById() throws Exception {
UserDao userDao=new UserDaoIm(sqlSessionFactory);
User user=userDao.findUserById(1);
System.out.println(user);
}
@Test
public void findUserByName() throws Exception {
UserDao userDao=new UserDaoIm(sqlSessionFactory);
List<User> users=userDao.findUserByName("博");
System.out.println(users);
}
@Test
public void insertUser() throws Exception {
UserDao userDao=new UserDaoIm(sqlSessionFactory);
User user=new User();
user.setUsername("张冯");
user.setBirthday(new Date(999999999));
user.setSex("男");
user.setAddress("商洛");
userDao.insertUser(user);
}
@Test
public void deleteUser() throws Exception {
UserDao userDao=new UserDaoIm(sqlSessionFactory);
userDao.deleteUser(22);
}
}
原始 dao开发问题
1、dao接口实现类方法中存在大量模板方法,设想能否将这些代码提取出来,大大减轻程序员的工作量。
2、调用sqlsession方法时将statement的id硬编码了 statement的id:"test.deleteUser"
3、调用sqlsession方法时传入的变量,由于sqlsession方法使用泛型,即使变量类型传入错误,在编译阶段也不报错,不利于程序员开发
mapper代理方法(程序员只需要mapper接口(相当 于dao接口))
程序员还需要编写mapper.xml映射文件
程序员编写mapper接口需要遵循一些开发规范,mybatis可以自动生成mapper接口实现类代理对象。
开发规范:
1、在mapper.xml中namespace等于mapper接口地址
2、mapper.java接口中的方法名和mapper.xml中statement的id一致
3、mapper.java接口中的方法输入参数类型和mapper.xml中statement的parameterType指定的类型一致。
4、mapper.java接口中的方法返回值类型和mapper.xml中statement的resultType指定的类型一致。
mapper.java
package com.zhang.mybatis.mapper;
import com.zhang.mybatis.po.User;
import com.zhang.mybatis.po.UserExten;
import com.zhang.mybatis.po.UserQueryVo;
import java.util.List;
/**
* UserMapper接口
*/
public interface UserMapper {
/**
* 用户综合查询
*/
List<UserExten> findUserList(UserQueryVo queryVo)throws Exception;
/**
* 用户综合查询
*/
int findUserCount(UserQueryVo queryVo)throws Exception;
/**
* 用户综合查询
*/
List<User> findUserByIdResultMap(int id)throws Exception;
/**
* 根据id查询用户
*/
User findUserById(int id) throws Exception;
/**
* 根据用户名或的用户列表
*/
List<User> findUserByName(String name) throws Exception;
/**
* 添加用户
*/
void insertUser(User user) throws Exception;
/**
* 根据id删除用户
*/
void deleteUser(int id) throws Exception;
}
mapper.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">
<!-- namespace命名空间,作用就是对sql进行分类化管理,理解sql隔离
注意:使用mapper代理方法开发,namespace有特殊重要的作用
-->
<mapper namespace="com.zhang.mybatis.mapper.UserMapper">
<!--定义sql片段-->
<sql id="queryUser">
<if test="userExten.sex!=null">
and user.sex=#{userExten.sex}
</if>
<if test="userExten.sex!=null and userExten.username!=null">
and user.username like '%${userExten.username}%'
</if>
<if test="ids!=null">
<!--使用foreach遍历传入ids
and (id=1 or id=28 or id=30)
and IN id(1,28,30)
-->
<foreach collection="ids" item="user_id" open="and (" close=")"
separator=" or ">
id=#{user_id}
</foreach>
</if>
</sql>
<resultMap id="userMap" type="user">
<id column="id_" property="id"></id>
<result column="username_" property="username"/>
</resultMap>
<!-- 在 映射文件中配置很多sql语句 -->
<!-- 需求:通过id查询用户表的记录 -->
<!-- 通过 select执行数据库查询
id:标识 映射文件中的 sql
将sql语句封装到mappedStatement对象中,所以将id称为statement的id
parameterType:指定输入 参数的类型,这里指定int型
#{}表示一个占位符号
#{id}:其中的id表示接收输入 的参数,参数名称就是id,如果输入 参数是简单类型,#{}中的参数名可以任意,可以value或其它名称
resultType:指定sql输出结果 的所映射的java对象类型,select指定resultType表示将单条记录映射成的java对象。
-->
<!--where标签两个条件都满足时,会自动去掉第一个and-->
<select id="findUserList" parameterType="userQueryVo" resultType="UserExten">
SELECT * FROM User
<where>
<include refid="queryUser"></include>
</where>
</select>
<select id="findUserCount" parameterType="userQueryVo" resultType="int">
SELECT * FROM User
<where>
<include refid="queryUser"></include>
</where>
</select>
<select id="findUserById" parameterType="int" resultType="com.zhang.mybatis.po.User">
SELECT * FROM USER WHERE id=#{value}
</select>
<select id="findUserByIdResultMap" parameterType="int" resultMap="userMap">
SELECT id id_,username username_ FROM USER WHERE id>#{value}
</select>
<!-- 根据用户名称模糊查询用户信息,可能返回多条
resultType:指定就是单条记录所映射的java对象 类型
${}:表示拼接sql串,将接收到参数的内容不加任何修饰拼接在sql中。
使用${}拼接sql,引起 sql注入
${value}:接收输入 参数的内容,如果传入类型是简单类型,${}中只能使用value
-->
<select id="findUserByName" parameterType="java.lang.String" resultType="user">
SELECT * FROM USER WHERE username LIKE '%${value}%'
</select>
<!-- 添加用户
parameterType:指定输入 参数类型是pojo(包括 用户信息)
#{}中指定pojo的属性名,接收到pojo对象的属性值,mybatis通过OGNL获取对象的属性值
-->
<insert id="insertUser" parameterType="com.zhang.mybatis.po.User">
<!--
将插入数据的主键返回,返回到user对象中
SELECT LAST_INSERT_ID():得到刚insert进去记录的主键值,只适用与自增主键
keyProperty:将查询到主键值设置到parameterType指定的对象的哪个属性
order:SELECT LAST_INSERT_ID()执行顺序,相对于insert语句来说它的执行顺序
resultType:指定SELECT LAST_INSERT_ID()的结果类型
-->
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
SELECT LAST_INSERT_ID()
</selectKey>
insert into user(username,birthday,sex,address) value(#{username},#{birthday},#{sex},#{address})
<!--
使用mysql的uuid()生成主键
执行过程:
首先通过uuid()得到主键,将主键设置到user对象的id属性中
其次在insert执行时,从user对象中取出id属性值
-->
<!-- <selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">
SELECT uuid()
</selectKey>
insert into user(id,username,birthday,sex,address) value(#{id},#{username},#{birthday},#{sex},#{address}) -->
</insert>
<!-- 删除 用户
根据id删除用户,需要输入 id值
-->
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id=#{id}
</delete>
<!-- 根据id更新用户
分析:
需要传入用户的id
需要传入用户的更新信息
parameterType指定user对象,包括 id和更新信息,注意:id必须存在
#{id}:从输入 user对象中获取id属性值
-->
<update id="updateUser" parameterType="com.zhang.mybatis.po.User">
update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}
where id=#{id}
</update>
</mapper>
在SqlMapConfig.xml中加载mapper.xml
<mappers>
<mapper resource="sqlmap/User.xml"/>
<!--<mapper resource="sqlmap/UserMapper.xml"/>-->
<!--通过mapper接口加载映射文件,
规范:需要将mapper接口类名和mapper.xml名保持一致,并在同一个目录内,
前提是使用的mapper代理方法-->
<!-- <mapper class="com.zhang.mybatis.mapper.UserMapper"/>-->
<!--批量加载映射文件(推荐使用)-->
<package name="com.zhang.mybatis.mapper"/>
</mappers>
测试
package com.zhang.mybatis.mapper;
import com.zhang.mybatis.po.User;
import com.zhang.mybatis.po.UserExten;
import com.zhang.mybatis.po.UserQueryVo;
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 org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.*;
public class UserMapperTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void setUp()throws Exception{
String resource="SqlMapConfig.xml";
InputStream inputStream= Resources.getResourceAsStream(resource);
sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFindUserById() throws Exception {
SqlSession sqlSession=sqlSessionFactory.openSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
User user=userMapper.findUserById(28);
System.out.println(user);
}
@Test
public void testFindUserByIdResultMap() throws Exception {
SqlSession sqlSession=sqlSessionFactory.openSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
List<User> user=userMapper.findUserByIdResultMap(28);
System.out.println(user);
}
@Test
public void testFindUserByName() throws Exception {
SqlSession sqlSession=sqlSessionFactory.openSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
List<User> user=userMapper.findUserByName("冯");
System.out.println(user);
}
@Test
public void testFindUserList() throws Exception {
SqlSession sqlSession=sqlSessionFactory.openSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
UserQueryVo queryVo=new UserQueryVo();
UserExten userExten=new UserExten();
userExten.setSex("男");
userExten.setUsername("王博");
List<Integer> ids=new ArrayList<>();
ids.add(1);
ids.add(28);
ids.add(30);
queryVo.setIds(ids);
queryVo.setUserExten(userExten);
List<UserExten> user=userMapper.findUserList(queryVo);
System.out.println(user);
}
@Test
public void testFindUserCount() throws Exception {
SqlSession sqlSession=sqlSessionFactory.openSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
UserQueryVo queryVo=new UserQueryVo();
UserExten userExten=new UserExten();
userExten.setSex("男");
userExten.setUsername("王博");
queryVo.setUserExten(userExten);
int user=userMapper.findUserCount(queryVo);
System.out.println(user);
}
}
即使mapper接口只有一个参数,可以使用包装类型的pojo满足不同的业务方法的需求。
SqlMapConfig.xml
mybatis的全局配置文件SqlMapConfig.xml,配置内容如下:
properties(属性)
settings(全局配置参数)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境集合属性对象)
environment(环境子属性对象)
transactionManager(事务管理)
dataSource(数据源)
mappers(映射器)
<?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="db.properties"></properties>
<!--定义别名-->
<typeAliases>
<!--<typeAlias type="com.zhang.mybatis.po.User" alias="user"></typeAlias>-->
<package name="com.zhang.mybatis.po"></package>
</typeAliases>
<!-- 和spring整合后 environments配置将废除-->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理,事务控制由mybatis-->
<transactionManager type="JDBC" />
<!-- 数据库连接池,由mybatis管理-->
<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="sqlmap/User.xml"/>
<!--<mapper resource="sqlmap/UserMapper.xml"/>-->
<!--通过mapper接口加载映射文件,
规范:需要将mapper接口类名和mapper.xml名保持一致,并在同一个目录内,
前提是使用的mapper代理方法-->
<!-- <mapper class="com.zhang.mybatis.mapper.UserMapper"/>-->
<!--批量加载映射文件(推荐使用)-->
<package name="com.zhang.mybatis.mapper"/>
</mappers>
</configuration>
typeAliases(别名)重点
需求
在mapper.xml中,定义很多的statement,statement需要parameterType指定输入参数的类型、需要resultType指定输出结果的映射类型。
如果在指定类型时输入类型全路径,不方便进行开发,可以针对parameterType或resultType指定的类型定义一些别名,在mapper.xml中通过别名定义,方便开发。
mybatis默认支持别名
别名 | 映射的类型 |
_byte | byte |
_long | long |
_short | short |
_int | int |
_integer | int |
_double | double |
_float | float |
_boolean | boolean |
string | String |
byte | Byte |
long | Long |
short | Short |
int | Integer |
integer | Integer |
double | Double |
float | Float |
boolean | Boolean |
date | Date |
decimal | BigDecimal |
bigdecimal | BigDecimal |
自定义别名
在SqlMapConfig.xml中
<!--定义别名-->
<typeAliases>
<!--单个别名-->
<!--<typeAlias type="com.zhang.mybatis.po.User" alias="user"></typeAlias>-->
<!--批量定义别名-->
<package name="com.zhang.mybatis.po"></package>
</typeAliases>
typeHandlers(类型处理器)
mybatis中通过typeHandlers完成jdbc类型和java类型的转换。
通常情况下,mybatis提供的类型处理器满足日常需要,不需要自定义.
mybatis支持类型处理器:
类型处理器 | Java类型 | JDBC类型 |
BooleanTypeHandler | Boolean,boolean | 任何兼容的布尔值 |
ByteTypeHandler | Byte,byte | 任何兼容的数字或字节类型 |
ShortTypeHandler | Short,short | 任何兼容的数字或短整型 |
IntegerTypeHandler | Integer,int | 任何兼容的数字和整型 |
LongTypeHandler | Long,long | 任何兼容的数字或长整型 |
FloatTypeHandler | Float,float | 任何兼容的数字或单精度浮点型 |
DoubleTypeHandler | Double,double | 任何兼容的数字或双精度浮点型 |
BigDecimalTypeHandler | BigDecimal | 任何兼容的数字或十进制小数类型 |
StringTypeHandler | String | CHAR和VARCHAR类型 |
ClobTypeHandler | String | CLOB和LONGVARCHAR类型 |
NStringTypeHandler | String | NVARCHAR和NCHAR类型 |
NClobTypeHandler | String | NCLOB类型 |
ByteArrayTypeHandler | byte[] | 任何兼容的字节流类型 |
BlobTypeHandler | byte[] | BLOB和LONGVARBINARY类型 |
DateTypeHandler | Date(java.util) | TIMESTAMP类型 |
DateOnlyTypeHandler | Date(java.util) | DATE类型 |
TimeOnlyTypeHandler | Date(java.util) | TIME类型 |
SqlTimestampTypeHandler | Timestamp(java.sql) | TIMESTAMP类型 |
SqlDateTypeHandler | Date(java.sql) | DATE类型 |
SqlTimeTypeHandler | Time(java.sql) | TIME类型 |
ObjectTypeHandler | 任意 | 其他或未指定类型 |
EnumTypeHandler | Enumeration类型 | VARCHAR-任何兼容的字符串类型,作为代码存储(而不是索引)。 |
mappers(映射配置)
通过resource加载单个映射文件
通过mapper接口加载单个mapper
批量加载mapper(推荐使用)
<mappers>
<mapper resource="sqlmap/User.xml"/>
<!--<mapper resource="sqlmap/UserMapper.xml"/>-->
<!--通过mapper接口加载映射文件,
规范:需要将mapper接口类名和mapper.xml名保持一致,并在同一个目录内,
前提是使用的mapper代理方法-->
<!-- <mapper class="com.zhang.mybatis.mapper.UserMapper"/>-->
<!--批量加载映射文件(推荐使用)-->
<package name="com.zhang.mybatis.mapper"/>
</mappers>
查询出来的结果集只有一行且一列,可以使用简单类型进行输出映射
mybatis中使用resultMap完成高级输出结果映射
定义reusltMap
<resultMap id="userMap" type="user">
<id column="id_" property="id"></id>
<result column="username_" property="username"/>
</resultMap>
使用resultMap作为statement的输出映射类型
<select id="findUserByIdResultMap" parameterType="int" resultMap="userMap">
SELECT id id_,username username_ FROM USER WHERE id>#{value}
</select>
使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。
如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系
动态sql
用户信息综合查询列表和用户信息查询列表总数这两个statement的定义使用动态sql。
对查询条件进行判断,如果输入参数不为空才进行查询条件拼接
sql片段
将上边实现的动态sql判断代码块抽取出来,组成一个sql片段。其它的statement中就可以引用sql片段。
方便程序员进行开发
foreach
向sql传递数组或List,mybatis使用foreach解析
<!--定义sql片段-->
<sql id="queryUser">
<if test="userExten.sex!=null">
and user.sex=#{userExten.sex}
</if>
<if test="userExten.sex!=null and userExten.username!=null">
and user.username like '%${userExten.username}%'
</if>
<if test="ids!=null">
<!--使用foreach遍历传入ids
and (id=1 or id=28 or id=30)
and IN id(1,28,30)
-->
<foreach collection="ids" item="user_id" open="and (" close=")"
separator=" or ">
id=#{user_id}
</foreach>
</if>
</sql>
<select id="findUserList" parameterType="userQueryVo" resultType="UserExten">
SELECT * FROM User
<where>
<include refid="queryUser"></include>
</where>
</select>