Mybatis教程-实战

article/2025/8/20 2:00:26

1.从JDBC谈起

1.1.使用IDEA创建maven工程
在这里插入图片描述

在这里插入图片描述
1.2.引入mysql依赖包

<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.32</version>
</dependency>

在这里插入图片描述
1.3.准备数据

  • 创建数据库:
CREATE DATABASE ssmdemo;
  • 创建表:
DROP TABLE IF EXISTS tb_user;
CREATE TABLE tb_user (
id int(10) NOT NULL AUTO_INCREMENT ,
user_name varchar(32) DEFAULT NULL,
password varchar(32) DEFAULT NULL,
name varchar(32) DEFAULT NULL,
age int(10) DEFAULT NULL,
sex int(2) DEFAULT NULL,
birthday date DEFAULT NULL,
created datetime DEFAULT NULL,
updated datetime DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  • 插入数据:
insert into `ssmdemo`.`tb_user` ( `updated`, `password`,  `age`, `birthday`, `created`, `user_name`, `sex`, `name`) values ( sysdate(), '123456',  '22', '1990-09-02', sysdate(), 'zpc', 0, '小红');
insert into `ssmdemo`.`tb_user` ( `updated`, `password`,  `age`, `birthday`, `created`, `user_name`, `sex`, `name`) values ( sysdate(), '123456',  '21', '1990-09-05', sysdate(), 'hj', 1, '小明');

1.4.JDBC基础代码回顾

  • JDBCTest.java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;/*** @T-zhaos* 2020/09/01*/
public class JDBCTest {public static void main(String[] args) throws Exception {Connection connection = null;PreparedStatement prepareStatement = null;ResultSet rs = null;try {// 加载驱动Class.forName("com.mysql.jdbc.Driver");// 获取连接String url = "jdbc:mysql://127.0.0.1:3306/ssmdemo";String user = "root";String password = "root";connection = DriverManager.getConnection(url, user, password);// 获取statement,preparedStatementString sql = "select * from tb_user where id=?";prepareStatement = connection.prepareStatement(sql);// 设置参数prepareStatement.setLong(1, 1l);// 执行查询rs = prepareStatement.executeQuery();// 处理结果集while (rs.next()) {System.out.println(rs.getString("userName"));System.out.println(rs.getString("name"));System.out.println(rs.getInt("age"));System.out.println(rs.getDate("birthday"));}} finally {// 关闭连接,释放资源if (rs != null) {rs.close();}if (prepareStatement != null) {prepareStatement.close();}if (connection != null) {connection.close();}}}
}

2.MyBatis介绍

在这里插入图片描述

官方文档 http://www.mybatis.org/mybatis-3/getting-started.html

3.Mybaits整体架构

在这里插入图片描述

4.快速入门(quick start)

  • 4.1.引入依赖(pom.xml)
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.2.8</version>
</dependency>
  • 4.2.全局配置文件(mybatis-config.xml)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- 根标签 -->
<configuration><properties><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://127.0.0.1:3306/ssmdemo?useUnicode=true&amp;characterEncoding=utf-8&amp;allowMultiQueries=true"/><property name="username" value="root"/><property name="password" value="root"/></properties><!-- 环境,可以配置多个,default:指定采用哪个环境 --><environments default="test"><!-- id:唯一标识 --><environment id="test"><!-- 事务管理器,JDBC类型的事务管理器 --><transactionManager type="JDBC" /><!-- 数据源,池类型的数据源 --><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver" /><property name="url" value="jdbc:mysql://127.0.0.1:3306/ssmdemo" /><property name="username" value="root" /><property name="password" value="root" /></dataSource></environment><environment id="development"><!-- 事务管理器,JDBC类型的事务管理器 --><transactionManager type="JDBC" /><!-- 数据源,池类型的数据源 --><dataSource type="POOLED"><property name="driver" value="${driver}" /> <!-- 配置了properties,所以可以直接引用 --><property name="url" value="${url}" /><property name="username" value="${username}" /><property name="password" value="${password}" /></dataSource></environment></environments>
</configuration>
  • 4.3.配置Map.xml(MyMapper.xml)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- mapper:根标签,namespace:命名空间,随便写,一般保证命名空间唯一 -->
<mapper namespace="MyMapper"><!-- statement,内容:sql语句。id:唯一标识,随便写,在同一个命名空间下保持唯一resultType:sql语句查询结果集的封装类型,tb_user即为数据库中的表--><select id="selectUser" resultType="cn.ssm.domian.User">select * from tb_user where id = #{id}</select>
</mapper>
  • 4.4.修改全局配置文件(mybatis-config.xml)
    配上MyMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- 根标签 -->
<configuration><properties><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://127.0.0.1:3306/ssmdemo?useUnicode=true&amp;characterEncoding=utf-8&amp;allowMultiQueries=true"/><property name="username" value="root"/><property name="password" value="root"/></properties><!-- 环境,可以配置多个,default:指定采用哪个环境 --><environments default="test"><!-- id:唯一标识 --><environment id="test"><!-- 事务管理器,JDBC类型的事务管理器 --><transactionManager type="JDBC" /><!-- 数据源,池类型的数据源 --><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver" /><property name="url" value="jdbc:mysql://127.0.0.1:3306/ssmdemo" /><property name="username" value="root" /><property name="password" value="root" /></dataSource></environment><environment id="development"><!-- 事务管理器,JDBC类型的事务管理器 --><transactionManager type="JDBC" /><!-- 数据源,池类型的数据源 --><dataSource type="POOLED"><property name="driver" value="${driver}" /> <!-- 配置了properties,所以可以直接引用 --><property name="url" value="${url}" /><property name="username" value="${username}" /><property name="password" value="${password}" /></dataSource></environment></environments><mappers><mapper resource="mappers/MyMapper.xml" /></mappers>
</configuration>
  • 4.5 完整代码:
  • User.java
package cn.ssm.domian;import java.util.Date;public class User {Integer id;String user_name;String password;String name;Integer age;Integer sex;Date birthday;Date created;Date updated;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUser_name() {return user_name;}public void setUser_name(String user_name) {this.user_name = user_name;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Integer getSex() {return sex;}public void setSex(Integer sex) {this.sex = sex;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}public Date getCreated() {return created;}public void setCreated(Date created) {this.created = created;}public Date getUpdated() {return updated;}public void setUpdated(Date updated) {this.updated = updated;}@Overridepublic String toString() {return "User{" +"id=" + id +", userName='" + user_name + '\'' +", password='" + password + '\'' +", name='" + name + '\'' +", age=" + age +", sex=" + sex +", birthday=" + birthday +", created=" + created +", updated=" + updated +'}';}
}
  • JDBCTest.java
package cn.ssm.test;import cn.ssm.domian.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 java.io.IOException;
import java.io.InputStream;public class MybatisTest {public static void main(String[] args) throws IOException {// 指定全局配置文件String resource = "mybatis-config.xml";// 读取配置文件InputStream inputStream = Resources.getResourceAsStream(resource);// 构建sqlSessionFactorySqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);// 获取sqlSessionSqlSession sqlSession = sqlSessionFactory.openSession();// 操作CRUD,第一个参数:指定statement,规则:命名空间+“.”+statementId// 第二个参数:指定传入sql的参数:这里是用户idUser user = sqlSession.selectOne("MyMapper.selectUser", 1);System.out.println(user);}
}

4.6.目录结构

在这里插入图片描述

5.分析

  • 5.1.引入日志依赖包(pom.xml)
    会自动引入log4j以及slf4j-api
<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.5</version>
</dependency>
  • 5.2.添加log4j.properties
log4j.rootLogger=DEBUG,A1
log4j.logger.org.apache=DEBUG
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n
  • 再次运行程序会打印日志:
Connected to the target VM, address: '127.0.0.1:64813', transport: 'socket'
2020-09-02 17:54:34,230 [main] [org.apache.ibatis.logging.LogFactory]-[DEBUG] Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.
2020-09-02 17:54:34,244 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] PooledDataSource forcefully closed/removed all connections.
2020-09-02 17:54:34,244 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] PooledDataSource forcefully closed/removed all connections.
2020-09-02 17:54:34,244 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] PooledDataSource forcefully closed/removed all connections.
2020-09-02 17:54:34,244 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] PooledDataSource forcefully closed/removed all connections.
2020-09-02 17:54:34,308 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Opening JDBC Connection
2020-09-02 17:54:34,576 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Created connection 310623126.
2020-09-02 17:54:34,576 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1283bb96]
2020-09-02 17:54:34,578 [main] [MyMapper.selectUser]-[DEBUG] ==>  Preparing: select * from tb_user where id = ? 
2020-09-02 17:54:34,608 [main] [MyMapper.selectUser]-[DEBUG] ==> Parameters: 1(Integer)
2020-09-02 17:54:34,628 [main] [MyMapper.selectUser]-[DEBUG] <==      Total: 1
User{id=1, userName='zpc', password='123456', name='鹏程', age=22, sex=0, birthday=Sun Sep 02 00:00:00 CDT 1990, created=Wed Sep 02 15:37:00 CST 2020, updated=Wed Sep 02 15:37:00 CST 2020}
Disconnected from the target VM, address: '127.0.0.1:64813', transport: 'socket'Process finished with exit code 0
  • 5.3.MyBatis使用步骤总结
  • 1)配置mybatis-config.xml 全局的配置文件 (1、数据源,2、外部的mapper)
  • 2)创建SqlSessionFactory
  • 3)通过SqlSessionFactory创建SqlSession对象
  • 4)通过SqlSession操作数据库 CRUD
  • 5)调用session.commit()提交事务
  • 6)调用session.close()关闭会话

