1.1 MyBatis介绍
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis,实质上Mybatis对ibatis进行一些改进。 现在托管到gitHub上,下载:https://github.com/mybatis/mybatis-3/releases
MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。
Mybatis可以将向 preparedStatement中的输入参数自动进行输入映射,将查询结果集灵活映射成java对象。(输出映射)
1.2 Mybatis框架执行流程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N9fmXA6E-1669618379614)(assets/image-20220804224841305.png)]
- 读取MyBatis 配置文件mybatis-config.xml,加载数据源、事务等
- 加载映射文件mapper.xml
- 定义SQL语句,在上一步的文件中加载。
- 创建会话工厂。(SqlSessionFactory)
- 创建会话(SqlSession)
- 通过Executor 操作数据库
- 输入参数和输出结果
2. Mybatis 入门程序
2.1 需求
根据用户id(主键)查询用户信息
根据用户名称模糊查询用户信息
添加用户
删除用户
更新用户
2.2 环境搭建
sql语句:
CREATE TABLE tb_user(
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(20),
password VARCHAR(50),
sex VARCHAR(2),
brithday DATE,
address VARCHAR(200)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
log4j.properties
#在开发阶段使用debug,在生产环境设置为info或者error
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 %p [%c] - %m%n
添加如下依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.suke</groupId>
<version>1.0-SNAPSHOT</version>
<artifactId>mybatis-demo1</artifactId>
<!--添加mybatis的依赖-->
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<!--mysql的数据库驱动jar-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<!--log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
</project>
2.3 Mybatis的主配置文件 mybatis-config.xml
mybatis-config.xml主要用来配置mybatis的运行环境,数据源、事务等。
在classpath下创建mybatis-config.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>
<!-- 和spring整合后 environments配置将废除-->
<environments default="development">
<!-- 可以配置多个environment -->
<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/shopdb" />
<property name="username" value="root" />
<property name="password" value="123" />
</dataSource>
</environment>
</environments>
</configuration>
2.4 根据用户id(主键)查询用户信息
编写User实体类
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
public class User{
//实例类的属性的数据类型写包装类型
private Integer userId;
private String name;
private String password;
private String sex;
//实体类的日期类型一定使用java.util.Date
private Date brithday;
private String address;
}
2.5 sql映射文件
映射文件命名:
User.xml(原始ibatis命名),mapper代理开发映射文件名称叫XXXMapper.xml,比如:UserMapper.xml、ItemsMapper.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">
<!-- namespace命名空间,作用就是对sql进行分类管理
注意:使用mapper代理方法开发时,namespace需要特殊设置
-->
<mapper namespace="test">
</mapper>
在UserMapper.xml中添加sql语句
<!-- 根据id获取用户信息 -->
<select id="findUserById" parameterType="int" resultType="org.csmf.mybatis.entity.User">
select * from t_user where id = #{id}
</select>
parameterType:定义输入到sql中的映射类型,#{id}表示使用preparedstatement设置占位符号并将输入变量id传到sql。
resultType:定义结果映射类型。
2.6 将sql映射文件添加到MyBatis主配置文件中
mybatis框架需要加载映射文件,将UserMapper.xml添加到mybatis-config.xml中
<mappers>
<mapper resource="UserMapper.xml"/>
</mappers>
2.7 测试程序
import java.io.IOException;
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 org.csmf.mybatis.entity.User;
import org.junit.Test;
/**
* 测试使用Mybatis操作数据库
* @author pactera
*
*/
public class UserDaoTest {
@Test
public void testFindUserById(){
InputStream inputStream = null;
try {
//0.加载Mybatis的主配置文件
// Resources.getResourceAsStream()获取classpath下面的资源
inputStream = Resources.getResourceAsStream("mybatis-config.xml");
} catch (IOException e) {
e.printStackTrace();
}
//1.通过Mybatis的主配置文件得到SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//2.通过SqlSessionFactory得到SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//3.通过SqlSession操作数据库
//selectOne():
//第一个参数是Statement的Id也就是sql映射文件中的select,insert,,标签的Id
//第二个参数是输入参数
User user = sqlSession.selectOne("findUserById",2);
//输出
System.out.println(user.getUsername()+"-->"+user.getBrithday());
//4.关闭SqlSession
sqlSession.close();
}
}
2.8 根据用户姓名模糊查询
<!-- 根据姓名模糊查询 -->
<select id="findUserByName" parameterType="string" resultType="org.csmf.mybatis.entity.User">
select * from tb_user where username like #{name}
</select>
2.9 添加用户
<!-- 添加用户 -->
<!--
parameterType: 输入参数为Java对象类型
如果输入参数为java对象类型 #{}中只能写的是Java对象的属性名,不能随意写
注意:如果主键是自增长,不能手动赋值
-->
<insert id="addUser" parameterType="org.csmf.mybatis.entity.User">
insert into tb_user(username,password, sex,birthday, address)
values(#{username},#{password},#{sex},#{brithday},#{address})
</insert>
如果想得到自增列产生的id值,我们可以进行如下配置:
<insert id="insert">
<selectKey resultType="int" order="AFTER" keyProperty="id">
SELECT LAST_INSERT_ID()
</selectKey>
insert into tb_userinfo(name,gender,age,address,email,qq,photo)
values(#{name,jdbcType=VARCHAR},#{gender,jdbcType=VARCHAR},#{age,jdbcType=INTEGER},#{address,jdbcType=VARCHAR}
,#{email,jdbcType=VARCHAR},#{qq,jdbcType=VARCHAR},#{photo,jdbcType=VARCHAR})
</insert>
SELECT LAST_INSERT_ID()
查询生成的id的值,但是需要注意该sql语句必须要与insert的sql语句位于同一次会话中,不然查询不到数据
测试代码
//测试添加用户
@Test
public void testAddUser() throws ParseException{
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream("mybatis-config.xml");
} catch (IOException e) {
e.printStackTrace();
}
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setUsername("suke");
user.setAddress("深圳");
user.setPassword("123");
user.setSex("男");
//使用SimpleDateFormat把指定格式的字符串转换为日期
// 1992-10-12
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
user.setBrithday(fmt.parse("1992-10-12"));
sqlSession.insert("test.addUser", user);
//提交事务
sqlSession.commit();
//关闭SqlSession
sqlSession.close();
}
2.10 修改用户
<!-- 修改用户 -->
<update id="updateUser" parameterType="org.csmf.mybatis.entity.User">
update t_user set username=#{username},password=#{password},sex=#{sex},
brithday=#{brithday},address=#{address} where id=#{id}
</update>
测试代码:
// 测试修改用户
@Test
public void testUpdateUser() throws ParseException {
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream("mybatis-config.xml");
} catch (IOException e) {
e.printStackTrace();
}
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setId(15);
user.setUsername("王五");
user.setAddress("长沙");
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
user.setBrithday(fmt.parse("1991-11-12"));
user.setPassword("123");
user.setSex("男");
//修改
sqlSession.update("updateUser", user);
// 提交事务
sqlSession.commit();
// 关闭SqlSession
sqlSession.close();
}
2.11 总结
2.11.1 #{}
与${}
区别
#{}表示一个占位符号,#{}接收输入参数,类型可以是简单类型,pojo、hashmap。
如果接收简单类型,#{}中可以写成value或其它名称。
#{}接收pojo对象值,通过OGNL读取对象中的属性值,通过属性.属性.属性…的方式获取对象属性值。
${}
表示一个拼接符号,会引用sql注入,所以不建议使用${}。${}接收输入参数,类型可以是简单类型,pojo、hashmap。
如果接收简单类型,#{}中可以写成value或其它名称。
${}接收pojo对象值,通过OGNL读取对象中的属性值,通过属性.属性.属性…的方式获取对象属性值。
2.11.2 parameterType和resultType
parameterType:指定输入参数类型,mybatis通过ognl从输入对象中获取参数值拼接在sql中。
resultType:指定输出结果类型,mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象。
2.11.2 selectOne和selectList
selectOne查询一条记录
selectList可以查询一条或多条记录。
Mybatis是选择selectOne还是selectList是看返回值来解决,如果返回的一个对象,则使用selectOne,返回一个集合则使用selectList
如果使用selectOne查询多条记录则抛出异常:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NzQovCP6-1669618379620)(assets/image-20220804233927454.png)]