????????MyBatis 是一款优秀的持久层框架,它支持定制化?SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的?POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。
mybatis特点
简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件。易于学习,易于使用。通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
提供映射标签,支持对象与数据库的ORM字段关系映射。
提供对象关系映射标签,支持对象关系组建维护。
提供xml标签,支持编写动态sql。
在本次案例中,我们使用 mybatis 实现对 MySQL 数据库的增删改查操作
? ? ? ? 下面是本次实验的项目目录,其中下方是我们的数据库表?
? ? ? ? 新建一个名字为 demo 的 MySQL 数据库,并且运行下列代码创建一张表,在表内随意增添数据
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(20) DEFAULT NULL,
`password` varchar(20) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`gender` char(1) DEFAULT NULL,
`email` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=utf8;
? ? ? ? 在该文件中,导入依赖如下
<dependencies>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!-- Mybatis核心 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.13</version>
</dependency>
<!-- log4j日志 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
1)jdbc.properties 配置文件
? ? ? ? 配置数据的url,账号和密码等?
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=123456
2)log4j.properties 配置文件
????????配置日志文件的相关参数
log4j.rootLogger=DEBUG,stdout
# MyBatis logging configuration...
# MyBatis
log4j.logger.com.example.test.datasource.mappers.UserMapper=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
3)mybatis-config.xml 配置文件
? ? ? ? 这个是 mybatis 的配置文件,其中文件名是固定的,不能修改,否则会报错
<?xml version="1.0" encoding="UTF-8" ?>
<!--MyBatis DTD文档约束-->
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--
mybatis核心配置文件中的标签必须要按照指定的顺序配置
properties?,settings?,typeAliases?,
typeHandlers?,objectFactory?,
objectWrapperFactory?,reflectorFactory?,
plugins?,environments?,
databaseIdProvider?,mappers?
-->
<!-- 引入properties文件,此后就可以在当前文件中使用${key}的方式访问value-->
<properties resource="jdbc.properties"/>
<!--
typeAliases类型别名
设置类型别名,即为某个具体的类型设置一个别名
在Mybatis范围中,就可以使用别名表示一个具体的类型
-->
<typeAliases>
<!--
type:设置需要起别名的类型
alias:设置某个类型的别名
如果没有设置alias,当前的类型就拥有默认的别名,即类名且不区分大小写
-->
<typeAlias type="com.example.test.datasource.entities.User" alias="User"/>
<!--通过包类设置类型别名,指定包下所有的类型将全部拥有默认的别名,即类名且不区分大小写-->
</typeAliases>
<!-- environments:配置连接数据库的环境
default:设置默认使用的环境的id
属性:
id:设置环境的唯一标识,不能重复
-->
<!--在MyBatis中可以配置多套环境,然后通过default来控制采用哪套环境,让配置变得灵活-->
<environments default="development">
<environment id="development">
<!-- transactionManager:设置事务管理器-->
<!-- 属性:-->
<!-- type:设置事务管理的方式-->
<!-- type="JDBC|MANAGED-->
<!-- JDBC:表示使用JDBC原生的事务管理方式-->
<!-- MANAGED:被管理,例如spring-->
<!--采取JDBC方式对数据库事务进行commit/rollback-->
<transactionManager type="JDBC"/>
<!-- dataSource:设置数据源
属性:
type:设置数据源类型
type="POOLED|UNPOOLED|JNDI"
POOLED:表示使用数据库连接池
UNPOOLED:表示不是要给你数据库连接池
JNDI:表示使用上下文中的数据源
-->
<!--采用连接池方式管理数据库连接-->
<dataSource type="POOLED">
<!--数据库驱动-->
<property name="driver" value="${jdbc.driver}"/>
<!--IP、端口、库、字符集-->
<!--需要注意的是&在XML中是有意义的,需要使用amp;进行转义-->
<property name="url" value="${jdbc.url}"/>
<!--用户名和密码-->
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
<!-- 比如下面这个就是另一种环境,不过我们在本次实验中没有使用到 -->
<environment id="prod">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://148.70.251.110:3306/babytun?useUnicode=yes&characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="931548241"/>
</dataSource>
</environment>
</environments>
<!-- 引入mybatis的映射文件-->
<mappers>
<mapper resource="mappers/User.xml"/>
</mappers>
</configuration>
4)mappers.User.xml 映射文件
? ? ? ? 该文件是映射文件,这里需要注意的是,映射文件的 id 需要和前面的接口文件名称保持一致
<?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="com.example.test.datasource.mappers.UserMapper">
<!-- namespace需和UserMapper映射接口全类名保持一致 -->
<!--
mapper接口和映射文件要保证两个一致
1、mapper接口的全类名和映射文件的namespace一致
2、mapper接口中的方法名要和映射文件中的sql的id保持一致
parameterType:传入数据的类型
resultType:返回结果类型(这里返回list,mybatis会自动转成User的集合类型)
${value}:对于字符串拼接中的占位符,必须用value
#{ss}:普通占位符,ss和任意取
parameterType="User" 值User对应配置文件typeAlias设置的别名
-->
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id" parameterType="User">
insert into t_user value (#{id}, #{username}, #{password}, #{age}, #{gender}, #{email})
</insert>
<update id="updateUser">
update t_user
<set>
<if test="user.username != null">username=#{user.username},</if>
<if test="user.password != null">password=#{user.password},</if>
<if test="user.age != null">age=#{user.age},</if>
<if test="user.gender != null">gender=#{user.gender},</if>
<if test="user.email != null">email=#{user.email}</if>
</set>
<trim prefix="where" prefixOverrides="AND |OR ">
<if test="userCondition.id != null">id=#{userCondition.id}</if>
<if test="userCondition.username != null">AND username=#{userCondition.username}</if>
<if test="userCondition.password != null">AND password=#{userCondition.password}</if>
<if test="userCondition.age != null">AND age=#{userCondition.age}</if>
<if test="userCondition.gender != null">AND gender=#{userCondition.gender}</if>
<if test="userCondition.email != null">AND email=#{userCondition.email}</if>
</trim>
</update>
<delete id="deleteById">
delete
from t_user
where id = #{id};
</delete>
<select id="queryAll" resultType="User">
select * from t_user
</select>
<select id="queryAllByIds">
select * from t_user where id in
<foreach collection="array" item="item" index="index" open="(" separator="," close=")">
#{item}
</foreach>
</select>
<select id="queryAllByIds2">
select * from t_user
<foreach collection="list" item="item" index="index" open=" where id in(" separator="," close=")">
#{item}
</foreach>
</select>
<select id="queryAllByIds3">
select * from t_user
<foreach collection="listIds" item="item" index="index" open=" where id in(" separator="," close=")">
#{item}
</foreach>
</select>
<select id="queryByAge">
select * from t_user where age > #{age}
</select>
</mapper>
? ? ? ? 这个类是我们的实体类,和数据库的每一个属性相对应。并且提供 get 和 set 方法。?
package com.example.test.datasource.entities;
public class User {
private Long id;
private String username;
private String password;
private Integer age;
private String gender;
private String email;
public User(){}
public User(String username, String password, Integer age, String gender, String email) {
this.username = username;
this.password = password;
this.age = age;
this.gender = gender;
this.email = email;
}
public Long getId() {
return id;
}
public void setId(Long 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;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
", email='" + email + '\'' +
'}';
}
}
? ? ? ? 这里和前面的配置文件名称需要保持一致?
package com.example.test.datasource.mappers;
import com.example.test.datasource.entities.User;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
import java.util.Map;
public interface UserMapper {
int insertUser(User user);
int updateUser(@Param("user") User user, @Param("userCondition") User userCondition);
int deleteById(int id);
List<User> queryAll();
List<User> queryAllByIds(Integer[] ids);
List<User> queryAllByIds2(List<Integer> list);
List<User> queryAllByIds3(Map<String, Object> mapIds);
List<User> queryByAge(Integer age);
@Select("select * from t_user")
List<User> queryAll2();
/**
* 使用注解传递多个参数
*/
@Select("select ${fields} from t_user where id = #{id}")
User queryById(@Param("id") int id, @Param("fields") String fields);
}
package com.example.test.datasource.service;
import com.example.test.datasource.entities.User;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
import java.util.Map;
public interface UserService {
int insertUser(User user);
int updateUser(User user, User userCondition);
int deleteById(int id);
List<User> queryAll();
List<User> queryAllByIds(Integer[] ids);
List<User> queryAllByIds2(List<Integer> list);
List<User> queryAllByIds3(Map<String, Object> mapIds);
List<User> queryAll2();
User queryById(int id, String fields);
List<User> queryByAge(Integer age);
}
package com.example.test.datasource.service;
import com.example.test.datasource.entities.User;
import com.example.test.datasource.mappers.UserMapper;
import java.util.List;
import java.util.Map;
public class UserServiceImpl implements UserService {
public UserMapper userMapper;
public UserServiceImpl(UserMapper userMapper){
this.userMapper = userMapper;
}
@Override
public int insertUser(User user) {
return userMapper.insertUser(user);
}
@Override
public int updateUser(User user, User userCondition) {
return userMapper.updateUser(user, userCondition);
}
@Override
public int deleteById(int id) {
return userMapper.deleteById(id);
}
@Override
public List<User> queryAll() {
return userMapper.queryAll();
}
@Override
public List<User> queryAllByIds(Integer[] ids) {
return userMapper.queryAllByIds(ids);
}
@Override
public List<User> queryAllByIds2(List<Integer> list) {
return userMapper.queryAllByIds2(list);
}
@Override
public List<User> queryAllByIds3(Map<String, Object> mapIds) {
return userMapper.queryAllByIds3(mapIds);
}
@Override
public List<User> queryAll2() {
return userMapper.queryAll2();
}
@Override
public User queryById(int id, String fields) {
return userMapper.queryById(id, fields);
}
@Override
public List<User> queryByAge(Integer age){
return userMapper.queryByAge(age);
}
}
? ? ? ? 该方法是我们的执行方法,并且定义了增删改查等方法,在实际开发中,我们是需要将其拆分定义到 dao 中的
package com.example.test;
import com.example.test.datasource.entities.User;
import com.example.test.datasource.mappers.UserMapper;
import com.example.test.datasource.service.UserServiceImpl;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.jdbc.SQL;
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;
import java.text.SimpleDateFormat;
import java.util.*;
@SuppressWarnings("all")
public class App
{
/** 下面是初始化这些公共参数 */
static String resource = "mybatis-config.xml";
static InputStream inputStream;
static {
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
static SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
public static void main( String[] args ) throws IOException {
App app = new App();
// app.select1();
app.queryByAge();
}
/** 查询1*/
public static void select1() throws IOException {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
UserServiceImpl userService = new UserServiceImpl(sqlSession.getMapper(UserMapper.class));
List<User> users = userService.queryAll();
System.out.println(users);
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
/** 查询2*/
public static void select2() throws IOException {
// String resource = "mybatis-config.xml";
// InputStream inputStream = Resources.getResourceAsStream(resource);
// SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
UserServiceImpl userService = new UserServiceImpl(sqlSession.getMapper(UserMapper.class));
User user = userService.queryById(1, "id,username");
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
/** 根据年龄查询,大于18岁*/
public static void queryByAge() throws IOException {
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
UserServiceImpl userService = new UserServiceImpl(sqlSession.getMapper(UserMapper.class));
List<User> user = userService.queryByAge(18);
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
/** 插入*/
public static void insert() throws IOException {
// String resource = "mybatis-config.xml";
// InputStream inputStream = Resources.getResourceAsStream(resource);
// SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// SqlSession sqlSession = sqlSessionFactory.openSession(true); //加上参数true,会自动提交事务
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
UserServiceImpl userService = new UserServiceImpl(sqlSession.getMapper(UserMapper.class));
User user = new User("小石头", "123456789", 21, "男", "123456789@qq.com");
int res = userService.insertUser(user);
// 提交事务
sqlSession.commit();
System.out.println((res == 0 ? "新增失败" : "新增成功") + " 自增id=" + user.getId());
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
/** 更新*/
public static void update() throws IOException {
// String resource = "mybatis-config.xml";
// InputStream inputStream = Resources.getResourceAsStream(resource);
// SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
try (SqlSession sqlSession = sqlSessionFactory.openSession(true)) {
UserServiceImpl userService = new UserServiceImpl(sqlSession.getMapper(UserMapper.class));
User condition = userService.queryById(1, "id,username,email");
// 更新字段
User user = new User();
user.setEmail("newEmail@qq.com");
int res = userService.updateUser(user, condition);
System.out.println((res == 0 ? "更新失败" : "更新成功") + " res=" + res);
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
/** 删除*/
public static void delete() throws IOException {
// String resource = "mybatis-config.xml";
// InputStream inputStream = Resources.getResourceAsStream(resource);
// SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
try (SqlSession sqlSession = sqlSessionFactory.openSession(true)) {
UserServiceImpl userService = new UserServiceImpl(sqlSession.getMapper(UserMapper.class));
int res = userService.deleteById(1);
System.out.println((res == 0 ? "删除失败" : "删除成功") + " res=" + res);
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}
? ? ? ? 这里我们执行的是第一个查询全部的方法,效果如下:
? ? ? ? mybatis 是目前开发中,连接数据较为常用的技术栈,已经逐步开始替代 jdbc ,因此我们要熟练地掌握 mybatis 对数据库的增删改查等操作。当然?mybatis 也可以使用注解进行开发,不过使用注解开发无法解决较为复杂的处理逻辑,因此,本案例是使用的 xml 完成案例实践。好啦本文就到此为止啦,希望能够对各位小伙伴有所帮助哦!