6.完整的CRUD操作

  • 6.1.创建UserDao接口
package cn.ssm.service;import cn.ssm.domian.User;import java.util.List;public interface UserDao {/*** 根据用户id查询用户信息* @param id* @return*/public User queryUserById(Integer id);/*** 查询所有的用户信息* @return*/public List<User> findAll();/*** 新增用户* @param user*/public void insertUser(User user);/*** 修改用户信息* @param user*/public void updateUser(User user);/*** 根据用户id删除用户信息* @param id*/public void deleteUser(Integer id);
}
  • 6.2.创建UserDaoImpl
package cn.ssm.service.impl;import cn.ssm.domian.User;
import cn.ssm.service.UserDao;
import org.apache.ibatis.session.SqlSession;import java.util.List;public class UserDaoImpl implements UserDao {public SqlSession sqlSession;public UserDaoImpl(SqlSession sqlSession) {this.sqlSession = sqlSession;}public User queryUserById(Integer id) {return this.sqlSession.selectOne("UserDao.queryUserById", id);}public List<User> findAll() {return this.sqlSession.selectList("UserDao.queryUserAll");}public void insertUser(User user) {this.sqlSession.insert("UserDao.insertUser", user);}public void updateUser(User user) {this.sqlSession.update("UserDao.updateUser", user);}public void deleteUser(Integer id) {this.sqlSession.delete("UserDao.deleteUser", id);}
}
  • 6.3.编写UserDao对应的UserDaoMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- mapper:根标签,namespace:命名空间,随便写,一般保证命名空间唯一 -->
