MyBatis学习总结一

Mybatis学习总结一

1、Mybatis介绍

Mybatis是一个类似于Hibernate的ORM持久化框架,支持普通SQL查询,存储过程以及高级映射。Mybatis通过使用简单的XML或注解用于配置和原始映射,将接口和POJO对象映射成数据库中的记录。

Hibernate是一个完全的ORM框架,而Mybatis是一个不完全的orm框架。Mybatis让程序员只关注sql本身,而不需要去关注如连接的创建、statement的创建等操作。Mybatis会将输入参数、输出结果进行映射。

由于Mybatis是直接基于JDBC做了简单的映射包装,所有从性能角度来看:JDBC > Mybatis > Hibernate。


2、Mybatis架构图

下图来自于这里!
在这里插入图片描述

2.1、架构图的意义

2.1.1、JDBC编写

package com.csa.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import org.junit.jupiter.api.Test;

public class App {
	
	@Test
	public void app() throws Exception {
		// 加载驱动
		Class.forName("com.mysql.jdbc.Driver");
		String url = "jdbc:mysql://127.0.0.1:3306/mybatis";
		String user = "root";
		String password = "3306";
		Connection connection = null;
		PreparedStatement statement = null;
		ResultSet resultSet = null;
		try {
			// 创建数据库连接
			connection = DriverManager.getConnection(url, user, password);
			// 创建Statement对象
			String sql = "SELECT * FROM user WHERE username = ?";
			statement = connection.prepareStatement(sql);
			// 设置参数,下标从1开始
			statement.setString(1, "rose");
			// 执行sql,变量结果集
			resultSet = statement.executeQuery();
			while (resultSet.next()) {
				System.out.println("id: " + resultSet.getInt("id"));
				System.out.println("name: " + resultSet.getString("username"));
				System.out.println("age: " + resultSet.getString("age"));
			}
		} finally {
			// 释放资源
			if (null != resultSet) {
				resultSet.close();
			}
			if (null != statement) {
				statement.close();
			}
			if (null != connection) {
				connection.close();
			}
		}
	}
}

2.1.2、反思问题

JDBC这种固定的东西,完全可以用框架加以实现。因为编写的内容都是一样的!

差不多有以下几个问题:

  1. 在创建连接时,存在硬编码
  2. 在执行statement时存在硬编码
  3. 频繁的开启和关闭数据库连接,会造成数据库性能下降

解决方案:配置xml文件来解决这些问题,使得管理起来方便、高效!

2.2、Mybatis架构图

下图来自于这里!
在这里插入图片描述


3、入门案例

3.1、下载地址以及导入jar包

Mybatis下载地址
在这里插入图片描述
别忘记连接数据库的jar!
在这里插入图片描述

3.2、工程目录

在这里插入图片描述

3.3、创建PO类

package com.csa.po;

public class User {
	private Integer id;
	private String username;
	private Integer age;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "User [id=" + id + ", username=" + username + ", age=" + age + "]";
	}
}

3.4、创建全局配置文件

编写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>
	
	<!-- 引入外部文件 -->
	<properties resource="jdbc.properties"></properties>
	
	<!-- 环境 -->
	<environments default="development">
		<environment id="development">
			<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>
	
	<!-- 加载UserMapper.xml文件 
	<mappers>
		<mapper resource="User.xml"/>
	</mappers>
	-->
</configuration>

3.5、创建映射文件

编写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="app">
	<select id="findUserById" parameterType="int" resultType="com.csa.po.User">
		select * from User where id = #{id}
	</select>
</mapper>

3.6、在全局配置文件中加载映射文件

重新编写SqlMapConfig.xml(在最后添加一个mappers):

<configuration>
	...
	...
	...
	<environments ...>
		...
	</environments>
	<!-- 加载UserMapper.xml文件 -->
	<mappers>
		<mapper resource="User.xml"/>
	</mappers>
</configuration>

3.7、测试

package com.csa.app;

import java.io.InputStream;

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 com.csa.po.User;

