1、输入映射和输出映射
a) 输入参数映射
b) 返回值映射
2、动态sql
a) If标签
b) Where标签
c) Sql片段
d) Foreach标签
3、关联查询
a) 一对一关联
b) 一对多关联
4、Mybatis整合spring
a) 如何整合spring
b) 使用原始的方式开发dao
c) 使用Mapper接口动态代理
5、Mybatis逆向工程(了解)
Mapper.xml映射文件中定义了操作数据库的sql,每个sql是一个statement,映射文件是mybatis的核心。
1. 复制昨天的工程,按照下图进行
2.如下图粘贴,并更名
3.只保留Mapper接口开发相关的文件,其他的删除
最终效果如下图:
4.如下图修改SqlMapConfig.xml配置文件。Mapper映射器只保留包扫描的方式
参考第一天内容。
使用#{}占位符,或者${}进行sql拼接。
参考第一天的内容。
Mybatis使用ognl表达式解析对象字段的值,#{}或者${}括号中的值为pojo属性名称。
开发中通过可以使用pojo传递查询条件。
查询条件可能是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如查询用户信息的时候,将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。
包装对象:Pojo类中的一个属性是另外一个pojo。
需求:根据用户名模糊查询用户信息,查询条件放到QueryVo的user属性中。
SELECT * FROM user WHERE username LIKE ‘%张%‘
在UserMapper.xml中配置sql,如下图。
在UserMapper.java接口中添加方法,如下图:
在UserMapeprTest增加测试方法,如下:
需求:查询用户表数据条数
sql:SELECT count(*) FROM user
在UserMapper添加方法,如下图:
在UserMapeprTest增加测试方法,如下:
参考第一天内容
参考第一天内容。
resultType可以指定将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。
如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中。
resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。
需求:查询订单表order的所有数据
Order.java代码
import java.util.Date; public class Order { private int id; private int userId; private String number; private Date createtime; private String note; public int getId() { return id; } public void setId(int id) { this.id = id; } public int getUserId() { return userId; } public void setUserId(int userId) { this.userId = userId; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } public Date getCreatetime() { return createtime; } public void setCreatetime(Date createtime) { this.createtime = createtime; } public String getNote() { return note; } public void setNote(String note) { this.note = note; } @Override public String toString() { return "Order [id=" + id + ", userId=" + userId + ", number=" + number + ", createtime=" + createtime + ", note=" + note + "]"; } }
创建OrderMapper.xml配置文件,如下:
注意:由于sql查询列(user_id)和Order类属性(userId)不一致,需要定义resultMap,把orderResultMap将sql查询列(user_id)和Order类属性(userId)对应起来,不能在直接使用resultType,不然在返回值中,userId的值会获取不到,为NULL。
OrderMapper.java代码:
import java.util.List; import pojo.Order; public interface OrderMapper { public List<Order> queryOrder(); }
注意:接口方法名和mapper.xml文件里面的id要一一对应
编写测试方法OrderMapperTest如下:
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 org.junit.Before; import org.junit.Test; import dao.OrderMapper; import pojo.Order; public class OrderMapperTest { private SqlSessionFactory sqlSessionFactory; @Before public void init() throws IOException{ // 1. 创建SqlSessionFactoryBuilder对象 SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); // 2. 加载SqlMapConfig.xml配置文件 InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml"); // 3. 创建SqlSessionFactory对象 this.sqlSessionFactory=sqlSessionFactoryBuilder.build(inputStream); } @Test public void queryOrder() throws Exception { SqlSession session = sqlSessionFactory.openSession(); OrderMapper mapper = session.getMapper(OrderMapper.class); List<Order> queryOrder = mapper.queryOrder(); for (Order order : queryOrder) { System.out.println(order); } session.close(); } }
通过mybatis提供的各种标签方法实现动态拼接sql。
需求:根据性别和名字查询用户
查询sql:
SELECT id, username, birthday, sex, address FROM `user` WHERE sex = 1 AND username LIKE ‘%张%‘
UserMapper.xml配置sql,如下:
新增以下方法
在UserMapperTest添加测试方法,如下:
如果注释掉 user.setSex("1"),测试结果如下图:
测试结果二很显然不合理。
按照之前所学的,要解决这个问题,需要编写多个sql,查询条件越多,需要编写的sql就更多了,显然这样是不靠谱的。
解决方案,使用动态sql的if标签
改造UserMapper.xml,如下:
注意字符串类型的数据需要要做不等于空字符串校验
上面的sql还有where 1=1 这样的语句,很麻烦
可以使用where标签进行改造
改造UserMapper.xml,如下
Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的。
把上面例子中的id, username, birthday, sex, address提取出来,作为sql片段,如下:
如果要使用别的Mapper.xml配置的sql片段,可以在refid前面加上对应的Mapper.xml的namespace
向sql传递数组或List,mybatis使用foreach解析,如下:
根据多个id查询用户信息
查询sql:
SELECT * FROM user WHERE id IN (1,10,24)
如下图在pojo中定义list属性ids存储多个用户id,并添加getter/setter方法
UserMapper.xml添加sql,如下:
<!-- 根据ids查询用户 --> <select id="queryUserByIds" parameterType="queryVo" resultType="user"> SELECT * FROM user <where> <!-- foreach标签,进行遍历 --> <!-- collection:遍历的集合,这里是QueryVo的ids属性 --> <!-- item:遍历的项目,可以随便写,,但是和后面的#{}里面要一致 --> <!-- open:在前面添加的sql片段 --> <!-- close:在结尾处添加的sql片段 --> <!-- separator:指定遍历的元素之间使用的分隔符 --> <foreach collection="ids" item="item" open="id IN (" close=")" separator=","> #{item} </foreach> </where> </select>
测试方法如下图:
需求:查询所有订单信息,关联查询下单用户信息。
注意:因为一个订单信息只会是一个人下的订单,所以从查询订单信息出发关联查询用户信息为一对一查询。如果从用户信息出发查询用户下的订单信息则为一对多查询,因为一个用户可以下多个订单。
sql语句:
SELECT o.id, o.user_id userId, o.number, o.createtime, o.note, u.username, u.address FROM orders o LEFT JOIN user u ON o.user_id = u.id
使用resultType,改造订单pojo类,此pojo类中包括了订单信息和用户信息
这样返回对象的时候,mybatis自动把用户信息也注入进来了
OrderUser类继承Order类后OrderUser类包括了Order类的所有字段,只需要定义用户的信息字段即可,如下图:
在UserMapper.xml添加sql,如下
在UserMapper接口添加方法,如下图
在UserMapperTest添加测试方法,如下:
使用resultMap,定义专门的resultMap用于映射一对一查询结果。
在Order类中加入User属性,user属性中用于存储关联查询的用户信息,因为订单关联查询用户是一对一关系,所以这里使用单个User对象存储关联查询的用户信息。
在Order.java中添加以下代码:
这里resultMap指定orderUserResultMap,如下:
编写OrderMapper如下图:
在OrderMapperTest增加测试方法,如下:
案例:查询所有用户信息及用户关联的订单信息。
用户信息和订单信息为一对多关系。
sql语句:
SELECT u.id, u.username, u.birthday, u.sex, u.address, o.id oid, o.number, o.createtime, o.note FROM user u LEFT JOIN orders o ON u.id = o.user_id
在User类中加入List<Order> orders属性,如下图:
在UserMapper.xml添加sql,如下:
<resultMap type="user" id="userOrderResultMap"> <id property="id" column="id" /> <result property="username" column="username" /> <result property="birthday" column="birthday" /> <result property="sex" column="sex" /> <result property="address" column="address" /> <!-- 配置一对多的关系 --> <collection property="orders" javaType="list" ofType="order"> <!-- 配置主键,是关联Order的唯一标识 --> <id property="id" column="oid" /> <result property="number" column="number" /> <result property="createtime" column="createtime" /> <result property="note" column="note" /> </collection> </resultMap> <!-- 一对多关联,查询订单同时查询该用户下的订单 --> <select id="queryUserOrder" resultMap="userOrderResultMap"> SELECT u.id, u.username, u.birthday, u.sex, u.address, o.id oid, o.number, o.createtime, o.note FROM `user` u LEFT JOIN `order` o ON u.id = o.user_id </select>
编写UserMapper接口,添加以下方法:
在UserMapperTest增加测试方法,如下
1、SqlSessionFactory对象应该放到spring容器中作为单例存在。
2、传统dao的开发方式中,应该从spring容器中获得sqlsession对象。
3、Mapper代理形式中,应该从spring容器中直接获得mapper的代理对象。
4、数据库的连接以及数据库连接池事务管理都交给spring容器来完成。
1、spring的jar包
2、Mybatis的jar包
3、Spring+mybatis的整合包。
4、Mysql的数据库驱动jar包。
5、数据库连接池的jar包。
jar包位置如下所示:
如下图创建一个java工程:
前面提到的jar包需要导入,如下图:
1.mybatisSpring的配置文件
2.配置文件sqlmapConfig.xml
a) 数据库连接及连接池
b) 事务管理(暂时可以不配置)
c) sqlsessionFactory对象,配置到spring容器中
d) mapeer代理对象或者是dao实现类配置到spring容器中。
创建资源文件夹config拷贝加入配置文件,如下图
配置文件是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> <!-- 设置别名 --> <typeAliases> <!-- 指定扫描包,会把包内所有的类都设置别名,别名的名称就是类名,大小写不敏感 --> <package name="pojo" /> </typeAliases> </configuration>
applicationContext.xml,配置内容如下
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!-- 加载配置文件 --> <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> <!-- 配置SqlSessionFactory --> <bean id="" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 配置mybatis核心配置文件 --> <property name="configLocation" value="classpath:SqlMapConfig.xml"></property> <!-- 配置数据源 --> <property name="dataSource" ref="dataSource" /> </bean> </beans>
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
jdbc.username=root
jdbc.password=123
# Global logging configuration
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
加入的配置文件最终效果如下:
两种dao的实现方式:
1、原始dao的开发方式
2、使用Mapper代理形式开发方式
a) 直接配置Mapper代理
b) 使用扫描包配置Mapper代理
需求:
import java.util.Date; public class User { private int id; private String username; private String sex; private Date birthday; private String address; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
原始的DAO开发接口+实现类来完成。
需要dao实现类需要继承SqlsessionDaoSupport类
编写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"> <mapper namespace="test"> <!-- 根据用户id查询 --> <select id="queryUserById" parameterType="int" resultType="user"> select *from user where id= #{v} </select> <!-- 根据用户名模糊查询用户 --> <select id="queryUserByUsername" parameterType="String" resultType="user"> select *from user where username like "%"#{username}"%" </select> <!-- 添加用户 --> <insert id="addUser" parameterType="user"> insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address}); </insert> </mapper>
在SqlMapConfig如下图进行配置:
import java.util.List; import pojo.User; public interface UserDao { public User queryUserById(int id); public List<User> queryUserByUsername(String username); public void addUser(User user); }
编写DAO实现类,实现类必须集成SqlSessionDaoSupport
SqlSessionDaoSupport提供getSqlSession()方法来获取SqlSession
import java.util.List; import org.apache.ibatis.session.SqlSession; import org.mybatis.spring.support.SqlSessionDaoSupport; import pojo.User; public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao { @Override public User queryUserById(int id) { SqlSession session = super.getSqlSession(); User user=session.selectOne("queryUserById", id); return user; } @Override public List<User> queryUserByUsername(String username) { SqlSession session = super.getSqlSession(); List<User> list = session.selectList("queryUserByUsername", username); return list; } @Override public void addUser(User user) { SqlSession session = super.getSqlSession(); session.insert("addUser", user); } }
把dao实现类配置到spring容器中,如下图
applicationContext.xml添加以下代码
import java.util.Date; import java.util.List; import org.junit.Before; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import dao.UserDao; import pojo.User; public class UserDaoTest { private ApplicationContext context; @Before public void setUp(){ this.context=new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); } @Test public void queryUserByIdTest(){ UserDao dao=this.context.getBean(UserDao.class); User user = dao.queryUserById(10); System.out.println(user); } @Test public void queryUserByUsernameTest(){ UserDao dao=this.context.getBean(UserDao.class); List<User> user = dao.queryUserByUsername("张"); for (User user2 : user) { System.out.println(user2); } } @Test public void addUserTest() { // 获取userDao UserDao userDao = this.context.getBean(UserDao.class); User user = new User(); user.setUsername("曹操"); user.setSex("1"); user.setBirthday(new Date()); user.setAddress("三国"); userDao.addUser(user); System.out.println(user); } }
编写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"> <mapper namespace="mapper.UserMapper"> <!-- 根据用户id查询 --> <select id="queryUserById" parameterType="int" resultType="user"> select *from user where id= #{v} </select> <!-- 根据用户名模糊查询用户 --> <select id="queryUserByUsername" parameterType="String" resultType="user"> select *from user where username like "%"#{username}"%" </select> <!-- 添加用户 --> <insert id="addUser" parameterType="user"> insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address}); </insert> </mapper>
import java.util.List; import pojo.User; public interface UserMapper { public User queryUserById(int id); public List<User> queryUserByUsername(String username); public void addUser(User user); }
在applicationContext.xml添加配置
MapperFactoryBean也是属于mybatis-spring整合包
<!-- Mapper代理的方式开发方式一,配置Mapper代理对象 --> <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> <!-- 配置Mapper接口 --> <property name="mapperInterface" value="mapper.UserMapper"></property> <property name="sqlSessionFactory" ref="sqlSessionFactory"></property> </bean>
import java.util.Date; import java.util.List; import org.junit.Before; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import dao.UserDao; import mapper.UserMapper; import pojo.User; public class UserMapperTest { private ApplicationContext context; @Before public void setUp(){ this.context=new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); } @Test public void queryUserByIdTest(){ UserMapper dao=this.context.getBean(UserMapper.class); User user = dao.queryUserById(10); System.out.println(user); } @Test public void queryUserByUsernameTest(){ UserMapper dao=this.context.getBean(UserMapper.class); List<User> user = dao.queryUserByUsername("张"); for (User user2 : user) { System.out.println(user2); } } @Test public void addUserTest() { // 获取userDao UserMapper dao=this.context.getBean(UserMapper.class); User user = new User(); user.setUsername("曹操"); user.setSex("1"); user.setBirthday(new Date()); user.setAddress("三国"); dao.addUser(user); System.out.println(user); } }
<!-- Mapper代理的方式开发方式二,扫描包方式配置代理 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="mapper"></property> </bean>
使用官方网站的Mapper自动生成工具mybatis-generator-core-1.3.2来生成po类和Mapper映射文件
原文:https://www.cnblogs.com/huozhonghun/p/9498473.html