<mapper namespace="UserDao"><!-- statement,内容:sql语句。id:唯一标识,随便写,在同一个命名空间下保持唯一resultType:sql语句查询结果集的封装类型,tb_user即为数据库中的表--><!--<select id="queryUserById" resultType="com.zpc.mybatis.pojo.User">--><!--select * from tb_user where id = #{id}--><!--</select>--><!--使用别名--><select id="queryUserById" resultType="cn.ssm.domian.User">selecttuser.id as id,tuser.user_name as userName,tuser.password as password,tuser.name as name,tuser.age as age,tuser.birthday as birthday,tuser.sex as sex,tuser.created as created,tuser.updated as updatedfromtb_user tuserwhere tuser.id = #{id};</select><select id="queryUserAll" resultType="cn.ssm.domian.User">select * from tb_user;</select><!--插入数据--><insert id="insertUser" parameterType="cn.ssm.domian.User">INSERT INTO tb_user (user_name,password,name,age,sex,birthday,created,updated)VALUES(#{userName},#{password},#{name},#{age},#{sex},#{birthday},now(),now());</insert><update id="updateUser" parameterType="cn.ssm.domian.User">UPDATE tb_user<trim prefix="set" suffixOverrides=","><if test="userName!=null">user_name = #{userName},</if><if test="password!=null">password = #{password},</if><if test="name!=null">name = #{name},</if><if test="age!=null">age = #{age},</if><if test="sex!=null">sex = #{sex},</if><if test="birthday!=null">birthday = #{birthday},</if>updated = now(),</trim>WHERE(id = #{id});</update><delete id="deleteUser">delete from tb_user where id=#{id}</delete>
</mapper>
  • 在mybatis-config.xml中添加配置:
<mappers><mapper resource="mappers/MyMapper.xml" /><mapper resource="mappers/UserDaoMapper.xml" />
</mappers>
  • 6.4.添加UserDao的测试用例
    Pom文件中添加junit依赖
 <dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version>
</dependency>
windows按住Alt+Enter,选择create test(mac 按住control+Enter)

在这里插入图片描述

在这里插入图片描述

  • 6.5.编写UserDao的测试用例
