简介
什么是MyBatis?
- MyBatis 是一款优秀的持久层框架
- 它支持定制化 SQL、存储过程以及高级映射。
- MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
- MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
- MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。
- 2013年11月迁移到Github。
如何使用MyBatis
- 新建一个maven项目
- 导入MyBatis的jar包:自己下载jar包放在lib目录,或者在pom.xml中引入依赖
- 导入数据库(mysql)的jar包:自己下载jar包放在lib目录,或者在pom.xml中引入依赖
- MyBatis和MySQL的在pom.xml中的依赖:
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
- Github中MyBatis的下载地址 : https://github.com/mybatis/mybatis-3/releases
- MyBatis的中文文档:https://mybatis.org/mybatis-3/zh/index.html
持久化
数据持久化
- 持久化就是将程序的数据在持久状态和瞬时状态转化的过程
- 内存:断电即失
- 数据库(JDBC),IO文件持久化
为什么要持久化
- 有一些对象,不能让他丢掉。(特别重要)
- 内存太贵了
持久层
Dao层,Service层,Controller层(控制层)….
- 完成持久化工作的代码块
- 层界限十分明显。(层与层之间的功能是分开的,降低代码的耦合度)
为什么需要MyBatis?
- 帮助程序猿将数据存入到数据库中
- 方便
- 传统的JDBC代码太复杂了
- MyBatis优点:
- 简单易学
- 灵活
- sql和代码的分离,提高了可维护性
- 提供映射标签,支持对象与数据库的orm字段关系映射
- 提供对象关系映射标签,支持对象关系组建维护
- 提供xml标签,支持编写动态sql。
第一个Mybatis程序
思路:搭建环境–>导入Mybatis–>编写代码–>测试
1.搭建环境
搭建数据库
CREATE DATABASE `mybatis`;
USE `mybatis`;
CREATE TABLE `user`(
`id` INT(20) NOT NULL PRIMARY KEY,
`name` VARCHAR(30) DEFAULT NULL,
`pwd` VARCHAR(30) DEFAULT NULL
)ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO `user`VALUES
(1,'张三','123456'),
(2,'李四','123456'),
(3,'王五','123890')
新建项目
- 新建一个普通的maven项目
- 删除src目录(使它成为父项目,在它里面新建module就行)
- 导入依赖
<!--导入依赖-->
<dependencies>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!--mybatis-->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
2.创建一个模块
在resources包下编写配置文件:1.db.properties 2.mybatis-config.xml
- 编写mybatis-config.xml配置文件
如下图是configuration里的配置顺序,按顺序设置,可以选择不设置,但是一定得按顺序,不然的话会报错
<?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核心配置文件-->
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper class="org.westos.mapper.userMapper"></mapper>
</mappers>
</configuration>
- 编写db.properties配置文件
driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"
username="root"
password="123456"
- 编写mybatis工具类
在java包下建三个包:1.mapper(里面放实体类的接口和实体类对应的配置文件);2.pojo(里面放数据库得实体类);3.utils(里面放mybatis的工具类)
编写mybatis的工具类,用来获得SqlSession的对象
package org.westos.utils;
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 mybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
try{
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}catch (IOException e){
e.printStackTrace();
}
}
//获取SqlSession对象,SqlSession 完全包含了面向数据库执行 SQL 命令所需的所有方法
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
3.编写代码
- 实体类(pojo包)
package org.westos.pojo;
public class User {
private Integer id;
private String userName;
private String password;
public User() {
}
public User(Integer id, String userName, String password) {
this.id = id;
this.userName = userName;
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", userName='" + userName + '\'' +
", password='" + password + '\'' +
'}';
}
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 String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
- Mapper接口
package org.westos.mapper;
import org.westos.pojo.User;
import java.util.List;
public interface userMapper {
List<User> getUserlist();
Integer addUser(User user);
Integer removeUser(int id);
Integer updateUser(User user);
}
- 接口实现类由原来的UserDaoImpl转变为一个 Mapper配置文件.
<?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="org.westos.mapper.userMapper">
<select id="getUserlist" resultType="org.westos.pojo.User">
select * from mybatis.user
</select>
<insert id="addUser" parameterType="org.westos.pojo.User">
insert into mybatis.user values (#{id},#{userName},#{password})
</insert>
<delete id="removeUser">
delete from mybatis.user where id=#{id}
</delete>
<update id="updateUser" parameterType="org.westos.pojo.User">
update user set id=#{id},userName=#{userName},password=#{password} where id=#{id}
</update>
</mapper>
4.测试
- 注意点:可能会报以下错误
org.apache.ibatis.binding.BindingException: Type interface com.kuang.dao.UserDao is not known to the MapperRegistry. - 解决方法:
核心配置文件中(mybatis-config.xml)注册 mappers
<mappers>
<mapper class="org.westos.mapper.userMapper"></mapper>
</mappers>
- junit测试(利用Test注解测试,前提是在pom.xml里依赖junit)
package org.westos.mapper;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import org.westos.pojo.User;
import org.westos.utils.mybatisUtils;
import java.util.List;
public class userTest {
@Test
public void selectUser(){
SqlSession sqlSession = mybatisUtils.getSqlSession();
userMapper mapper = sqlSession.getMapper(userMapper.class);
List<User> list = mapper.getUserlist();
for (User user : list) {
System.out.println(user);
}
sqlSession.close();
}
@Test
public void addUser(){
SqlSession sqlSession = mybatisUtils.getSqlSession();
userMapper mapper = sqlSession.getMapper(userMapper.class);
Integer result = mapper.addUser(new User(5, "田七", "123456"));
if(result>0){
System.out.println("插入成功...");
}
sqlSession.commit();
sqlSession.close();
}
@Test
public void removeUser(){
SqlSession sqlSession = mybatisUtils.getSqlSession();
userMapper mapper = sqlSession.getMapper(userMapper.class);
Integer result = mapper.removeUser(5);
if(result>0){
System.out.println("删除成功...");
}
sqlSession.commit();
sqlSession.close();
}
@Test
public void updateUser(){
SqlSession sqlSession = mybatisUtils.getSqlSession();
userMapper mapper = sqlSession.getMapper(userMapper.class);
Integer result = mapper.updateUser(new User(4, "奥特曼", "123456"));
if(result>0){
System.out.println("更新成功...");
}
sqlSession.commit();
sqlSession.close();
}
}
在配置文件中进行CRUD操作
- namespace
namespace中的包名要和 Dao/mapper 接口的包名一致!
1. Create new records(编写 Insert 语句)
- 在 mapper 接口中编写增添方法,代码如下:
//增加用户信息
public int add(User user)throws Exception;
- 在 mapper 接口对应的配置文件中编写 Insert 语句,代码如下:
<insert id="add" parameterType="org.westos.pojo.User">
insert into smbms.smbms_user values (#{id},#{userCode},#{userName},#{userPassword},#{gender},#{birthday},#{phone},#{address},#{userRole},#{createdBy},#{creationDate},#{modifyBy},#{modifyDate})
</insert>
- 利用 @Test 注解进行测试
@Test
public void add() throws Exception {
SqlSession sqlSession = mybatisUtils.getSqlSession();
User user = new User(50, "哈哈", "哼哈二将", "123456789", 5, null, "", "", 4, 6, null, 7, null);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int i = mapper.add(user);
if(i>0){
System.out.println("添加用户成功...");
}else {
System.out.println("插入失败...");
}
sqlSession.commit();
sqlSession.close();
}
2. Read existing records(编写 Select 语句)
- 在 mapper 接口中编写查询方法,代码如下:
//通过userCode获取User
public User getLoginUser(@Param("userCode") String userCode)throws Exception;
- 在 mapper 接口对应的配置文件中编写 Select 语句,代码如下:
<select id="getLoginUser" resultType="org.westos.pojo.User">
select * from smbms.smbms_user where userCode=#{userCode}
</select>
- 利用 @Test 注解进行测试
@Test
public void getLoginUser() throws Exception {
SqlSession sqlSession = mybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.getLoginUser("admin");
if (user != null) {
System.out.println(user);
}else {
System.out.println("查无此人...");
}
sqlSession.close();
}
3. Update existing records(编写 Update 语句)
- 在 mapper 接口中编写更新方法,代码如下:
Integer updateUser(User user);
- 在 mapper 接口对应的配置文件中编写 Update 语句,代码如下:
<update id="updateUser" parameterType="org.westos.pojo.User">
update user set id=#{id},userName=#{userName},password=#{password} where id=#{id}
</update>
- 利用 @Test 注解进行测试:
@Test
public void updateUser(){
SqlSession sqlSession = mybatisUtils.getSqlSession();
userMapper mapper = sqlSession.getMapper(userMapper.class);
Integer result = mapper.updateUser(new User(4, "奥特曼", "123456"));
if(result>0){
System.out.println("更新成功...");
}
sqlSession.commit();
sqlSession.close();
}
4. Delete existing records(编写 Delete 语句)
- 在 mapper 接口中编写删除方法,代码如下:
//通过userId删除user
public int deleteUserById(@Param("id") Integer delId)throws Exception;
- 在 mapper 接口对应的配置文件中编写 Delete 语句,代码如下:
<delete id="deleteUserById" parameterType="_int">
delete from smbms.smbms_user where id=#{id}
</delete>
- 利用 @Test 注解进行测试:
@Test
public void deleteUserById() throws Exception {
SqlSession sqlSession = mybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int i = mapper.deleteUserById(50);
if(i>0){
System.out.println("删除成功...");
}else {
System.out.println("删除失败...");
}
sqlSession.commit();
sqlSession.close();
}
5. 编写CRUD时需要注意的问题:
- 配置文件中 CRUD标签 的 id值 对应的是mapper/dao 接口中所对应的方法名
- 编写增删改查代码时,除了查询不需要提交事务,增删改都需要自行提交事务
6. #{} 和 ${} 的区别
- #{} 预编译 ,可以有效的防止sql注入问题
- #{} 编译为占位符 ,相当于JDBC中预编译操作中的 ? 占位符
- #{} 可以自动判断参数类型
- #{} 一个参数时#{}可以使用任意名称接收参数
- ${} 非预编译 ,不可以防止sql注入问题
- ${} 直接进行拼接 ,不会编译成占位符
- ${} 需要自行判断参数类型
- ${} 接受参数时 ,只能用 value 来接受参数
7.万能 Map ,用 Map 接受参数
假设,我们的实体类,或者数据库中的表,字段或者参数过多,我们应当考虑使用Map!
- 在mapper接口中参数类型为Map的方法,代码如下:
//用Map接受参数
int addUser2(Map<String,Object> map);
- 在配置文件中编写对应的代码,代码如下:
<!--对象中的属性,可以直接取出来, #{}里面的参数名为你 map 集合中的键值,通过键值拿到 value 的值-->
<insert id="addUser2" parameterType="map">
insert into mybatis.user (id, pwd) values (#{userid},#{passWord});
</insert>
- 利用 @Test 注解进行测试,代码如下:
@Test
public void addUser2(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Map<String, Object> map = new HashMap<String, Object>();
map.put("userid",5);
map.put("passWord","2222333");
mapper.addUser2(map);
sqlSession.close();
}
- 注意点:
1.Map传递参数,通过键值拿到value的值 ,格式为:#{map集合中的键值}
【parameterType=“map”】
2.对象传递参数,通过pojo(实体类)中的属性名拿到值, 格式为:#{实体类中的属性名}
【parameterType=“pojo中的实体类”】
3.只有一个基本类型参数的情况下,可以直接在sql中取到!
8. 模糊查询
往往我们在查询时,会用到关键字进行查询,而普通的查询语句没有办法做到关键字查询,这时模糊查询就有很大的作用了
- 在mapper接口中编写模糊查询的方法,代码如下:
List<User> fuzzySelect(@Param("fuzzy") String fuzzy);
- 在配置文件中编写对应的代码,代码如下:
<select id="fuzzySelect" resultType="User">
select * from smbms.smbms_user where userName like #{fuzzy}
</select>
- 在main方法中进行测试,代码如下:
public static void main(String[] args) {
SqlSession sqlsession = mybatisUtils.getSqlsession();
userMapper mapper = sqlsession.getMapper(userMapper.class);
Scanner sc = new Scanner(System.in);
System.out.println("请输入模糊查询的字");
String s = sc.nextLine();
List<User> list = mapper.fuzzySelect("%"+s+"%");
if (list.size()!=0) {
for (User user : list) {
System.out.println(user);
}
}else {
System.out.println("没有查询到所匹配的用户信息...");
}
sqlsession.close();
}
- 注意点:
1.参数类型为 String 时,最好加一个注解,就能在配置文件中直接拿到 String 的值。
2.这块用main方法测试而不是 @test 注解测试的原因是用到了 Scanner 键盘录入,键盘录入(Scanner)在 @Test 里面不能使用