public class App {
	public static void main(String[] args) throws Exception {
		// 读取全局配置文件
		String resource = "SqlMapConfig.xml";
		InputStream input = Resources.getResourceAsStream(resource);
		// 创建SqlSessionFactory
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
		// 创建SqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();
		// 调用SqlSession的增删改查的方法
		User user = sqlSession.selectOne("app.findUserById",1);
		// 打印user
		System.out.println(user);
		// 关闭资源
		sqlSession.close();
	}
}

3.8、实验结果

在这里插入图片描述


4、Mybatis开发的两种方式

4.0、映射文件User.xml详解

4.0.1、mapper元素

<mapper namespace="app">...</mapper>其中namespace是命名空间。

4.0.2、CRUD元素

分别是select、insert、update、delete元素。

例如:

<select id="findUserById" parameterType="int" resultType="com.csa.po.User">
	select *from User where id = #{id}
</select>

4.0.3、CRUD元素常用属性

CRUD元素的几个常用属性:

  1. id:唯一,用于被程序调用
  2. parameterType:参数类型,POJO类型或者基本数据类型
  3. parameterMap:参数类型,一个Map集合
  4. resultType:结果类型,POJO类型或者基本数据类型
  5. resultMap:结果类型,一个Map集合

4.0.4、#{id}与${id}的区别

#{id}是占位符,安全

${id}是用于字符串连接的,不安全,会被sql注入。

4.1、dao类实现CRUD

4.1.0、工程目录

在这里插入图片描述

4.1.1、UserDao

package com.csa.dao;

import java.util.List;
import com.csa.po.User;

public interface UserDao {
	/**
	 * 添加用户 
	 * @return 是否添加成功
	 */
	public boolean addUser(User user);
	
	/**
	 * 删除指定id的用户
	 * @param id 
	 */
	public boolean deleteUserById(Integer id);
	
	/**
	 * 更新用户信息
	 * @param user
	 */
	public boolean updateUser(User user);
	
	/**
	 * 通过id查找用户
	 * @param id
	 * @return
	 */
	public User findUserById(Integer id);
	
	/**
	 * 查找所有用户
	 * @return
	 */
	public List<User> selectUserList();
}

4.1.2、UserDaoImp

package com.csa.dao.imp;

import java.util.List;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import com.csa.dao.UserDao;
import com.csa.po.User;

public class UserDaoImp implements UserDao {
	// DI依赖注入
	private SqlSessionFactory sqlSessionFactory;

	public UserDaoImp(SqlSessionFactory sqlSessionFactory) {
		this.sqlSessionFactory = sqlSessionFactory;
	}

	@Override
	public boolean addUser(User user) {
		// 创建SqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();
		// 调用SqlSession的增删改查的方法
		int insert = sqlSession.insert("app.addUser", user);
		// 提交事务
		sqlSession.commit();
		// 关闭资源
		sqlSession.close();
		return insert != 0;
	}

	@Override
	public boolean deleteUserById(Integer id) {
		// 创建SqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();
		// 调用SqlSession的增删改查的方法
		int delete = sqlSession.delete("app.deleteUserById", id);
		// 提交事务
		sqlSession.commit();
		// 关闭资源
		sqlSession.close();
		return delete != 0;
	}

	@Override
	public boolean updateUser(User user) {
		// 创建SqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();
		// 调用SqlSession的增删改查的方法
		int update = sqlSession.update("app.updateUser", user);
		// 提交事务
		sqlSession.commit();
		// 关闭资源
		sqlSession.close();
		return update != 0;
	}

	@Override
	public User findUserById(Integer id) {
		// 创建SqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();
		// 调用SqlSession的增删改查的方法
		User user = sqlSession.selectOne("app.findUserById", id);
		// 关闭资源
		sqlSession.close();
		return user;
	}

	@Override
	public List<User> selectUserList() {
		// 创建SqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();
		// 调用SqlSession的增删改查的方法
		List<User> userList = sqlSession.selectList("app.selectUserList");
		// 关闭资源
		sqlSession.close();
		return userList;
	}
}