package cn.ssm.service;import cn.ssm.domian.User;
import cn.ssm.service.impl.UserDaoImpl;
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.Date;
import java.util.List;public class UserDaoTest {public UserDao userDao;public SqlSession sqlSession;@Beforepublic void setUp() throws Exception {// mybatis-config.xmlString resource = "mybatis-config.xml";// 读取配置文件InputStream is = Resources.getResourceAsStream(resource);// 构建SqlSessionFactorySqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);// 获取sqlSessionsqlSession = sqlSessionFactory.openSession();this.userDao = new UserDaoImpl(sqlSession);}@Testpublic void queryUserById() throws Exception {System.out.println(this.userDao.queryUserById(1));}@Testpublic void queryUserAll() throws Exception {List<User> userList = this.userDao.findAll();for (User user : userList) {System.out.println(user);}}@Testpublic void insertUser() throws Exception {User user = new User();user.setAge(16);user.setBirthday(new Date("1990/09/02"));user.setName("大鹏");user.setPassword("123456");user.setSex(1);user.setUserName("evan");this.userDao.insertUser(user);this.sqlSession.commit();}@Testpublic void updateUser() throws Exception {User user = new User();user.setBirthday(new Date());user.setName("静鹏");user.setPassword("654321");user.setSex(1);user.setUserName("evanjin");user.setId(1);this.userDao.updateUser(user);this.sqlSession.commit();}@Testpublic void deleteUser() throws Exception {this.userDao.deleteUser(4);this.sqlSession.commit();}
}
  • 6.6.目录结构
    在这里插入图片描述
  • 6.7.解决数据库字段名和实体类属性名不一致的问题
    查询数据的时候,发现查不到userName的信息,

User{id=‘2’, userName=‘null’, password=‘123456’, name=‘静静’, age=22, sex=0, birthday=‘1993-09-05’, created=‘2018-06-30 18:22:28.0’, updated=‘2018-06-30 18:22:28.0’}

原因:数据库的字段名是user_name,POJO中的属性名字是userName
两端不一致,造成mybatis无法填充对应的字段信息。修改方法:在sql语句中使用别名。

  • 解决方案1:在sql语句中使用别名:
<!--使用别名--><select id="queryUserById" resultType="cn.ssm.domian.User">selecttuser.id as id,tuser.user_name as userName,tuser.password as password,tuser.name as name,tuser.age as age,tuser.birthday as birthday,tuser.sex as sex,tuser.created as created,tuser.updated as updatedfromtb_user tuserwhere tuser.id = #{id};</select>
  • 解决方案2: 参考后面的resultMap –mapper具体的配置的时候

  • 解决方案3:参考驼峰匹配 — mybatis-config.xml 的时候

7.动态代理Mapper实现类

  • 7.1.思考上述CRUD中的问题
  • 1、接口->实现类->mapper.xml
  • 2、实现类中,使用mybatis的方式非常类似
  • 3、xml中的sql statement 硬编码到java代码中。

思考:能否只写接口,不写实现类。只编写接口和Mapper.xml即可?
因为在dao(mapper)的实现类中对sqlsession的使用方式很类似。因此mybatis提供了接口的动态代理。

  • 7.2.使用动态代理改造CRUD
    修改测试用例的setUp方法
//this.userDao = new UserDaoImpl(sqlSession);this.userDao = sqlSession.getMapper(UserDao.class);

在这里插入图片描述

  • 执行queryUserAll()方法

在这里插入图片描述

  • 分析原因,在UserMapper.xml中配置接口的全路径mapper.xml namespace
    如果希望使用mybatis通过的动态代理的接口,就需要namespace中的值,和需要对应的Mapper(dao)接口的全路径一致。Mapper中Namespace的定义本身是没有限制的,只要不重复即可,但如果使用Mybatis的DAO接口动态代理,则namespace必须为DAO接口的全路径,例如:cn.ssm.service.UserDao
    在这里插入图片描述
  • 7.3.完整的例子
    1、创建UserMapper接口(对应原UserDao)
package cn.ssm.service;import cn.ssm.domian.User;
import org.apache.ibatis.annotations.Param;import java.util.List;public interface UserMapper {/*** 登录(直接使用注解指定传入参数名称)* @param userName* @param password* @return*/public User login(@Param("userName") String userName, @Param("password") String password);/*** 根据表名查询用户信息(直接使用注解指定传入参数名称)* @param tableName* @return*/public List<User> queryUserByTableName(@Param("tableName") String tableName);/*** 根据Id查询用户信息* @param id* @return*/public User queryUserById(Long id);/*** 查询所有用户信息* @return*/public List<User> queryUserAll();/*** 新增用户信息* @param user*/public void insertUser(User user);/*** 根据id更新用户信息* @param user*/public void updateUser(User user);/*** 根据id删除用户信息* @param id*/public void deleteUserById(Long id);
}

2、创建UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- mapper:根标签,namespace:命名空间,随便写,一般保证命名空间唯一 ,为了使用接口动态代理,这里必须是接口的全路径名-->
<mapper namespace="cn.ssm.service.UserMapper"><!--1.#{},预编译的方式preparedstatement,使用占位符替换,防止sql注入,一个参数的时候,任意参数名可以接收2.${},普通的Statement,字符串直接拼接,不可以防止sql注入,一个参数的时候,必须使用${value}接收参数--><select id="queryUserByTableName" resultType="cn.ssm.domian.User">select * from ${tableName}</select><select id="login" resultType="cn.ssm.domian.User">select * from tb_user where user_name = #{userName} and password = #{password}</select><!-- statement,内容:sql语句。id:唯一标识,随便写,在同一个命名空间下保持唯一,使用动态代理之后要求和方法名保持一致resultType:sql语句查询结果集的封装类型,使用动态代理之后和方法的返回类型一致;resultMap:二选一parameterType:参数的类型,使用动态代理之后和方法的参数类型一致--><select id="queryUserById" resultType="cn.ssm.domian.User">select * from tb_user where id = #{id}</select><select id="queryUserAll" resultType="cn.ssm.domian.User">select * from tb_user</select><!-- 新增的Statementid:唯一标识,随便写,在同一个命名空间下保持唯一,使用动态代理之后要求和方法名保持一致parameterType:参数的类型,使用动态代理之后和方法的参数类型一致useGeneratedKeys:开启主键回写keyColumn:指定数据库的主键keyProperty:主键对应的pojo属性名--><insert id="insertUser" useGeneratedKeys="true" keyColumn="id" keyProperty="id"parameterType="cn.ssm.domian.User">INSERT INTO tb_user (id,user_name,password,name,age,sex,birthday,created,updated)VALUES(null,#{userName},#{password},#{name},#{age},#{sex},#{birthday},NOW(),NOW());</insert><!--更新的statementid:唯一标识,随便写,在同一个命名空间下保持唯一,使用动态代理之后要求和方法名保持一致parameterType:参数的类型,使用动态代理之后和方法的参数类型一致--><update id="updateUser" parameterType="cn.ssm.domian.User">UPDATE tb_user<trim prefix="set" suffixOverrides=","><if test="userName!=null">user_name = #{userName},</if><if test="password!=null">password = #{password},</if><if test="name!=null">name = #{name},</if><if test="age!=null">age = #{age},</if><if test="sex!=null">sex = #{sex},</if><if test="birthday!=null">birthday = #{birthday},</if>updated = now(),</trim>WHERE(id = #{id});</update><!--删除的statementid:唯一标识,随便写,在同一个命名空间下保持唯一,使用动态代理之后要求和方法名保持一致parameterType:参数的类型,使用动态代理之后和方法的参数类型一致--><delete id="deleteUserById" parameterType="java.lang.String">delete from tb_user where id=#{id}</delete>
</mapper>

3、全局配置文件mybatis-config.xml引入UserMapper.xml

<mappers><mapper resource="mappers/MyMapper.xml" /><mapper resource="mappers/UserDaoMapper.xml" /><mapper resource="mappers/UserMapper.xml" />
</mappers>

4、创建UserMapper测试用例

package cn.ssm.service;import cn.ssm.domian.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.Before;
import org.junit.Test;import java.io.InputStream;
import java.util.Date;
import java.util.List;public class UserMapperTest {public UserMapper userMapper;@Beforepublic void setUp() throws Exception {// 指定配置文件String resource = "mybatis-config.xml";// 读取配置文件InputStream inputStream = Resources.getResourceAsStream(resource);// 构建sqlSessionFactorySqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);// 获取sqlSessionSqlSession sqlSession = sqlSessionFactory.openSession(true);// 1. 映射文件的命名空间(namespace)必须是mapper接口的全路径// 2. 映射文件的statement的id必须和mapper接口的方法名保持一致// 3. Statement的resultType必须和mapper接口方法的返回类型一致// 4. statement的parameterType必须和mapper接口方法的参数类型一致(不一定)this.userMapper = sqlSession.getMapper(UserMapper.class);}@Testpublic void login() {System.out.println(this.userMapper.login("hj", "123456"));}@Testpublic void queryUserByTableName() {List<User> userList = this.userMapper.queryUserByTableName("tb_user");for (User user : userList) {System.out.println(user);}}@Testpublic void queryUserById() {System.out.println(this.userMapper.queryUserById(1L));}@Testpublic void queryUserAll() {List<User> userList = this.userMapper.queryUserAll();for (User user : userList) {System.out.println(user);}}@Testpublic void insertUser() {User user = new User();user.setAge(20);user.setBirthday(new Date());user.setName("大神");user.setPassword("123456");user.setSex(2);user.setUserName("bigGod222");this.userMapper.insertUser(user);System.out.println(user.getId());}@Testpublic void updateUser() {User user = new User();user.setBirthday(new Date());user.setName("静静");user.setPassword("123456");user.setSex(0);user.setUserName("Jinjin");user.setId(1);this.userMapper.updateUser(user);}@Testpublic void deleteUserById() {this.userMapper.deleteUserById(1L);}
}

目录结构:
在这里插入图片描述

  • 7.4.动态代理总结

在这里插入图片描述

8.mybatis-config.xml详解

mybatis-config.xml讲究严格的顺序,具体顺序遵循文档的顺序
在这里插入图片描述

  • 8.1.properties属性读取外部资源
    properties配置的属性都是可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可通过 properties 元素的子元素来传递。例如:
    在这里插入图片描述
    然后其中的属性就可以在整个配置文件中被用来替换需要动态配置的属性值。比如:
    在这里插入图片描述
    这个例子中的 username 和 password 将会由 properties 元素中设置的相应值来替换。 driver 和 url 属性将会由 config.properties 文件中对应的值来替换。这样就为配置提供了诸多灵活选择。
    属性也可以被传递到 SqlSessionFactoryBuilder.build()方法中。例如:
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, props);
// ... or ...
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, props);

