一、mybatis下载、导包、基本使用
1、mybatis下载地址:https://github.com/mybatis/mybatis-3/releases,下载后解压可以获取mybatis需要的jar包
3、添加约束
4、在src下写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">
如果mybatis没有和spring整合(和spring整合后就不需要了),而是单独使用时需要在配置文件里添加一下信息:
<configuration>
<environments default="development">
<environment id="development">
<!-- 使用jdbc进行事务管理 -->
<transactionManager type="JDBC" />
<!-- 数据库连接池配置 、连接数据库四大参数配置 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="123" />
</dataSource>
</environment>
</environments>
</configuration>
5、添加mapper.xml,用来书写操作表的sql语句,UserMapper.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">
<!-- 书写增、删、改、查Sql语句 -->
<mapper namespace="cn.znh.mybatis.mapper.UserMapper">
<!-- 根据用户id查询用户, parameterType:参数类型 resultType:查询结果返回值类型 #{id}:占位符相当于jdbc时的? -->
<select id="queryUserById" parameterType="Integer" resultType="cn.znh.mybatis.domain.User">
select * from user where id= #{id}
</select>
</mapper>
并在主配置文件中引入UserMapper.xml:
<mappers>
<mapper resource="cn/znh/mybatis/mapper/UserMapper.xml"/>
</mappers>
6、书写测试代码:
@Test
public void queryUserById() throws IOException {
// 加载主配置文件
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 获取SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取SqlSession
SqlSession session = sessionFactory.openSession();
// 根据用户id查询用户
User user = session.selectOne("user.queryUserById", 16);
System.out.println(user);
}
1、 基本思路:使用mapper动态代理方式可以简化传统的dao层操作代码,不需要书写dao层的实现类,只需要书写dao层的接口(Mapper接口)即可。
Mybatis会根据接口定义的方法生产动态代理对象,从而调用dao层方法。
2、 Mapper接口(dao层接口)书写时需要遵循四个原则:
a、Mapper.xml文件中的namespace与Mapper接口的类路径相同。
b、Mapper接口方法名和Mapper.xml中定义的每个sql语句的id相同。
c、Mapper接口方法的输入参数类型和Mapper.xml中定义的每个sql的parameterType的类型相同。
d、Mapper接口方法的返回值类型和Mapper.xml中定义的每个sql的resultType的类型相同。
3、书写UserMapper.java和UserMapper.xml
/**
* 用户的Mapper接口(dao层接口)
*
* @author Administrator
*
*/
public interface UserMapper {
/**
* 根据用户名模糊查询用户列表
*
* @param userName
* @return
*/
public List<User> queryUsersByUserName(String username);
}
<mapper namespace="cn.znh.mybatis.mapper.UserMapper">
<select id="queryUsersByUserName" parameterType="String" resultType="User">
select * from user where username like '%${value}%'
</select>
</mapper>
4、测试代码
@Test
public void queryUserByUserName() throws IOException {
// 加载主配置文件
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 获取SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取SqlSession
SqlSession session = sessionFactory.openSession();
// 根据用户名称模糊查询用户
UserMapper uMapper = session.getMapper(UserMapper.class);
List<User> users = uMapper.queryUsersByUserName("明");
System.out.println(users);
}
5、说明:此时对Mapper.xml的文件名和位置不做要求,对Mapper接口的名称和位置也不做要求。(为下面的SqlMapConfig.xml的一些配置做对比)
三、SqlMapConfig.xml的一些配置
1、 自定义别名
a、单个别名定义,SqlMapConfig.xml中的配置:
<typeAliases>
<!-- 自定义单个别名,用user指代cn.znh.mybatis.domain.User-->
<typeAlias type="cn.znh.mybatis.domain.User" alias="user" />
</typeAliases>
在UserMapper.xml中的使用,resultType="user"
<select id="queryUserById" parameterType="Integer" resultType="user">
select * from user where id= #{v}
</select>
b、多个别名定义,SqlMapConfig.xml中的配置:
<typeAliases>
<!-- 批量别名定义,别名是指定的包下的每个类名(每个类的类名可以指代自身的全路径,大小写都可以) -->
<package name="cn.zhn.mybatis.domain" />
</typeAliases>
在UserMapper.xml中的使用, resultType="User"
<select id="queryUsersByUserName" parameterType="String" resultType="User">
select * from user where username like '%${value}%'
</select>
2、 Mapper.xml的另一种引用方式
a、 在SqlMapConfig.xml引入Mapper.xml有很多种方式,上文的1.5是一种方式,还有一种开发中最常用的方式是package引入方式。
就是通过package注册所有的mapper接口,进而找到mapper.xml的一种实现方式。
b、 使用这种方式要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录下。
c、 在SqlMapConfig.xml中的配置:
<mappers>
<package name="cn.zhn.mybatis.mapper" />
</mappers>
四、动态Sql
1、 if标签,多个条件时会用到,Mapper.xml配置:
<select id="queryUsersByUserNameAndSex" parameterType="User" resultType="User">
select * from user where
<if test="username!=null and username!=''">
username=#{username}
</if>
<if test="sex!=null and sex!=''">
and sex=#{sex}
</if>
</select>
测试代码:
@Test
public void queryUserByUserNameAndSex() throws IOException {
// 加载主配置文件
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 获取SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取SqlSession
SqlSession session = sessionFactory.openSession();
// 根据用户名和性别查询用户
UserMapper uMapper = session.getMapper(UserMapper.class);
User user = new User();
user.setUsername("张三");
user.setSex("1");
List<User> users = uMapper.queryUsersByUserNameAndSex(user);
System.out.println(users);
}
2、 where标签
使用if标签有条件值为空,就会出现多个and的情况,这样sql语句就会报错了,比如上例中的username为空,就会导致sex条件前多个and的错误语句。
Where标签可以解决这种问题,可以过滤掉前and。
<select id="queryUsersByUserNameAndSex" parameterType="User" resultType="User">
select * from user
<where>
<if test="username!=null and username!=''">
username=#{username}
</if>
<if test="sex!=null and sex!=''">
and sex=#{sex}
</if>
</where>
</select>
测试代码:
@Test
public void queryUserByUserNameAndSex() throws IOException {
// 加载主配置文件
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 获取SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取SqlSession
SqlSession session = sessionFactory.openSession();
// 根据用户名和性别查询用户
UserMapper uMapper = session.getMapper(UserMapper.class);
User user = new User();
//user.setUsername("张三");
user.setSex("1");
List<User> users = uMapper.queryUsersByUserNameAndSex(user);
System.out.println(users);
}
3、 foreach标签
当需要向sql中传递数组或者list集合时,需要用到foreach标签。比如根据多个用户id查询用户信息。原生sql语句
为:SELECT * FROM user WHERE id IN (16,25,26)。IN里的参数就要用到foreach处理。有3种方式进行传参:
a、 数组
<select id="queryUsersByIds" resultType="User">
<!-- collection:遍历的集合,必须写array不能写其他的 -->
<!-- item:指代单个元素(相当于条目变量),可以随便写,但是要和后面的#{}里面的一致 -->
<!-- open:在前面添加的sql片段 -->
<!-- close:在结尾处添加的sql片段 -->
<!-- separator:指定遍历的元素之间使用的分隔符 ,这里是逗号 -->
select * from user
<where>
id in
<foreach collection="array" item="idItem" separator="," open="(" close=")">
#{idItem}
</foreach>
</where>
</select>
测试代码:
@Test
public void queryUserByIds() throws IOException {
// 加载主配置文件
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 获取SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取SqlSession
SqlSession session = sessionFactory.openSession();
UserMapper uMapper = session.getMapper(UserMapper.class);
Integer[] idsIntegers={16,25,26};
List<User> users = uMapper.queryUsersByIds(idsIntegers);
System.out.println(users);
}
b、 List
<select id="queryUsersByIds" resultType="User">
<!-- collection:遍历的集合,必须写list不能写其他的 -->
<!-- item:指代单个元素(相当于条目变量),可以随便写,但是要和后面的#{}里面的一致 -->
<!-- open:在前面添加的sql片段 -->
<!-- close:在结尾处添加的sql片段 -->
<!-- separator:指定遍历的元素之间使用的分隔符 ,这里是逗号 -->
select * from user
<where>
id in
<foreach collection="list" item="idItem" separator="," open="(" close=")">
#{idItem}
</foreach>
</where>
</select>
测试代码:
@Test
public void queryUserByIds() throws IOException {
// 加载主配置文件
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 获取SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取SqlSession
SqlSession session = sessionFactory.openSession();
UserMapper uMapper = session.getMapper(UserMapper.class);
List<Integer> idsIntegers=new ArrayList<>();
idsIntegers.add(16);
idsIntegers.add(25);
idsIntegers.add(26);
List<User> users = uMapper.queryUsersByIds(idsIntegers);
System.out.println(users);
}
c、 QueryVo(包装类)
public class QueryVo {
private List<Integer> idList;
private Integer[] idArray;
public List<Integer> getIdList() {
return idList;
}
public void setIdList(List<Integer> idList) {
this.idList = idList;
}
public Integer[] getIdArray() {
return idArray;
}
public void setIdArray(Integer[] idArray) {
this.idArray = idArray;
}
}
<select id="queryUsersByIds" parameterType="QueryVo" resultType="User">
<!-- collection:遍历的集合,这里是QueryVo的idList属性-->
<!-- item:指代单个元素(相当于条目变量),可以随便写,但是要和后面的#{}里面的一致 -->
<!-- open:在前面添加的sql片段 -->
<!-- close:在结尾处添加的sql片段 -->
<!-- separator:指定遍历的元素之间使用的分隔符 ,这里是逗号 -->
select * from user
<where>
id in
<foreach collection="idList" item="idItem" separator="," open="(" close=")">
#{idItem}
</foreach>
</where>
</select>
测试代码:
@Test
public void queryUserByIds() throws IOException {
// 加载主配置文件
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 获取SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取SqlSession
SqlSession session = sessionFactory.openSession();
UserMapper uMapper = session.getMapper(UserMapper.class);
QueryVo qVo=new QueryVo();
List<Integer> idsIntegers=new ArrayList<>();
idsIntegers.add(16);
idsIntegers.add(25);
idsIntegers.add(26);
qVo.setIdList(idsIntegers);
List<User> users = uMapper.queryUsersByIds(qVo);
System.out.println(users);
}
五、表关联操作
1、一对一(以订单表为参照,订单和用户的一对一关系,一个订单只对应一个用户)
在Orders中添加private User user;
<resultMap type="Orders" id="order">
<!-- Orders表自身的手动映射,需要查询的Orders字段都需要手动映射,下面只会查id,userId,createtime -->
<id column="id" property="id" />
<result column="user_id" property="userId" />
<result column="createtime" property="createtime" />
<!--以订单为参照的,一对一订单和用户的手动映射,需要查询的用户的字段都需要手动映射一下 ,下面只会查username,sex,address -->
<association property="user" javaType="User">
<result column="username" property="username" />
<result column="sex" property="sex" />
<result column="address" property="address" />
</association>
</resultMap>
<select id="queryOrderUsers" resultMap="order">
select * from orders o
left join user u
on o.user_id=u.id
</select>
测试代码:
@Test
public void fun1() throws IOException {
// 加载主配置文件
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 获取SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取SqlSession
SqlSession session = sessionFactory.openSession();
UserMapper uMapper = session.getMapper(UserMapper.class);
List<Orders> orders = uMapper.queryOrderUsers();
System.out.println(orders);
}
2、一对多(以用户表为参照,用户和订单的对应关系,一个用户有多个订单)
在User中添加private List<Orders> orderList;
<resultMap type="User" id="user">
<id column="id" property="id" />
<result column="username" property="username" />
<!-- 一对多关系 -->
<collection property="orderList" ofType="Orders">
<result column="user_id" property="userId" />
<result column="number" property="number" />
</collection>
</resultMap>
<select id="queryUserOrders" resultMap="user">
select * from user u
leftjoin orders o
on o.user_id=u.id
</select>
测试代码:
@Test
public void fun2() throws IOException {
// 加载主配置文件
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 获取SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取SqlSession
SqlSession session = sessionFactory.openSession();
UserMapper uMapper = session.getMapper(UserMapper.class);
List<User> users = uMapper.queryUserOrders();
System.out.println(users);
}
六、spring和mybatis的整合
1、导包,需要导入的包如下:
a、spring的jar包
b、Mybatis的jar包
c、Spring+mybatis的整合包
d、数据库驱动jar包
e、数据库连接池的jar包
jar图片
2、添加spring和mybatis的约束
跟单独使用spring和mybatis时一样
3、在src下创建applicationContext.xml配置文件、sqlMapConfig.xml配置文件、db.properties配置文件
前两个配置文件头内容跟单独使用spring和mybatis时一样,db.properties里配置的是数据库连接参数:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
jdbc.username=root
jdbc.password=123
4、在applicationContext中配置
<!-- 引入db配置文件 -->
<context:property-placeholder location="classpath:db.properties" />
<!-- 数据库连接池配置 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<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="maxActive" value="10" />
<property name="maxIdle" value="5" />
</bean>
<!-- 注入Mybatis的sqlSessionFactory工厂 -->
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 核心配置文件的位置 -->
<property name="configLocation" value="classpath:sqlMapConfig.xml" />
</bean>
5、原始dao开发,在applicationContext中注入dao类,从spring中获取dao实现类进行数据库操作(这种方式很少用)
<!-- 注入userDao,userDao依赖sqlSessionFactory工厂-->
<bean id="userDao" class="cn.znh.mybatis.dao.UserDaoImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactoryBean" />
</bean>
6、Mapper动态代理开发(常用)
a、在applicationContext.xml中配置
方式一:
<!-- 注入MapperFactoryBean,指定mapperInterface,从spring中获取mapper对象-->
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="sqlSessionFactory" ref="sqlSessionFactoryBean" />
<property name="mapperInterface" value="cn.zhn.mybatis.mapper.UserMapper" />
</bean>
方式二:
<!-- Mapper包扫描方式,不需要指定具体的mapperInterface,会自动扫描指定包下面的所有mapper -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 基本包 -->
<property name="basePackage" value="cn.zhn.mybatis.mapper"/>
</bean>
b、编写UserMapper.java和UserMapper.xml
public interface UserMapper {
public User queryUserById(Integer id);
}
<mapper namespace="cn.zhn.mybatis.mapper.UserMapper">
<!-- 根据用户id查询用户-->
<select id="queryUserById" parameterType="Integer" resultType="User">
select * from user where id= #{id}
</select>
</mapper>
c、编写测试代码
@Test
public void fun1() {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper uMapper = (UserMapper) ac.getBean(UserMapper.class);
User user = uMapper.queryUserById(16);
System.out.print(user);
}
1、mybatis下载地址:https://github.com/mybatis/mybatis-3/releases,下载后解压可以获取mybatis需要的jar包
2、导包,需要导入上面项目的lib下的包、mybatis-3.2.7.jar、mysql-connector-java-5.1.8.jar这三部分
3、添加约束
4、在src下写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">
如果mybatis没有和spring整合(和spring整合后就不需要了),而是单独使用时需要在配置文件里添加一下信息:
<configuration>
<environments default="development">
<environment id="development">
<!-- 使用jdbc进行事务管理 -->
<transactionManager type="JDBC" />
<!-- 数据库连接池配置 、连接数据库四大参数配置 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="123" />
</dataSource>
</environment>
</environments>
</configuration>
5、添加mapper.xml,用来书写操作表的sql语句,UserMapper.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">
<!-- 书写增、删、改、查Sql语句 -->
<mapper namespace="cn.znh.mybatis.mapper.UserMapper">
<!-- 根据用户id查询用户, parameterType:参数类型 resultType:查询结果返回值类型 #{id}:占位符相当于jdbc时的? -->
<select id="queryUserById" parameterType="Integer" resultType="cn.znh.mybatis.domain.User">
select * from user where id= #{id}
</select>
</mapper>
并在主配置文件中引入UserMapper.xml:
<mappers>
<mapper resource="cn/znh/mybatis/mapper/UserMapper.xml"/>
</mappers>
6、书写测试代码:
@Test
public void queryUserById() throws IOException {
// 加载主配置文件
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 获取SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取SqlSession
SqlSession session = sessionFactory.openSession();
// 根据用户id查询用户
User user = session.selectOne("user.queryUserById", 16);
System.out.println(user);
}
1、 基本思路:使用mapper动态代理方式可以简化传统的dao层操作代码,不需要书写dao层的实现类,只需要书写dao层的接口(Mapper接口)即可。
Mybatis会根据接口定义的方法生产动态代理对象,从而调用dao层方法。
2、 Mapper接口(dao层接口)书写时需要遵循四个原则:
a、Mapper.xml文件中的namespace与Mapper接口的类路径相同。
b、Mapper接口方法名和Mapper.xml中定义的每个sql语句的id相同。
c、Mapper接口方法的输入参数类型和Mapper.xml中定义的每个sql的parameterType的类型相同。
d、Mapper接口方法的返回值类型和Mapper.xml中定义的每个sql的resultType的类型相同。
3、书写UserMapper.java和UserMapper.xml
/**
* 用户的Mapper接口(dao层接口)
*
* @author Administrator
*
*/
public interface UserMapper {
/**
* 根据用户名模糊查询用户列表
*
* @param userName
* @return
*/
public List<User> queryUsersByUserName(String username);
}
<mapper namespace="cn.znh.mybatis.mapper.UserMapper">
<select id="queryUsersByUserName" parameterType="String" resultType="User">
select * from user where username like '%${value}%'
</select>
</mapper>
4、测试代码
@Test
public void queryUserByUserName() throws IOException {
// 加载主配置文件
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 获取SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取SqlSession
SqlSession session = sessionFactory.openSession();
// 根据用户名称模糊查询用户
UserMapper uMapper = session.getMapper(UserMapper.class);
List<User> users = uMapper.queryUsersByUserName("明");
System.out.println(users);
}
5、说明:此时对Mapper.xml的文件名和位置不做要求,对Mapper接口的名称和位置也不做要求。(为下面的SqlMapConfig.xml的一些配置做对比)
三、SqlMapConfig.xml的一些配置
1、 自定义别名
a、单个别名定义,SqlMapConfig.xml中的配置:
<typeAliases>
<!-- 自定义单个别名,用user指代cn.znh.mybatis.domain.User-->
<typeAlias type="cn.znh.mybatis.domain.User" alias="user" />
</typeAliases>
在UserMapper.xml中的使用,resultType="user"
<select id="queryUserById" parameterType="Integer" resultType="user">
select * from user where id= #{v}
</select>
b、多个别名定义,SqlMapConfig.xml中的配置:
<typeAliases>
<!-- 批量别名定义,别名是指定的包下的每个类名(每个类的类名可以指代自身的全路径,大小写都可以) -->
<package name="cn.zhn.mybatis.domain" />
</typeAliases>
在UserMapper.xml中的使用, resultType="User"
<select id="queryUsersByUserName" parameterType="String" resultType="User">
select * from user where username like '%${value}%'
</select>
2、 Mapper.xml的另一种引用方式
a、 在SqlMapConfig.xml引入Mapper.xml有很多种方式,上文的1.5是一种方式,还有一种开发中最常用的方式是package引入方式。
就是通过package注册所有的mapper接口,进而找到mapper.xml的一种实现方式。
b、 使用这种方式要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录下。
c、 在SqlMapConfig.xml中的配置:
<mappers>
<package name="cn.zhn.mybatis.mapper" />
</mappers>
四、动态Sql
1、 if标签,多个条件时会用到,Mapper.xml配置:
<select id="queryUsersByUserNameAndSex" parameterType="User" resultType="User">
select * from user where
<if test="username!=null and username!=''">
username=#{username}
</if>
<if test="sex!=null and sex!=''">
and sex=#{sex}
</if>
</select>
测试代码:
@Test
public void queryUserByUserNameAndSex() throws IOException {
// 加载主配置文件
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 获取SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取SqlSession
SqlSession session = sessionFactory.openSession();
// 根据用户名和性别查询用户
UserMapper uMapper = session.getMapper(UserMapper.class);
User user = new User();
user.setUsername("张三");
user.setSex("1");
List<User> users = uMapper.queryUsersByUserNameAndSex(user);
System.out.println(users);
}
2、 where标签
使用if标签有条件值为空,就会出现多个and的情况,这样sql语句就会报错了,比如上例中的username为空,就会导致sex条件前多个and的错误语句。
Where标签可以解决这种问题,可以过滤掉前and。
<select id="queryUsersByUserNameAndSex" parameterType="User" resultType="User">
select * from user
<where>
<if test="username!=null and username!=''">
username=#{username}
</if>
<if test="sex!=null and sex!=''">
and sex=#{sex}
</if>
</where>
</select>
测试代码:
@Test
public void queryUserByUserNameAndSex() throws IOException {
// 加载主配置文件
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 获取SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取SqlSession
SqlSession session = sessionFactory.openSession();
// 根据用户名和性别查询用户
UserMapper uMapper = session.getMapper(UserMapper.class);
User user = new User();
//user.setUsername("张三");
user.setSex("1");
List<User> users = uMapper.queryUsersByUserNameAndSex(user);
System.out.println(users);
}
3、 foreach标签
当需要向sql中传递数组或者list集合时,需要用到foreach标签。比如根据多个用户id查询用户信息。原生sql语句
为:SELECT * FROM user WHERE id IN (16,25,26)。IN里的参数就要用到foreach处理。有3种方式进行传参:
a、 数组
<select id="queryUsersByIds" resultType="User">
<!-- collection:遍历的集合,必须写array不能写其他的 -->
<!-- item:指代单个元素(相当于条目变量),可以随便写,但是要和后面的#{}里面的一致 -->
<!-- open:在前面添加的sql片段 -->
<!-- close:在结尾处添加的sql片段 -->
<!-- separator:指定遍历的元素之间使用的分隔符 ,这里是逗号 -->
select * from user
<where>
id in
<foreach collection="array" item="idItem" separator="," open="(" close=")">
#{idItem}
</foreach>
</where>
</select>
测试代码:
@Test
public void queryUserByIds() throws IOException {
// 加载主配置文件
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 获取SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取SqlSession
SqlSession session = sessionFactory.openSession();
UserMapper uMapper = session.getMapper(UserMapper.class);
Integer[] idsIntegers={16,25,26};
List<User> users = uMapper.queryUsersByIds(idsIntegers);
System.out.println(users);
}
b、 List
<select id="queryUsersByIds" resultType="User">
<!-- collection:遍历的集合,必须写list不能写其他的 -->
<!-- item:指代单个元素(相当于条目变量),可以随便写,但是要和后面的#{}里面的一致 -->
<!-- open:在前面添加的sql片段 -->
<!-- close:在结尾处添加的sql片段 -->
<!-- separator:指定遍历的元素之间使用的分隔符 ,这里是逗号 -->
select * from user
<where>
id in
<foreach collection="list" item="idItem" separator="," open="(" close=")">
#{idItem}
</foreach>
</where>
</select>
测试代码:
@Test
public void queryUserByIds() throws IOException {
// 加载主配置文件
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 获取SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取SqlSession
SqlSession session = sessionFactory.openSession();
UserMapper uMapper = session.getMapper(UserMapper.class);
List<Integer> idsIntegers=new ArrayList<>();
idsIntegers.add(16);
idsIntegers.add(25);
idsIntegers.add(26);
List<User> users = uMapper.queryUsersByIds(idsIntegers);
System.out.println(users);
}
c、 QueryVo(包装类)
public class QueryVo {
private List<Integer> idList;
private Integer[] idArray;
public List<Integer> getIdList() {
return idList;
}
public void setIdList(List<Integer> idList) {
this.idList = idList;
}
public Integer[] getIdArray() {
return idArray;
}
public void setIdArray(Integer[] idArray) {
this.idArray = idArray;
}
}
<select id="queryUsersByIds" parameterType="QueryVo" resultType="User">
<!-- collection:遍历的集合,这里是QueryVo的idList属性-->
<!-- item:指代单个元素(相当于条目变量),可以随便写,但是要和后面的#{}里面的一致 -->
<!-- open:在前面添加的sql片段 -->
<!-- close:在结尾处添加的sql片段 -->
<!-- separator:指定遍历的元素之间使用的分隔符 ,这里是逗号 -->
select * from user
<where>
id in
<foreach collection="idList" item="idItem" separator="," open="(" close=")">
#{idItem}
</foreach>
</where>
</select>
测试代码:
@Test
public void queryUserByIds() throws IOException {
// 加载主配置文件
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 获取SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取SqlSession
SqlSession session = sessionFactory.openSession();
UserMapper uMapper = session.getMapper(UserMapper.class);
QueryVo qVo=new QueryVo();
List<Integer> idsIntegers=new ArrayList<>();
idsIntegers.add(16);
idsIntegers.add(25);
idsIntegers.add(26);
qVo.setIdList(idsIntegers);
List<User> users = uMapper.queryUsersByIds(qVo);
System.out.println(users);
}
五、表关联操作
1、一对一(以订单表为参照,订单和用户的一对一关系,一个订单只对应一个用户)
在Orders中添加private User user;
<resultMap type="Orders" id="order">
<!-- Orders表自身的手动映射,需要查询的Orders字段都需要手动映射,下面只会查id,userId,createtime -->
<id column="id" property="id" />
<result column="user_id" property="userId" />
<result column="createtime" property="createtime" />
<!--以订单为参照的,一对一订单和用户的手动映射,需要查询的用户的字段都需要手动映射一下 ,下面只会查username,sex,address -->
<association property="user" javaType="User">
<result column="username" property="username" />
<result column="sex" property="sex" />
<result column="address" property="address" />
</association>
</resultMap>
<select id="queryOrderUsers" resultMap="order">
select * from orders o
left join user u
on o.user_id=u.id
</select>
测试代码:
@Test
public void fun1() throws IOException {
// 加载主配置文件
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 获取SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取SqlSession
SqlSession session = sessionFactory.openSession();
UserMapper uMapper = session.getMapper(UserMapper.class);
List<Orders> orders = uMapper.queryOrderUsers();
System.out.println(orders);
}
2、一对多(以用户表为参照,用户和订单的对应关系,一个用户有多个订单)
在User中添加private List<Orders> orderList;
<resultMap type="User" id="user">
<id column="id" property="id" />
<result column="username" property="username" />
<!-- 一对多关系 -->
<collection property="orderList" ofType="Orders">
<result column="user_id" property="userId" />
<result column="number" property="number" />
</collection>
</resultMap>
<select id="queryUserOrders" resultMap="user">
select * from user u
leftjoin orders o
on o.user_id=u.id
</select>
测试代码:
@Test
public void fun2() throws IOException {
// 加载主配置文件
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 获取SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取SqlSession
SqlSession session = sessionFactory.openSession();
UserMapper uMapper = session.getMapper(UserMapper.class);
List<User> users = uMapper.queryUserOrders();
System.out.println(users);
}
六、spring和mybatis的整合
1、导包,需要导入的包如下:
a、spring的jar包
b、Mybatis的jar包
c、Spring+mybatis的整合包
d、数据库驱动jar包
e、数据库连接池的jar包
jar图片
2、添加spring和mybatis的约束
跟单独使用spring和mybatis时一样
3、在src下创建applicationContext.xml配置文件、sqlMapConfig.xml配置文件、db.properties配置文件
前两个配置文件头内容跟单独使用spring和mybatis时一样,db.properties里配置的是数据库连接参数:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
jdbc.username=root
jdbc.password=123
4、在applicationContext中配置
<!-- 引入db配置文件 -->
<context:property-placeholder location="classpath:db.properties" />
<!-- 数据库连接池配置 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<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="maxActive" value="10" />
<property name="maxIdle" value="5" />
</bean>
<!-- 注入Mybatis的sqlSessionFactory工厂 -->
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 核心配置文件的位置 -->
<property name="configLocation" value="classpath:sqlMapConfig.xml" />
</bean>
5、原始dao开发,在applicationContext中注入dao类,从spring中获取dao实现类进行数据库操作(这种方式很少用)
<!-- 注入userDao,userDao依赖sqlSessionFactory工厂-->
<bean id="userDao" class="cn.znh.mybatis.dao.UserDaoImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactoryBean" />
</bean>
6、Mapper动态代理开发(常用)
a、在applicationContext.xml中配置
方式一:
<!-- 注入MapperFactoryBean,指定mapperInterface,从spring中获取mapper对象-->
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="sqlSessionFactory" ref="sqlSessionFactoryBean" />
<property name="mapperInterface" value="cn.zhn.mybatis.mapper.UserMapper" />
</bean>
方式二:
<!-- Mapper包扫描方式,不需要指定具体的mapperInterface,会自动扫描指定包下面的所有mapper -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 基本包 -->
<property name="basePackage" value="cn.zhn.mybatis.mapper"/>
</bean>
b、编写UserMapper.java和UserMapper.xml
public interface UserMapper {
public User queryUserById(Integer id);
}
<mapper namespace="cn.zhn.mybatis.mapper.UserMapper">
<!-- 根据用户id查询用户-->
<select id="queryUserById" parameterType="Integer" resultType="User">
select * from user where id= #{id}
</select>
</mapper>
c、编写测试代码
@Test
public void fun1() {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper uMapper = (UserMapper) ac.getBean(UserMapper.class);
User user = uMapper.queryUserById(16);
System.out.print(user);
}