4.1.3、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="app">
	<!-- 增加 -->
	<insert id="addUser" parameterType="com.csa.po.User">
		<!-- 
			对于这个例子
				keyProperty:查找的结果放在id中
				order:在执行insert语句''之后(AFTER)"再执行select last_insert_id()
		 -->
		<selectKey keyProperty="id" resultType="int" order="AFTER">
			select last_insert_id()
		</selectKey>
		insert into User(username,age) values(#{username},#{age})
	</insert>
	<!-- 删除 -->
	<delete id="deleteUserById" parameterType="int">
		delete from User where id=#{id}
	</delete>
	<!-- 改 -->
	<update id="updateUser" parameterType="com.csa.po.User">
		update User set username=#{username},age=#{age} where id like #{id}
	</update>
	<!-- 查询一个对象 -->
	<select id="findUserById" parameterType="int" resultType="com.csa.po.User">
		select * from User where id = #{id}
	</select>
	<!-- 查询多个对象 -->
	<select id="selectUserList" resultType="com.csa.po.User">
		select * from User
	</select>
</mapper>

4.1.3、测试Dao的CRUD

package com.csa.app;

import java.io.InputStream;
import java.util.List;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import com.csa.dao.UserDao;
import com.csa.dao.imp.UserDaoImp;
import com.csa.po.User;

public class App {
	public static void main(String[] args) throws Exception {
		// 读取全局配置文件
		String resource = "SqlMapConfig.xml";
		InputStream input = Resources.getResourceAsStream(resource);
		// 创建SqlSessionFactory
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
		// 创建dao类
		UserDao userDao = new UserDaoImp(sqlSessionFactory);
		// 调用增删改查方法
		// 1.增
		User user = new User();
		user.setUsername("hack");
		user.setAge(19);
		boolean insert = userDao.addUser(user);
		if(insert) {
			System.out.println("增加"+user+"成功");
		}else {
			System.out.println("增加失败:"+user);
		}
		// 2.改
		user.setUsername("mybatis");
		user.setAge(0);
		boolean update = userDao.updateUser(user);
		if(update) {
			System.out.println("更新"+user+"成功");
		}else {
			System.out.println("更新失败:"+user);
		}
		// 3.删
		boolean delete = userDao.deleteUserById(user.getId());
		if(delete) {
			System.out.println("删除"+user+"成功");
		}else {
			System.out.println("删除失败:"+user);
		}
		// 4.查
		// 4.1查询单个
		user = userDao.findUserById(user.getId());
		if(user!=null) {
			System.out.println("查询"+user+"成功");
		}else {
			System.out.println("查询失败:"+user);
		}
		// 4.2查询所有
		List list = userDao.selectUserList();
		System.out.println(list);
	}
}

4.1.4、测试结果

如果发现WARN这种结果,是因为没有log4j.properties文件。
在这里插入图片描述

4.1.5、log4j.properties导入及其测试结果

4.1.5.1、创建log4j.properties

在这里插入图片描述

4.1.5.1、编写log4j.properties
log4j.rootLogger=DEBUG, Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
log4j.logger.org.apache=INFO
4.1.5.1、测试

在这里插入图片描述

4.1.4、编写Dao类的问题

我们发现一个问题:编写了很多重复性的代码,而且都是固定(模板)形式!

解决方案:使用动态代理(Mapper)来解决!

4.2、使用动态代理mapper实现CRUD

4.2.0、Mapper代理的开发规范

  1. mapper接口的全限定名要和mapper映射文件的namespace值一致
  2. mapper接口的方法名称要和mapper映射文件的statement的id一致
  3. mapper接口的方法参数类型要和mapper映射文件的statement的parameterType的值一致,而且它的参数是一个
  4. mapper接口的方法返回值类型要和mapper映射文件的statement的resultType的值一致

4.2.1、开发目录

与上一个相比,只是少了实现类
在这里插入图片描述

4.2.2、创建UserDao

与上面一样。

4.2.3、配置mapper映射文件

不同的地方就只有一处:注意看namespace属性的不同

<mapper namespace="com.csa.dao.UserDao">内容与上面的一样</mapper>

4.2.4、测试

不同之处也只在于这两行:

// 创建sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 创建dao类
UserDao userDao = sqlSession.getMapper(UserDao.class);

下面是一个完整的:

package com.csa.app;

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 com.csa.dao.UserDao;
import com.csa.po.User;

public class App {
	public static void main(String[] args) throws Exception {
		// 读取全局配置文件
		String resource = "SqlMapConfig.xml";
		InputStream input = Resources.getResourceAsStream(resource);
		// 创建SqlSessionFactory
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
		// 创建sqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();
		// 创建dao类
		UserDao userDao = sqlSession.getMapper(UserDao.class);
		// 调用增删改查方法
		// 1.增
		User user = new User();
		user.setUsername("hack");
		user.setAge(19);
		boolean insert = userDao.addUser(user);
		if(insert) {
			System.out.println("增加"+user+"成功");
		}else {
			System.out.println("增加失败:"+user);
		}
		// 2.改...
		// 3.删...
		// 4.查
		// 4.1查询单个...
		// 4.2查询所有...
	}
}

4.2.5、测试结果

在这里插入图片描述


5、全局配置文件详解

5.1、properties元素

用于加载配置文件。比如<properties resource="配置文件的路径"></properties>。使用时${属性名}即可。

5.2、settings

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

<!--
    参数说明:
    cacheModelsEnabled:
    启用或禁用SqlMapClient的所有缓存model。调试程序时使用。
    enhancementEnabled:
    启用或禁用运行时字节码增强,以优化访问Java Bean属性的性能,同时优化延迟加载
    的性能。
    lazyLoadingEnabled:
    启用或禁用SqlMapClient的所有延迟加载。调试程序时使用。
    maxRequests:
    同时执行SQL语句的最大线程数。大于这个值的线程将阻塞直到另一个线程执行完成。
    不同的DBMS有不同的限制值,但任何数据库都有这些限制。通常这个值应该至少是
    maxTransactions的10倍,并且总是大于maxSessions和maxTranactions。减小这个参数值通常能提高性能。
    maxSessions:
    同一时间内活动的最大session数。一个session可以是代码请求的显式session,
    也可以是当线程使用SqlMapClient实例(即执行一条语句)自动获得的session。
    它应该总是大于或等于maxTransactions并小于maxRequests。减小这个参数值通常能
    减少内存使用。
    maxTransactions:
    同时进入SqlMapClient.startTransaction()的最大线程数。大于这个值的线程将阻塞
    直到另一个线程退出。不同的DBMS有不同的限制值,但任何数据库都有这些限制。这个
    参数值应该总是小于或等于maxSessions并总是远远小于maxRequests。减小这个参数值
    通常能提高性能。
    useStatementNamespaces:
    如果启用本属性,必须使用全限定名来引用mapped statement。Mapped statement的
    全限定名由sql-map的名称和mapped-statement的名称合成,例如
    queryForObject(“sqlMapName.statementName”)
      -->
    <settings cacheModelsEnabled="true"
        enhancementEnabled="false"
        lazyLoadingEnabled="false"
        maxRequests="3000"
        maxSessions="3000"
        maxTransactions="3000"
        useStatementNamespaces="false"/>

5.3、typeAliases

5.3.1、Mybatis支持的别名

别名映射的类型
_bytebyte
_longlong
_shortshort
_intint
_integerint
_doubledouble
_floatfloat
_booleanboolean
stringString
byteByte
longLong
shortShort
intInteger
integerInteger
doubleDouble
floatFloat
booleanBoolean
dateDate
decimalBigDecimal
bigdecimalBigDecimal

5.3.2、自定义别名

<typeAliases>
	<!--定义单个别名 -->
	<typeAlias type="com.csa.po.User" alias="user"/>
	<!-- 
		批量定义别名
			规则:类首字母小写
	 -->
	 <package name="com.csa.po"/>
</typeAliases>

5.4、mappers

以下4种形式,加载映射文件:

<!-- 加载UserMapper.xml文件 -->
<mappers>
	<!-- 相对路径 -->
	<mapper resource="User.xml"/>
	<!-- 完全限定路径 -->
	<mapper url="file:///D:\Mybatis\MybatisPro2\src\User.xml"/>
	<!-- 接口路径 -->
	<mapper class="com.csa.dao.UserDao"/>
	<!-- 包路径(常用) -->
	<package name="com.csa.dao"/>
</mappers>

6、输入映射与输出映射

6.1、输入映射与简单类型输出映射

6.1.1、简单类型输入

映射文件
<!-- 查询对应ID的用户名 -->
<select id="findUsernameById" parameterType="int" resultType="string">
	select username from User where id = #{id}
</select>
UserDao接口
/**
 * 通过id查找用户名
 * @param id
 * @return 用户名
 */
public String findUsernameById(Integer id);
测试方法
public static void main(String[] args) throws Exception {
	// 读取全局配置文件
	String resource = "SqlMapConfig.xml";
	InputStream input = Resources.getResourceAsStream(resource);
	// 创建SqlSessionFactory
	SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
	// 创建sqlSession
	SqlSession sqlSession = sqlSessionFactory.openSession();
	// 创建dao类
	UserDao userDao = sqlSession.getMapper(UserDao.class);
	// 执行简单类型的查找
	userDao.findUsernameById(16);
	System.out.println(username);
	// 关闭sqlSession
	sqlSession.close();
}
实验结果

在这里插入图片描述

6.1.2、POJO类型输入

映射文件
<!-- 查询符合年龄和出生月份的用户 -->
<select id="selectUsernamesByBrithday" parameterType="com.csa.po.User" resultType="string">
	select username from User where age=${age} and brithdayMonth=${brithdayMonth}
</select>
UserDao接口
/**
 * 查找与User的同年同月生的用户的用户名
 * @param user
 * @return
 */
public List<String> selectUsernamesByBrithday(User user);
测试方法
public static void main(String[] args) throws Exception {
	// 读取全局配置文件
	String resource = "SqlMapConfig.xml";
	InputStream input = Resources.getResourceAsStream(resource);
	// 创建SqlSessionFactory
	SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
	// 创建sqlSession
	SqlSession sqlSession = sqlSessionFactory.openSession();
	// 创建dao类
	UserDao userDao = sqlSession.getMapper(UserDao.class);
	User user = userDao.findUserById(15);
	System.out.println(user);
	List<String> usernames = userDao.selectUsernamesByBrithday(user);
	System.out.println(usernames);
	// 关闭sqlSession
	sqlSession.close();
}
实验结果

在这里插入图片描述

6.1.3、POJO类型嵌套POPJ类型的输入映射

User
package com.csa.po;

public class User {
	private Integer id;
	private String username;
	private Integer age;
	private Integer brithdayMonth;
	
	// set/get...
	
	@Override
	public String toString() {
		return "User [id=" + id + ", username=" + username + ", age=" + age + ", brithdayMonth=" + brithdayMonth + "]";
	}
}
UserVo
package com.csa.po;

public class UserVo {
	private User user;

	// set/get...

	@Override
	public String toString() {
		return "UserVo [user=" + user + "]";
	}
}
映射文件
<!-- POJO类型嵌套POPJ类型的输入映射,查询符合年龄和出生月份的用户 -->
	<select id="selectUserVonamesByBrithday" parameterType="com.csa.po.UserVo" resultType="string">
		select username from User where age=${user.age} and brithdayMonth=${user.brithdayMonth}
	</select>
UserDao接口
/**
 * POJO类型嵌套POPJ类型的输入映射
 * 查找与UserVo的同年同月生的用户的用户名
 * @param userVo
 * @return
 */
public List<String> selectUserVonamesByBrithday(UserVo userVo);
测试方法
public static void main(String[] args) throws Exception {
	// 读取全局配置文件
	String resource = "SqlMapConfig.xml";
	InputStream input = Resources.getResourceAsStream(resource);
	// 创建SqlSessionFactory
	SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
	// 创建sqlSession
	SqlSession sqlSession = sqlSessionFactory.openSession();
	// 创建dao类
	UserDao userDao = sqlSession.getMapper(UserDao.class);
	User user = userDao.findUserById(15);
	UserVo userVo = new UserVo();
	userVo.setUser(user);
	System.out.println(userVo);
	List<String> usernames = userDao.selectUserVonamesByBrithday(userVo);
	System.out.println(usernames);
	// 关闭sqlSession
	sqlSession.close();
}
实验结果

在这里插入图片描述

6.1.4、Map类型的输入映射

映射文件
<!-- 查询在某年某月出生的用户的用户名 -->
<select id="findUsernamesByBrithday" parameterType="hashmap" resultType="string">
	select username from User where age=${age} and brithdayMonth=${brithdayMonth}
</select>
UserDao接口
/**
 * 通过hashmap查询在某年某月出生的用户的用户名
 * @param map
 * @return
 */
public List<String> findUsernamesByBrithday(Map<String,Object> map);
测试
public static void main(String[] args) throws Exception {
	//读取全局配置文件
	String resource = "SqlMapConfig.xml";
	InputStream input = Resources.getResourceAsStream(resource);
	// 创建SqlSessionFactory
	SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
	// 创建sqlSession
	SqlSession sqlSession = sqlSessionFactory.openSession();
	// 创建dao类
	UserDao userDao = sqlSession.getMapper(UserDao.class);
	Map<String,Object> map = new HashMap<>();
	map.put("age", 12);
	map.put("brithdayMonth", 10);
	List<String> usernames = userDao.findUsernamesByBrithday(map);
	System.out.println(usernames);
	// 关闭sqlSession
	sqlSession.close();
}
测试结果

在这里插入图片描述

6.2、简单类型输入映射与输出映射

6.2.1、resultMap属性

映射文件
<!-- 定义一个resultMap,id唯一标识 -->
<resultMap type="com.csa.po.User" id="userMap">
	<result column="_id" property="id"/>
	<result column="_username" property="username"/>
	<result column="_age" property="age"/>
	<result column="_brithdayMonth" property="brithdayMonth"/>
</resultMap>

<!-- 使用resultMap,通过id查询User -->
<select id="selectUserMap" parameterType="int" resultMap="userMap">
	select id _id,username _username,age _age,brithdayMonth _brithdayMonth 
	from User 
	where id=#{id}
</select>
UserDao接口
/**
 * 通过id查询User
 * @param id
 * @return
 */
public User selectUserMap(Integer id);
测试
public static void main(String[] args) throws Exception {
	// 读取全局配置文件
	String resource = "SqlMapConfig.xml";
	InputStream input = Resources.getResourceAsStream(resource);
	// 创建SqlSessionFactory
	SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
	// 创建sqlSession
	SqlSession sqlSession = sqlSessionFactory.openSession();
	// 创建dao
	UserDao userDao = sqlSession.getMapper(UserDao.class);
	User user = userDao.selectUserMap(15);
	System.out.println(user);
	// 关闭sqlSession
	sqlSession.close();
}
测试结果

在这里插入图片描述

复杂输入类型与复杂输出类型的一个例子

输入类型是map,输出类型是一个UserVo。

UserVo类
package com.csa.po;
public class UserVo {
	private User user;

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

	@Override
	public String toString() {
		return "UserVo [user=" + user + "]";
	}
}
UserDao接口
/**
 * 通过map类型查找UserVo
 * @param map
 * @return
 */
public List<UserVo> selectUserVosMap(Map<String,Object> map);
映射文件
<!-- 复杂输入类型与复杂输出类型的一个例子 -->
<!-- resultmap -->
<resultMap type="com.csa.po.UserVo" id="userVoMap">
	<result column="id" property="user.id"/>
	<result column="username" property="user.username"/>
	<result column="age" property="user.age"/>
	<result column="brithdayMonth" property="user.brithdayMonth"/>
</resultMap>
<!-- 使用resultMap,查询在某年某月出生的User并封装到UserVo -->
<select id="selectUserVosMap" parameterType="hashmap" resultMap="userVoMap">
	select * from User where age=#{age} and brithdayMonth=#{brithdayMonth}
</select>
测试
public static void main(String[] args) throws Exception {
	// 读取全局配置文件
	String resource = "SqlMapConfig.xml";
	InputStream input = Resources.getResourceAsStream(resource);
	// 创建SqlSessionFactory
	SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
	// 创建sqlSession
	SqlSession sqlSession = sqlSessionFactory.openSession();
	// 创建dao
	UserDao userDao = sqlSession.getMapper(UserDao.class);
	Map<String,Object> map = new HashMap<>();
	map.put("age", 12);
	map.put("brithdayMonth", 10);
	List<UserVo> userVo = userDao.selectUserVosMap(map);
	System.out.println(userVo);
	// 关闭sqlSession
	sqlSession.close();
}
测试结果

在这里插入图片描述


7、动态sql

7.1、动态sql介绍

在mybatis中,它提供了一些动态sql标签,可以让程序员更快的进行mybatis的开发,这些动态sql可以通过sql的可重用性。

常用的动态sql标签:if标签、where标签、sql片段、foreach标签

7.2、If标签/where标签

映射文件

<!-- 复杂输入类型与复杂输出类型的一个例子 -->
<!-- resultmap -->
<resultMap type="com.csa.po.UserVo" id="userVoMap">
	<result column="id" property="user.id"/>
	<result column="username" property="user.username"/>
	<result column="age" property="user.age"/>
	<result column="brithdayMonth" property="user.brithdayMonth"/>
</resultMap>

<!-- 
	输入类型:UserVo
	输出类型:UserVo
	查询特定某年某月出生的用户,如果这个用户年龄和月份没有透露完全,则根据对应的去查找
 -->
<select id="selectUserVoList" parameterType="com.csa.po.UserVo" resultMap="userVoMap">
	select * from User
	<!-- where标签:默认去掉后面第一个and,如果没有参数,则把自己干掉 -->
	<where>
		<!-- if标签:可以对输入的参数进行判断 -->
		<!-- 与OGNL表达式类似 -->
		<if test="user != null">
			<if test="user.age != null">
				and age=#{user.age}
			</if>
			<if test="user.brithdayMonth != null">
				and brithdayMonth=#{brithdayMonth}
			</if>
		</if>
	</where>
</select>

UserDao接口

/**
 * 查询特定某年某月出生的用户,如果这个用户年龄和月份没有透露完全,则根据对应的去查找
 * @param userVo
 * @return
 */
public List<UserVo> selectUserVoList(UserVo userVo);

测试

public static void main(String[] args) throws Exception {
	// 读取全局配置文件
	String resource = "SqlMapConfig.xml";
	InputStream input = Resources.getResourceAsStream(resource);
	// 创建SqlSessionFactory
	SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
	// 创建sqlSession
	SqlSession sqlSession = sqlSessionFactory.openSession();
	// 创建dao
	UserDao userDao = sqlSession.getMapper(UserDao.class);
	User user = new User();
	UserVo userVo = new UserVo();
	user.setAge(12);
	userVo.setUser(user);
	List<UserVo> userVoList = userDao.selectUserVoList(userVo);
	System.out.println(userVoList);
	// 关闭sqlSession
	sqlSession.close();
}

测试结果

在这里插入图片描述

7.3、sql片段

映射文件
<!-- 
	输入类型:UserVo
	输出类型:UserVo
	查询特定某年某月出生的用户,如果这个用户年龄和月份没有透露完全,则根据对应的去查找
 -->
<select id="selectUserVoList" parameterType="com.csa.po.UserVo" resultMap="userVoMap">
	select * from User
	<include refid="whereUser"></include>
</select>

<sql id="whereUser">
	<!-- where标签:默认去掉后面第一个and,如果没有参数,则把自己干掉 -->
	<where>
		<!-- if标签:可以对输入的参数进行判断 -->
		<!-- 与OGNL表达式类似 -->
		<if test="user != null">
			<if test="user.age != null">
				and age=#{user.age}
			</if>
			<if test="user.brithdayMonth != null">
				and brithdayMonth=#{brithdayMonth}
			</if>
		</if>
	</where>
</sql>

7.4、sql片段

<foreach collection="迭代集合" item="迭代对象" open="()" close=")" separator=",">
	#{迭代对象.属性}
</foreach>

参考

黑马笔记和各种博客!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值