如果属性在不只一个地方进行了配置,那么 MyBatis 将按照下面的顺序来加载:

  • 1)在 properties 元素体内指定的属性首先被读取。
  • 2)然后根据 properties 元素中的 resource 属性读取类路径下属性文件或根据 url 属性指定的路径读取属性文件,并覆盖已读取的同名属性。
  • 3)最后读取作为方法参数传递的属性,并覆盖已读取的同名属性。
    因此,通过方法参数传递的属性具有最高优先级,resource/url 属性中指定的配置文件次之,最低优先级的是 properties 属性中指定的属性。
  • 8.2.settings设置
    在这里插入图片描述
<settings><setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

测试:
没有开启驼峰匹配:

2020-09-03 14:47:50,843 [main] [cn.ssm.service.UserMapper.queryUserAll]-[DEBUG] ==>  Preparing: select * from tb_user 
2020-09-03 14:47:50,871 [main] [cn.ssm.service.UserMapper.queryUserAll]-[DEBUG] ==> Parameters: 
2020-09-03 14:47:50,888 [main] [cn.ssm.service.UserMapper.queryUserAll]-[DEBUG] <==      Total: 2
User{id=1, userName='null', password='123456', name='鹏程', age=22, sex=0, birthday=Sun Sep 02 00:00:00 CDT 1990, created=Wed Sep 02 15:37:00 CST 2020, updated=Wed Sep 02 15:37:00 CST 2020}
User{id=2, userName='null', password='123456', name='静静', age=21, sex=1, birthday=Wed Sep 05 00:00:00 CDT 1990, created=Wed Sep 02 15:37:00 CST 2020, updated=Wed Sep 02 15:37:00 CST 2020}

