Mybatis-入门

目录
显示
文件的目录结构如下(
)下面的代码可以直接复制到你idea上运行,我的详细解释都在代码注释中
第一步: 配置pom依赖
<?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.zuoyueer</groupId>
<artifactId>Mybatis_day_01</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<!--单元测试坐标-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
<scope>runtime</scope>
</dependency>
<!--myBatis坐标-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--日志的坐标-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
</dependencies>
</project>
第二步:创建javaBean和初始化数据库
javaBean如下
package com.zuoyueer.domain;
import java.io.Serializable;
/**
* @author Zuoyueer
* Date: 2019/11/15
* Time: 21:47
* @projectName Framework
* @description: javabean
*/
public class User implements Serializable {
private int uid;
private String username;
private String sex;
private String birthday;
private String address;
//为了篇幅考虑,省略了get/set方法以及toString方法
}
package com.zuoyueer.domain;
import java.io.Serializable;
/**
* @author Zuoyueer
* Date: 2019/11/16
* Time: 10:56
* @projectName Framework
* @description: 条件搜索的javabean封装搜索条件,属性中包含其他javaBean的引用
*/
public class QueryVo implements Serializable {
private int id;
private User user;
private String other;
//为了篇幅考虑,省略了get/set方法以及toString方法
}
数据库脚本如下
CREATE DATABASE mybatis;
USE mybatis;
CREATE TABLE t_user(
uid INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(40),
sex VARCHAR(10),
birthday DATE,
address VARCHAR(40)
);
INSERT INTO `t_user` VALUES (NULL, '张三', '男', '2018-08-08', '北京');
INSERT INTO `t_user` VALUES (NULL, '李四', '女', '2018-08-30', '武汉');
INSERT INTO `t_user` VALUES (NULL, '王五', '男', '2018-08-08', '北京');
## t_user_表是为了测试表的列名和jopo的属性名不一致的情况下怎么处理,所以才创建了t_user_这个表
CREATE TABLE t_user_(
uid_ INT PRIMARY KEY AUTO_INCREMENT,
username_ VARCHAR(40),
sex_ VARCHAR(10),
birthday_ DATE,
address_ VARCHAR(40)
);
INSERT INTO `t_user_` VALUES (NULL, '张三', '男', '2018-08-08', '北京');
INSERT INTO `t_user_` VALUES (NULL, '李四', '女', '2018-08-30', '武汉');
INSERT INTO `t_user_` VALUES (NULL, '王五', '男', '2018-08-08', '北京');
第三步: 写DAO的接口,接口中声明方法
package com.zuoyueer.dao;
import com.zuoyueer.domain.QueryVo;
import com.zuoyueer.domain.User;
import java.util.List;
/**
* @author Zuoyueer
* Date: 2019/11/15
* Time: 21:56
* @projectName Framework
* @description: dao的接口
*/
public interface UserMapper {
/**
* 查询全部用户
*/
List<User> findAll();
/**
* 添加用户
*/
void insert(User user);
/**
* 修改用户
*/
void update(User user);
/**
* 删除用户
*/
void delete(int uid);
/**
* 模糊查询,名字的模糊查询
*/
List<User> findByName(String username);
/**
* 多条件查询 ,复杂条件,条件可选
*/
List<User> findByQueryVo(QueryVo queryVo);
/**
* 获取记录的总数
*/
int countOfAllUser();
/**
* 根据uid条件查询总数
*
* @return
*/
int countOfUserByUid(int uid);
/**
* 根据id和名字查询用户
*/
User findUserByIdAndName(User user);
/**
* 根据id和名字查询,但是数据库中的字段和pojo的属性名不一致
*/
User findUserById(User user);
}
第四步:写配置文件和映射文件
UserMapper接口的映射文件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是命名空间,必须唯一,他的值必须是接口的全权限定类名 -->
<mapper namespace="com.zuoyueer.dao.UserMapper">
<!--
id: 值必须对应接口中的方法名,也是唯一的,
resultType: 表示sql语句的返回类型,值必须是返回类型的权限定类名,
如果是简单数据类型,可以直接写,比如: int, String,Integer等
如果是集合,那么返回类型是该集合的泛型,也就是集合中存储的数据的类型,也是写权限定类名
-->
<!--<select id="findAll" resultType="com.zuoyueer.domain.User">-->
<select id="findAll" resultType="User">
select * from t_user;
</select>
<!--
#{}表示占位符,#{}里面的值是void insert(User user)方法传入参数User对象是属性名
parameterType: 表示规定了insert方法传入参数的类型,也是写权限定类名,如果取了别名,可以用别名
parameterType可以省略不写,省略的不写,#{}里面的值就按照传入的参数对象的属性名
-->
<insert id="insert" parameterType="com.zuoyueer.domain.User">
<!--
下面的整个selectKey表示:将插入数据的主键返回到User对象中的uid属性中
SELECT_LAST_INSERT_ID(): 表示获取最后插入的记录的ID(主键)值,是一个函数
keyProperty: 将得到的主键值,设置到parameterType指定对象的某一个属性里,下面的示例设置到User对象的uid属性里
resultType: 这个很好理解,就是指定执行函数的返回类型,示例是SELECT_LAST_INSERT_ID()的返回类型
order: 指定函数的执行顺序,AFTER表示在insert语句之后执行,还有另外一个值是BEFORE表示在insert语句之前执行
-->
<selectKey resultType="int" keyProperty="uid" order="AFTER">
select last_insert_id()
</selectKey>
insert into t_user values (null,#{username},#{sex},#{birthday},#{address})
</insert>
<!--
因为一个命名空间中id不能重复,否则包错Mapped Statements collection already contains value,于是,我把第二种方式注释起来了
返回主键值的第二种方式: 配置这keyProperty="uid" useGeneratedKeys="true"两个属性.
keyProperty:和上面的意义一样
useGeneratedKeys:设置是否使用JDBC的getGenereatedKeys方法获取主键并赋值到keyProperty设置的领域模型属性中
<insert id="insert" parameterType="com.zuoyueer.domain.User" keyProperty="uid" useGeneratedKeys="true">
insert into t_user values (null,#{username},#{sex},#{birthday},#{address})
</insert>
-->
<update id="update" parameterType="User">
update t_user set username=#{username},sex=#{sex} where uid=#{uid}
</update>
<delete id="delete" parameterType="int">
<!-- #{xxx} 是没有约束的,就是传递来的一个值,使用随便命名,不能为空#{},里面随便写一个名字就行 -->
DELETE FROM t_user WHERE uid = #{xxx}
</delete>
<!-- <select id="findByName" parameterType="String" resultType="User">
select * from t_user where username like #{xxx}
</select>-->
<!--
模糊查询的第二种写法: 使用 '${value}'
注意: '${value}' 是固定写法,{}里不能是其他名字,而且必须用引号引起来,因为mybatis是把这个当字符串处理的
<select id="findByName" parameterType="String" resultType="User">
select * from t_user where username like '${value}'
</select>
-->
<!--
补充一点: '${value}' 因为是字符串,使用可以在前后拼接,比如下面的拼接了 % 号, 那么传参数的时候可以不用再写%了
再补充一点,就是这种写法不安全,因为会引起sql注入漏洞问题
最后补充一点: #{xxx}个${value}的本质区别是,前置是占位符,后者是字符串,两者的sql语句不同
<select id="findByName" parameterType="String" resultType="User">
select * from t_user where username like '%${value}%'
</select>
-->
<select id="findByQueryVo" resultType="User" parameterType="QueryVo">
<!-- 在条件中,我们使用了QueryVo对象的属性user对象,再是user对象是属性uid,使用方法就是和EL表达式类似,属性一直点点点就可以了 -->
select * from t_user where uid > #{user.uid};
</select>
<select id="countOfAllUser" resultType="int">
select count(*) from t_user
</select>
<select id="countOfUserByUid" resultType="int" parameterType="int">
select count(1) from t_user where uid > #{xxx}
</select>
<select id="findUserByIdAndName" resultType="User" parameterType="User">
select * from t_user where uid =#{uid} and username=#{username}
</select>
<!--以上的配置,都是基于数据库中的表的列名和JavaBean的属性名是一样的情况下的,如果不一样,怎么办
我们可以使用resultMap配置
id: 是resultMap的唯一标志,<select>中的resultMap的值就是id的值,表示引用了这个结果集
type: 表示数据库中的数据封装到哪个类中,这里使用了别名User
-->
<resultMap id="findUserByIdResultMap" type="User">
<!--这里面的id是: 查询结果的唯一标志,可以理解为表的主键-->
<id property="uid" column="uid_"/>
<!-- result表示普通返回结果,也就是pojo的属性映射到哪个字段
property: 是User类的属性
column: 是sql查询结果的字段名
-->
<result property="username" column="username_"/>
<result property="sex" column="sex_"/>
<result property="birthday" column="birthday_"/>
<result property="address" column="address_"/>
</resultMap>
<select id="findUserById" resultMap="findUserByIdResultMap" parameterType="User">
select * from t_user_ where uid_ = #{uid} and username_ = #{username}
</select>
</mapper>
全局配置文件 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,typeAliases,environments,mappers,-->
<configuration>
<!--(可选配置)引入外部的properties文件,目的是动态获取properties中的值.-->
<properties resource="jdbc.properties"></properties>
<!--(可选配置)给类型取别名-->
<typeAliases>
<!--定义单个别名, 下面typeAlias的配置表示: 我们在映射文件中,返回类型或参数类型,可以不写权限定类名,而用"user"代替-->
<typeAlias type="com.zuoyueer.domain.User" alias="User"></typeAlias>
<!--批量定义别名,下面的package配置表示: 我们在映射文件中,返回类型或参数类型,如果定义在"name"属性值表示的包里,那么全部都能使用别名带她权限定类名-->
<package name="com.zuoyueer.domain"/>
<!--
如果返回类型或参数类型,是简单数据类型(8中基本数据类型+String+包装类型),可以直接写类名,因为mybatis帮我们取好了别名就是对应的类名
-->
</typeAliases>
<!--(必须配置)配置连接的环境,default表示默认使用哪一个环境-->
<environments default="development">
<!--(必须配置,最少一个)配置一个开发环境,id是随便起名字但是要在environments里唯一-->
<environment id="development">
<!--配置事务,mybatis事务是用jdbc的-->
<transactionManager type="JDBC"></transactionManager>
<!--POOLED是mybatis内置的连接池,如果不使用,就写type="UNPOOLED"-->
<dataSource type="POOLED">
<!--配置链接数据库的必要信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
<!--配置第二个连接环境-->
<environment id="test">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
<!--配置第三个连接环境,我们在这里使用引入的外部properties文件中的属性值-->
<environment id="deploy">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<!--在数据库连接的基本配置中,我们使用了外部properties文件中的属性值,使用方法类似于EL表达式-->
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--(必须配置,里面可以有多个mapper配置项)-->
<mappers>
<!--引入映射文件:这是必须要引入的
resource:是映射文件的路径,注意必须写成"/"不能使用"."
-->
<mapper resource="com/zuoyueer/dao/UserMapper.xml"></mapper>
<mapper resource="com/zuoyueer/dao/UserMapper2.xml"></mapper>
<!--映射文件和接口的名字一致,路径一致,就可以直接引入name属性值表示的包下的全部映射文件-->
<!--<package name="com.zuoyueer.dao"/>-->
<!--mapper和package使用的时候,映射不能重复,否则报错-->
</mappers>
</configuration>
外部引入的属性文件jdbc.properties 名字随便,规范就这样写, 这个外部属性文件,写不写看你的配置文件SqlMapConfig.xml中有没有引入.不引入就可以不写
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.user=root
jdbc.password=123456
第五步:写测试类
package com.zuoyueer;
import com.zuoyueer.dao.UserMapper;
import com.zuoyueer.domain.QueryVo;
import com.zuoyueer.domain.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.scripting.xmltags.TextSqlNode;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* @author Zuoyueer
* Date: 2019/11/15
* Time: 22:39
* @projectName Framework
* @description: 测试类测试UserMapper.xml映射文件
*/
public class MybatisTest {
/*
* mybatis的简单使用步骤:
* 1. 创建maven工程,引入相关坐标
* 2. 创建javaBean,记得实现序列化接口
* 3. 创建UserMapper接口,定义方法,是一些操作数据的方法
* 4. 创建映射文件,该文件在resources中创建
* 5. 创建全局的配置文件SqlMapConfig.xml,最重要的是引入映射文件
* 6. 测试,也就是下面方法里面的内容了
* */
@Test
public void testFindAll() throws IOException {
//读取SqlMapConfig.xml全局配置文件,注意使用了org.apache.ibatis.io.Resources;千万别倒错包了
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
//创建SQLSessionFactory
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(is);
//获取SQLSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取UserMapper代理对象,UserMapper是一个接口,根据接口动态代理获取执行接口的方法
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//使用代理对象调用方法,该方法的具体实现在映射文件UserMapper.xml中.
List<User> list = userMapper.findAll();
System.out.println(list);
//释放资源
sqlSession.close();
is.close();
}
@Test
public void testInsert() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(is);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setUsername("zuoyueer");
user.setSex("男");
user.setBirthday("1996-02-26");
user.setAddress("深圳");
userMapper.insert(user);
sqlSession.commit();
sqlSession.close();
is.close();
/*
如果映射文件中没有以下配置
<selectKey resultType="int" keyProperty="uid" order="AFTER">select last_insert_id()</selectKey>
输出的结果是User{uid=0, username='zuoyueer', sex='男', birthday='1996-02-26', address='深圳'}
加了之后的输出结果是:
User{uid=9, username='zuoyueer', sex='男', birthday='1996-02-26', address='深圳'}
* */
System.out.println(user);
System.out.println(user.getUid());
}
@Test
public void testUpdate() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(is);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setUsername("佐助");
user.setSex("男");
user.setUid(11);
mapper.update(user);
sqlSession.commit();
sqlSession.close();
is.close();
}
@Test
public void testDelete() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(is);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.delete(5);
sqlSession.commit();
sqlSession.close();
is.close();
}
@Test
public void testFindByName() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(is);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> list = mapper.findByName("%三%");
System.out.println(list);
sqlSession.commit();
sqlSession.close();
is.close();
}
@Test
public void testFindByQueryVo() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(is);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setUid(5);
QueryVo queryVo = new QueryVo();
queryVo.setUser(user);
List<User> list = mapper.findByQueryVo(queryVo);
System.out.println(list);
sqlSession.commit();
sqlSession.close();
is.close();
}
@Test
public void testCountOfAllUser() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(is);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int count = mapper.countOfAllUser();
System.out.println(count);
sqlSession.close();
is.close();
}
@Test
public void testCountOfUserByUid() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(is);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int count = mapper.countOfUserByUid(33);
System.out.println(count);
sqlSession.close();
is.close();
}
@Test
public void testFindUserByIdAndName() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(is);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setUid(2);
user.setUsername("李四");
User user2 = mapper.findUserByIdAndName(user);
System.out.println(user2);
sqlSession.close();
is.close();
}
@Test
public void testFindUserById() throws IOException {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(is);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setUid(3);
user.setUsername("王五");
User user2 = mapper.findUserById(user);
System.out.println(user2);
sqlSession.close();
is.close();
}
}
测试类中很多重复代码,我是为了锻炼自己,重复写了这么多遍,如果你觉得烦,可以抽取工具类,或者使用@before注解