目录
一、输入映射和输出映射
1.1 输入映射
1.1.1 传递简单类型
使用#{}占位符,或者用${}进行sql拼接。
1.1.2 传递pojo对象
mybatis使用ognl表达式解析对象字段的值,#{}或者${}括号中的值为pojo属性名称。
1.1.3 传递pojo包装对象
开发中通过可以使用pojo传递查询条件。
查询条件可能是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如查询用户信息的时候,将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。
包装对象:Pojo类中的一个属性是另外一个pojo。
需求:根据用户名模糊查询用户信息,查询条件放到QueryVo的user属性中。
编写QueryVo
package com.baidu.domain;
public class QueryVo {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
UserMapper.xml中添加如下内容
<select id="getUserByQueryVo" parameterType="QueryVo" resultType="User">
select* from users where name like '%${user.name}%'
</select>
关键代码:
SqlSession session = sessionFactory.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User();
user.setName("1");
QueryVo vo = new QueryVo();
vo.setUser(user);
System.out.println(mapper.getUserByQueryVo(vo));
session.close();
执行结果
1.1.4 传递其他映射类型
<select id="getUserCount" parameterMap="getUserCountMap" statementType="CALLABLE">
CALL mybatis.ges_user_count(?, ?)
</select>
参数类型为map,调用存储过程
<parameterMap type="java.util.Map" id="getUserCountMap">
<parameter property="sexid" mode="IN" jdbcType="INTEGER"/>
<parameter property="usercount" mode="OUT" jdbcType="INTEGER"/>
</parameterMap>
关键代码
String sql = "com.baidu.mapper.UserMapper.getUserCount";
Map<String,Integer> paramterMap = new HashMap<String, Integer>();
paramterMap.put("sexid", 1);
paramterMap.put("usercount", -1);
sqlSession.selectOne(sql, paramterMap);
Integer result = paramterMap.get("usercount");
sqlSession.close();
System.out.println(result);
1.2 resultType(输出类型)
可以输出简单类型,pojo对象,pojo列表,参考上一篇内容。
1.2.1 resultMap(输出类型映射)
resultMap可以将查询结果映射为指定类型,但是需要pojo的属性名和sql查询的列明保持一致方可映射成功,如果不一致,可以通过resultMap将字段名和属性名作为一个对应关系,还可以通过配置将结果映射为复杂类型的,比如一对一和一对多查询。
创建class、student表和teacher表
添加相关类
package com.baidu.domain;
public class Student {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString(){
return "Student [id=" + id + ", name=" + name + "]";
}
}
package com.baidu.domain;
import java.util.List;
public class Classes {
private int id;
private String name;
private Teacher teacher;
private List<Student> students;
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
@Override
public String toString(){
return "Classes [id=" + id + ", name=" + name + ", teacher=" + teacher+ ",students"+students+"]";
}
}
package com.baidu.domain;
public class Teacher {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString(){
return "Teacher [id=" + id + ", name=" + name + "]";
}
}
添加ClassMapper.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,习惯上设置成包名+sql映射文件名,这样就能够保持唯一了
-->
<mapper namespace="com.baidu.mapper.ClassMapper">
<select id="getClass" parameterType="int" resultMap="ClassResultMap">
select * from class c,teacher t where c.teacher_id = t.t_id and c.c_id = #{id}
</select>
<resultMap type="com.baidu.domain.Classes" id="ClassResultMap">
<id property="id" column="c_id" />
<result property="name" column="c_name"/>
<association property="teacher" javaType="com.baidu.domain.Teacher" >
<id property="id" column="t_id" />
<result property="name" column="t_name"/>
</association>
</resultMap>
<select id="getClassStudents" parameterType="int" resultMap="ClassStudentsResultMap">
select * from class c, teacher t,student s where c.teacher_id=t.t_id and c.C_id=s.class_id and c.c_id=#{id}
</select>
<resultMap type="com.baidu.domain.Classes" id="ClassStudentsResultMap">
<id property="id" column="c_id"/>
<result property="name" column="c_name"/>
<association property="teacher" column="teacher_id" javaType="com.baidu.domain.Teacher">
<id property="id" column="t_id"/>
<result property="name" column="t_name"/>
</association>
<collection property="students" ofType="com.baidu.domain.Student">
<id property="id" column="s_id"/>
<result property="name" column="s_name"/>
</collection>
</resultMap>
</mapper>
这个是一对一(一个班级对应一个老师)和一对多(一个班级对应多个学生)的查询
其中getClass返回的结果集比较复杂,所有resultMap要重新定义一个新的结果集映射,这里设置为ClassResultMap
添加一个resultMap,id为ClassResultMap,与上边的结果对应,type类型为我们的javabean的Classes
<resultMap type="com.baidu.domain.Classes" id="ClassResultMap">
实体的id属性property对应sql查出列c_id,用id标签映射主键
<id property="id" column="c_id" />
用result标签映射其他属性,对象的属性名name映射查出来的列c_name
<result property="name" column="c_name"/>
关联属性teacher映射
<association property="teacher" javaType="com.baidu.domain.Teacher" >
<id property="id" column="t_id" />
<result property="name" column="t_name"/>
</association>
</resultMap>
getClassStudent来映射一对多的集合
<select id="getClassStudents" parameterType="int" resultMap="ClassStudentsResultMap">
select * from class c, teacher t,student s where c.teacher_id=t.t_id and c.C_id=s.class_id and c.c_id=#{id}
</select>
<resultMap type="com.baidu.domain.Classes" id="ClassStudentsResultMap">
<id property="id" column="c_id"/>
<result property="name" column="c_name"/>
<association property="teacher" column="teacher_id" javaType="com.baidu.domain.Teacher">
<id property="id" column="t_id"/>
<result property="name" column="t_name"/>
</association>
学生集合属性映射
<collection property="students" ofType="com.baidu.domain.Student">
<id property="id" column="s_id"/>
<result property="name" column="s_name"/>
</collection>
</resultMap>
二、动态sql
通过mybatis提供的各种标签实现动态拼接sql
需求 根据年龄或者姓名查询用户,如果有年龄就根据年龄,如果有名字就根据名字
2.1 if标签
UserMapper.xml中添加如下select标签
<select id="getUserByNameOrAge" parameterType="User" resultType="User">
SELECT id, name,age FROM `user`
WHERE 1=1
<if test="age != null and age != ''">
AND age = #{age}
</if>
<if test="name != null and name != ''">
AND name LIKE
'%${name}%'
</if>
</select>
关键代码
SqlSession session = sessionFactory.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User();
user.setAge(23);
//user.setName("张");
System.out.println(mapper.getUserByNameOrAge(user));
当设置name或者不设置name的时候结果是不一样的,就满足了我们的需求。
2.2 where标签
上边的sql有where 1=1 这样的语句 感觉很别扭麻烦,我们可以使用where标签进行改造
<select id="getUserByNameOrAge" parameterType="User" resultType="User">
SELECT id, name,age FROM `user`
<!-- where标签可以自动添加where,同时处理sql语句中第一个and关键字 -->
<where>
<if test="age != null and age != ''">
AND age = #{age}
</if>
<if test="name != null and name != ''">
AND name LIKE
'%${name}%'
</if>
</where>
</select>
2.3 foreach标签
向sql传递数组或者List,mybatis使用foreach解析,如根据多个id查询用户信息的时候 SELECT * FROM user WHERE id IN (1,10,24),我们改造QueryVo
package com.baidu.domain;
import java.util.List;
public class QueryVo {
private User user;
private List<Integer> ids;
public List<Integer> getIds() {
return ids;
}
public void setIds(List<Integer> ids) {
this.ids = ids;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
UserMapper.xml添加如下标签
<select id="getUserByQueryVo" 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>
关键代码
SqlSession session = sessionFactory.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
QueryVo vo = new QueryVo();
List<Integer> ids = new ArrayList<Integer>();
ids.add(1);
ids.add(3);
ids.add(4);
vo.setIds(ids);
System.out.println(mapper.getUserByQueryVo(vo));
2.4 Sql片段
sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的。可以把上边例子中的id,name,age提取出来,作为sql片段
<select id="getUserByNameOrAge" parameterType="User" resultType="User">
SELECT <include refid="userFields" /> FROM `user`
<!-- where标签可以自动添加where,同时处理sql语句中第一个and关键字 -->
<where>
<if test="age != null and age != ''">
AND age = #{age}
</if>
<if test="name != null and name != ''">
AND name LIKE
'%${name}%'
</if>
</where>
</select>
<!-- 声明sql片段 -->
<sql id="userFields">
id, name, age
</sql>
三、整合spring
3.1 整合思路
1.SqlSessionFactory对象应该放到spring容器中作为单例存在。
2.传统dao的开发方式中,应该从spring容器中获得sqlsession对象。
3.mapper代理形式中,应该从spring容器中直接获取mapper代理对象。
4.数据库的连接一级数据库连接池事务管理都交给spring容易来完成。
3.2 整合所需要的jar包
3.3 创建工程
3.3.1 创建一个web工程
添加一个source folder 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>
<!-- 2. 指定扫描包,会把包内所有的类都设置别名,别名的名称就是类名,大小写不敏感 -->
<package name="cn.itcast.pojo" />
</typeAliases>
</configuration>
添加applicatinContext.xml 是spring的配置
<?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="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 配置mybatis核心配置文件 -->
<property name="configLocation" value="classpath:SqlMapConfig.xml" />
<!-- 配置数据源 -->
<property name="dataSource" ref="dataSource" />
</bean>
<!-- Mapper代理的方式开发方式二,扫描包方式配置代理 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 配置Mapper接口 -->
<property name="basePackage" value="cn.itcast.mapper" />
</bean>
</beans>
添加db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root
添加log4j.properties
# 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
配置文件的最终效果
添加mapper.xml
package cn.itcast.mapper;
import cn.itcast.pojo.User;
public interface UserMapper {
User getUser(int id);
void saveUser(User user);
void updateUserById(int id);
void deleteUserById(int id);
}
<?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,习惯上设置成包名+sql映射文件名,这样就能够保持唯一了
-->
<mapper namespace="cn.itcast.mapper.UserMapper">
<select id="getUser" parameterType="int" resultType="User">
select* from user where id = #{id}
</select>
<!-- 保存用户 -->
<insert id="saveUser" parameterType="User">
INSERT INTO `user`
(name,age) VALUES
(#{name},#{age})
</insert>
<!-- 更新用户 -->
<update id="updateUserById" parameterType="User">
UPDATE `user` SET
name = #{name},age = #{age} WHERE id = #{id}
</update>
<!-- 删除用户 -->
<delete id="deleteUserById" parameterType="int">
delete from user where
id=#{id}
</delete>
</mapper>
关键测试代码
package cn.itcast.test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.itcast.mapper.UserMapper;
import cn.itcast.pojo.User;
public class TestMain {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
UserMapper userMapper = context.getBean(UserMapper.class);
User user = userMapper.getUser(1);
System.out.println(user);
}
}
四、总结
整合之后我们的开发就方便的多,开发和维护起来都很方便。