开启驼峰匹配:

2020-09-03 14:46:33,896 [main] [cn.ssm.service.UserMapper.queryUserAll]-[DEBUG] ==>  Preparing: select * from tb_user 
2020-09-03 14:46:33,923 [main] [cn.ssm.service.UserMapper.queryUserAll]-[DEBUG] ==> Parameters: 
2020-09-03 14:46:33,945 [main] [cn.ssm.service.UserMapper.queryUserAll]-[DEBUG] <==      Total: 2
User{id=1, userName='zpc', password='123456', name='鹏程', age=22, sex=0, birthday=Sun Sep 02 00:00:00 CDT 1990, created=Wed Sep 02 15:37:00 CST 2020, updated=Wed Sep 02 15:37:00 CST 2020}
User{id=2, userName='hj', password='123456', name='静静', age=21, sex=1, birthday=Wed Sep 05 00:00:00 CDT 1990, created=Wed Sep 02 15:37:00 CST 2020, updated=Wed Sep 02 15:37:00 CST 2020}
  • 8.3.typeAliases

类型别名是为 Java 类型命名的一个短的名字。它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。

<typeAliases><typeAlias type="cn.ssm.domian.User" alias="User"/>
</typeAliases>

缺点:每个pojo类都要去配置。
解决方案:使用扫描包,扫描指定包下的所有类,扫描之后的别名就是类名(不区分大小写),建议使用的时候和类名一致。

<typeAliases><!--type:实体类的全路径。alias:别名,通常首字母大写--><!--<typeAlias type="cn.ssm.domian.User" alias="User"/>--><package name="cn.ssm.domian"/>
</typeAliases>

Mybatis已经为普通的 Java 类型内建了许多相应的类型别名。它们都是大小写不敏感的.
在这里插入图片描述

  • 8.4.typeHandlers(类型处理器)
    无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。可以重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。

  • 8.5.plugins(插件)拦截器
    MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:

Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)ParameterHandler (getParameterObject, setParameters)ResultSetHandler (handleResultSets, handleOutputParameters)StatementHandler (prepare, parameterize, batch, update, query)

现在一些MyBatis 插件比如PageHelper都是基于这个原理,有时为了监控sql执行效率,也可以使用插件机制
原理:
在这里插入图片描述
自定义拦截器:

package cn.ssm.interceptor;import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;import java.util.Properties;
// ExamplePlugin.java
@Intercepts({@Signature(type= Executor.class,method = "update",args = {MappedStatement.class,Object.class})})
public class ExamplePlugin implements Interceptor {public Object intercept(Invocation invocation) throws Throwable {return invocation.proceed();}public Object plugin(Object target) {return Plugin.wrap(target, this);}public void setProperties(Properties properties) {}
}

配置:(注意顺序)
在这里插入图片描述

<plugins><plugin interceptor="cn.ssm.interceptor.ExamplePlugin"><property name="someProperty" value="100"/></plugin>
</plugins>

上面的插件将会拦截在 Executor 实例中所有的 “update” 方法调用, 这里的 Executor 是负责执行低层映射语句的内部对象。

  • 8.6.environments(环境)
    MyBatis 可以配置成适应多种环境,例如,开发、测试和生产环境需要有不同的配置;
    尽管可以配置多个环境,每个 SqlSessionFactory 实例只能选择其一。
    虽然,这种方式也可以做到很方便的分离多个环境,但是实际使用场景下,我们更多的是选择使用spring来管理数据源,来做到环境的分离。

  • 8.7.mappers
    需要告诉 MyBatis 到哪里去找到 SQL 映射语句。即告诉 MyBatis 到哪里去找映射文件。你可以使用相对于类路径的资源引用, 或完全限定资源定位符(包括 file:/// 的 URL),或类名和包名等。例如:

<!-- 使用相对于类路径的资源引用 -->
<mappers><mapper resource="org/mybatis/builder/AuthorMapper.xml"/><mapper resource="org/mybatis/builder/BlogMapper.xml"/><mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers><!-- 使用映射器接口实现类的完全限定类名 -->
<mappers><mapper class="org.mybatis.builder.AuthorMapper"/><mapper class="org.mybatis.builder.BlogMapper"/><mapper class="org.mybatis.builder.PostMapper"/>
</mappers>

这里所谓的mapper接口路径。实际上就是dao的接口路径。在mybatis中,通常把dao的包叫做mapper。类名,也叫做mapper

1、定义一个接口。
2、在接口所在的包中定义mapper.xml,并且要求xml文件和interface的名称要相同。
3、在mybatis-config.xml 中通过class路径,引入mapper(注解方式)。要求mapper.xml 中的名称空间是类的接口的全路径。

  • 注解方式
<mappers><mapper resource="mappers/MyMapper.xml" /><mapper resource="mappers/UserDaoMapper.xml" /><!--<mapper resource="mappers/UserMapper.xml" />--><!--注解方式可以使用如下配置方式--><mapper class="cn.ssm.service.UserMapper"/>
</mappers>

问题:
1、mapper.xml 和 java文件没有分离。 之后的教程讲述和spring整合之后解决。
2、需要一个一个的去加载mapper。
当然也可以使用包扫描(必须使用注解方式,即在接口方法上使用注解,如@Select("select * from tb_user ")):
缺点:
1、如果包的路径有很多?
2、mapper.xml和mapper.java没有分离。
spring整合的时候解决。

9.Mapper XML文件详解

9.1.CRUD标签

  • 9.1.1.select
select – 书写查询sql语句
select中的几个属性说明:
id属性:当前名称空间下的statement的唯一标识。必须。要求id和mapper接口中的方法的名字一致。
resultType:将结果集映射为java的对象类型。必须(和 resultMap 二选一)
parameterType:传入参数类型。可以省略
  • 9.1.2.insert
nsert 的几个属性说明:
id:唯一标识,随便写,在同一个命名空间下保持唯一,使用动态代理之后要求和方法名保持一致
parameterType:参数的类型,使用动态代理之后和方法的参数类型一致
useGeneratedKeys:开启主键回写
keyColumn:指定数据库的主键
keyProperty:主键对应的pojo属性名
标签内部:具体的sql语句。
  • 9.1.3.update
id属性:当前名称空间下的statement的唯一标识(必须属性);
parameterType:传入的参数类型,可以省略。
标签内部:具体的sql语句。
  • 9.1.4.delete
delete 的几个属性说明:
id属性:当前名称空间下的statement的唯一标识(必须属性);
parameterType:传入的参数类型,可以省略。
标签内部:具体的sql语句。

9.2.#{}和${}

场景:数据库有两个一模一样的表。历史表,当前表
查询表中的信息,有时候从历史表中去查询数据,有时候需要去新的表去查询数据。
希望使用1个方法来完成操作。

	<!--1.#{},预编译的方式preparedstatement,使用占位符替换,防止sql注入,一个参数的时候,任意参数名可以接收2.${},普通的Statement,字符串直接拼接,不可以防止sql注入,一个参数的时候,必须使用${value}接收参数--><select id="queryUserByTableName" resultType="User">select * from ${tableName}</select>/*** 根据表名查询用户信息(直接使用注解指定传入参数名称)* @param tableName* @return*/public List<User> queryUserByTableName(@Param("tableName") String tableName);

http://chatgpt.dhexx.cn/article/pJRjgT3F.shtml

相关文章

SpringBoot使用Mybatis教程

文章目录 新建SpringBoot项目引入mybatis依赖如何使用mybatis&#xff1f;1.配置mybatis①.数据库配置②.mybatis相关配置 2.使用mybatis①.创建JavaBean②.创建mapper1).使用注解方式2&#xff09;.使用xml方式 ③.调用 新建SpringBoot项目 本文所使用的代码编辑器为IntelliJ…

MyBatis教程看这一篇就够啦,简单又全面(IDEA版)

目录 一、MyBatis简介 1.1 MyBatis介绍 为什么需要Mybatis&#xff1f; 二、MyBatis框架部署 2.1 创建Maven项目 2.2 在项目中添加MyBatis依赖 2.3 创建MyBatis配置文件 三、MyBatis框架使用 3.1 创建数据表 3.2 创建实体类 3.3 创建DAO接口&#xff0c;定义操作方法 …

MyBatis学习--完整教程

文章目录 MyBatis1、简介1.1 什么是Mybatis1.2 持久化1.3 持久层1.4 为什么需要MyBatis 2、第一个Mybatis程序2.1 搭建环境2.2 创建一个模块2.3 编写代码 3、CURD1. namespace2. select3. Insert4. update5. Delete6. 万能Map7. 模糊查询 4、配置解析1. 核心配置文件2. 环境配置…

mybatis详细教程

文章目录 [toc]1. 概述1.1 什么是Mybatis?1.2 Mybatis 操作数据库的方式1.3 Mybatis 操作数据库的七大步骤?1.4 Mybatis 的开发优点 2. Mybatis 操作数据库具体实现2.1 创建一个数据库表2.2 创建一个maven项目,配置pom.xml文件,导入相关依赖2.3 创建mybatis 核心配置文件2.4 …

MyBatis教程(看这一篇就够了)

一.全面了解Mybatis 环境变量 jdk 8 MySQL 8.0.27maven-3.6.1IDEA 2021.2.2 学习前需要掌握&#xff1a; JDBCMySQLJava基础MavenJunit&#xff08;单元测试&#xff09; 什么是MyBatis Myba是一款优秀的持久层框架MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及…

fsck命令使用

由于错误操作Linux导致系统无法正常开机&#xff0c;系统提示需要checking filesystems。如下图所示&#xff1a; 根据图中提示&#xff0c;先输入root用户密码进入root用户&#xff0c;然后在root用户中执行命令&#xff1a; fsck -f -y /dev/sda2 命令解释&#xff1a; fsc…

linux基本功之fsck命令详解

&#x1f493; 大家好&#xff0c;我是沐风晓月&#xff0c;双一流院校英语计算机双专业在读&#xff1b; &#x1f493; 想要学好Linux&#xff0c;命令是基本功&#xff0c;企业中常用的命令大约200多个&#xff0c;不管是写shell脚本还是管理操作系统&#xff0c;最常用的命…

fsck命令详解

fsck命令来自于英文词组“filesystem check”的缩写&#xff0c;其功能是用于检查与修复文件系统。若系统有过突然断电或磁盘异常的情况&#xff0c;建议使用fsck命令对文件系统进行检查与修复&#xff0c;以防数据丢失。 语法格式&#xff1a;fsck [参数] 文件系统 常用参…

hdfs fsck

转载来自&#xff1a;https://blog.csdn.net/zlfing/article/details/78070951 1.常用指令&#xff1a;打印文件块的位置信息 hdfs fsck /user/hadoop/wkz -files -blocks -locations生产实例&#xff1a;hdfs fsck *文件路径* -list-corruptfileblocks 线上环境降副本后&a…

Linux fsck 机制解析

Linux fsck 机制 0. 概述1. Upstart 方式 (ubuntu 14.04 32bit)1.1 配置fsck启动1.2 配置fsck运行参数1.3 mountall.config1.4 mountall1.5 fsck 2. Systemd 方式 (ubuntu 16.04 64bit)2.1 普通分区的fsck2.2 Root分区的fsck2.3 ext文件系统的限制2.4 强制fsck完整扫描2.5 fsck…

fsck异常

ubuntu 18 开机显示错误。&#xff08;完了&#xff0c;我的数据啊&#xff09; 莫慌&#xff01;&#xff01;&#xff01; 仔细看下报错。 原因大概是上次系统异常断电关机等非正常关机导致 磁盘损坏。 解决方法 fsck -y /dev/sdb6 sdb6为损坏的目标磁盘 修复完 重启就可以了…

Linux磁盘修复命令----fsck

linux下文件信息出现乱码&#xff0c;无法启动服务&#xff0c;也无法删除&#xff0c;改权限等等&#xff0c;那证明你的磁盘已损坏&#xff0c;需要修复&#xff0c;期间不会丢失数据&#xff0c;请放心操作 使用fsck命令修复磁盘时 一定要进入单用户模式去修复 语 法 fsck.…

fsck-磁盘修复工具

1、简介 fsck&#xff08;file system check&#xff09;用来检查和维护不一致的文件系统。若系统掉电或磁盘发生问题&#xff0c;可利用fsck命令对文件系统进行检查。 2、参数介绍 -a&#xff1a;自动修复文件系统&#xff0c;不询问任何问题&#xff1b;-A&#xff1a;依照/e…

linux命令中fsck命令 – 检查并修复Linux文件系统

fsck命令的英文全称是“filesystem check”&#xff0c;即检查文件系统的意思&#xff0c;常用于检查并修复Linux文件系统的一些错误信息&#xff0c;操作文件系统需要先备份重要数据&#xff0c;以防丢失。 Linux fsck命令用于检查并修复Linux文件系统&#xff0c;可以同时检…

压缩感知超分辨技术

1.技术原理 利用被测物体在时间、空间以及深度&#xff08;或在相应的变换域&#xff09;内的稀疏性&#xff0c;对信号进行少量的编码测量&#xff0c;而后利用重建算法还原原始信号。 实质&#xff1a;有限系统带宽下提升信息量 1.空间编码—超空间分辨率 优势&#xff1a…

压缩感知介绍

Nyquist采样定理&#xff08;香农采样定理&#xff09;指出&#xff0c;采样速率达到信号带宽的两倍以上时&#xff0c;才能由采样信号精确重建原始信号。可见&#xff0c;带宽是Nyquist采样定理对采样的本质要求。然而随着人们对信息需求量的增加&#xff0c;携带信息的信号带…

压缩感知笔记

压缩感知笔记 CS理论认为&#xff0c;我们可以从比奈奎斯特采样所需的更少的样本中恢复某些信号。如果信号在原始域或变换域中是稀疏的&#xff08;完全恢复&#xff09;或可压缩的&#xff08;近似恢复&#xff09;&#xff0c;我们可以用比奈奎斯特采样所需的更少的采样样本…

压缩感知高斯测量矩阵matlab,压缩感知的常见测量矩阵

题目:压缩感知的常见测量矩阵 下面首先给出十篇参考文献中有关测量矩阵的叙述,然后以一篇硕士论文中对七种常见测量矩阵的描述依据,给出了这七种常见测量矩阵的MATLAB实现代码,以为以后的研究提供一个参考,由于目前还没有一个简单有效的测量矩阵评价方法,因此这里给出的七…

压缩感知算法_CEALeti研发出基于压缩感知的CMOS图像传感器

据麦姆斯咨询报道&#xff0c;法国原子能委员会电子与信息技术实验室(CEA-Leti)近日发表了Wissam Benjilali的博士论文&#xff0c;题为“Exploring analog-to-information CMOS image sensor design taking advantage on recent advances of compressive sensing for low-powe…