MyBatis
分类:
IT文章
•
2025-02-04 16:23:43
一、MyBatis架构与项目搭建


● 导入Jar
数据库驱动包:mysql-connector-java-5.1.46-bin.jar

mybatis核心包:mybatis-3.4.6.jar
mybatis依赖:

● 准备数据库


● db.properties - mysql驱动配置文件(这样可以优化性能)
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/games_db?useUnicode=true&characterEncoding=UTF-8&useSSL=true
jdbc.username=root
jdbc.password=123456
View Code
● 引入log4j.properties文件(测试输出需要)
● 添加mybatis映射配置文件 - sqlMapConfig.xml
配置文件中主要是配置连接数据库和事务管理的内容,文件名可以自定义,默认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 resource="db.properties"></properties>
<!-- 配置别名;推荐使用package包形式来配置别名;包的形式会扫描主包及子包中所有文件;以对象类名为别名,大小写不限,推荐使用小写 -->
<typeAliases>
<!-- <typeAlias type="com.sikiedu.beans.User" alias="user" /> -->
<package name="com.sikiedu.beans" />
</typeAliases>
<!-- 配置mybatis运行环境 ; 在集成Spring是不用 -->
<environments default="development">
<environment id="development">
<!-- type="JDBC" 代表使用JDBC的提交和回滚来管理事务 -->
<transactionManager type="JDBC" />
<!-- 使用连接池连接数据库 - mybatis提供了3种数据源类型,分别是:POOLED,UNPOOLED,JNDI -->
<!-- POOLED 表示支持JDBC数据源连接池 ; UNPOOLED 表示不支持数据源连接池 ; JNDI 表示支持外部数据源连接池 -->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
</environment>
</environments>
<!--配置映射器的位置 -->
<mappers>
<!-- 单个配置 -->
<!-- <mapper resource="com/sikiedu/mapper/UserMapper.xml" /> -->
<!-- <mapper url="file:\D:JavaWorkSpaceJavaEE_SSM_Testssm_mybatissrccomsikiedumapperUserMapper.xml" /> -->
<!-- <mapper class="com.sikiedu.mapper.UserMapper" /> -->
<!-- 多配置-以包的形式;推荐使用 -->
<package name="com.sikiedu.mapper" />
</mappers>
</configuration>
● 创建数据库对应的实体对象

数据库实体对象
1 package com.sikiedu.beans;
2
3 public class Role {
4
5 private Integer id;
6 private String name;
7 private Integer level;
8 private String roletype;
9 private Integer userid;
10
11 public Integer getId() {
12 return id;
13 }
14
15 public void setId(Integer id) {
16 this.id = id;
17 }
18
19 public String getName() {
20 return name;
21 }
22
23 public void setName(String name) {
24 this.name = name;
25 }
26
27 public Integer getLevel() {
28 return level;
29 }
30
31 public void setLevel(Integer level) {
32 this.level = level;
33 }
34
35 public String getRoletype() {
36 return roletype;
37 }
38
39 public void setRoletype(String roletype) {
40 this.roletype = roletype;
41 }
42
43 public Integer getUserid() {
44 return userid;
45 }
46
47 public void setUserid(Integer userid) {
48 this.userid = userid;
49 }
50
51 @Override
52 public String toString() {
53 return "Role [
54 + userid + "]";
55 }
56
57 }
Role.java
1 package com.sikiedu.beans;
2
3 import java.util.Date;
4
5 public class User {
6
7 private Integer id;
8 private String username;
9 private String userpassword;
10 private Float balance;
11 private String grgisterdate;
12
13 public Integer getId() {
14 return id;
15 }
16
17 public void setId(Integer id) {
18 this.id = id;
19 }
20
21 public String getUsername() {
22 return username;
23 }
24
25 public void setUsername(String username) {
26 this.username = username;
27 }
28
29 public String getUserpassword() {
30 return userpassword;
31 }
32
33 public void setUserpassword(String userpassword) {
34 this.userpassword = userpassword;
35 }
36
37 public Float getBalance() {
38 return balance;
39 }
40
41 public void setBalance(Float balance) {
42 this.balance = balance;
43 }
44
45 public String getGrgisterdate() {
46 return grgisterdate;
47 }
48
49 public void setGrgisterdate(String grgisterdate) {
50 this.grgisterdate = grgisterdate;
51 }
52
53 @Override
54 public String toString() {
55 return "User [> balance
56 + ", grgisterdate=" + grgisterdate + "]";
57 }
58
59 }
User.java
Vo为关联查询需要 - 一对一、一对多
1 package com.sikiedu.beans;
2
3 import java.util.List;
4
5 public class RoleVo extends Role {
6
7 private User user;
8 private List<Integer> idList;
9
10 public User getUser() {
11 return user;
12 }
13
14 public void setUser(User user) {
15 this.user = user;
16 }
17
18 public List<Integer> getList() {
19 return idList;
20 }
21
22 public void setList(List<Integer> idList) {
23 this.idList = idList;
24 }
25
26 @Override
27 public String toString() {
28 return "RoleVo [ID=" + getId() + " name=" + getName() + " roletype=" + getRoletype() + " user=" + user
29 + "]";
30 }
31
32 }
RoleVo.java
1 package com.sikiedu.beans;
2
3 import java.util.List;
4
5 public class UserVo extends User {
6 // 维护一个Role集合
7 private List<Role> roleList;
8
9 public List<Role> getRole() {
10 return roleList;
11 }
12
13 public void setRole(List<Role> roleList) {
14 this.roleList = roleList;
15 }
16
17 @Override
18 public String toString() {
19 return "UserVo [ID=" + getId() + " username=" + getUsername() + " Grgisterdate=" + getGrgisterdate()
20 + " role=" + roleList + "]";
21 }
22
23 }
UserVo.java
● 创建方法接口XxxxMapper.java And 定义操作数据表的sql映射文件XxxMapper.xml

创建方法接口 - 提供简单的增删改查数据信息。
1 package com.sikiedu.mapper;
2
3 import java.util.List;
4
5 import com.sikiedu.beans.Role;
6 import com.sikiedu.beans.RoleVo;
7
8 public interface RoleMapper {
9
10 // 查询所有
11 public List<Role> selectAllRole();
12
13 // 通过RoleVo一对一关联查询
14 public List<RoleVo> selectAllRoleVo();
15
16 // 多条件查询 通过角色对象中的条件查询角色表
17 public List<Role> selectRoleListByRole(Role role);
18
19 // 多条件查询 通过角色对象中的条件查询角色表Trim
20 public List<Role> selectRoleListByTrim(Role role);
21
22 // 更新角色表
23 public void updateSetRole(Role role);
24
25 // 使用多个ID获取角色列表 By array
26 public List<Role> selectRoleListByids(Integer[] ids);
27
28 // 使用多个ID获取角色列表 By list
29 public List<Role> selectRoleListByList(List<Integer> idList);
30
31 // 使用多个ID获取角色列表 By RoleVo
32 public List<Role> selectRoleListByRoleVo(RoleVo roleVo);
33
34 }
RoleMapper.java
1 package com.sikiedu.mapper;
2
3 import java.util.List;
4
5 import com.sikiedu.beans.User;
6 import com.sikiedu.beans.UserVo;
7
8 public interface UserMapper {
9
10 // 根据ID查询用户
11 public User selectUserById(Integer id);
12
13 // 根据用户名模糊查询用户
14 public List<User> selectUserLikeUsername(String username);
15
16 // 同过包装类UserVo查询用户
17 public User selectUserByUserVoId(UserVo vo);
18
19 // 查询用户总条数
20 public Integer selectUserCount();
21
22 // 查询所有用户包装类
23 public List<UserVo> selectAllUserVo();
24 }
UserMapper.java
定义操作数据表的sql映射文件
1 <?xml version="1.0" encoding="UTF-8" ?>
2 <!DOCTYPE mapper
3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
5 <mapper namespace="com.sikiedu.mapper.RoleMapper">
6
7 <sql id="myselect">
8 SELECT *
9 FROM role
10 </sql>
11
12 <resultMap type="Role" id="roleRM">
13 <id property="id" column="idrole" />
14 </resultMap>
15 <select id="selectAllRole" resultMap="roleRM">
16 <include refid="myselect"></include>
17 </select>
18
19 <resultMap type="RoleVo" id="roleVo">
20 <id property="id" column="idrole" />
21 <result property="name" column="name" />
22 <result property="level" column="level" />
23 <result property="roletype" column="roletype" />
24 <!-- 一对一关系 -->
25 <association property="user" javaType="User">
26 <id property="id" column="id" />
27 <result property="username" column="username" />
28 </association>
29 </resultMap>
30 <!-- 一对一关联查询 -->
31 <select id="selectAllRoleVo" resultMap="roleVo">
32 SELECT
33 r.idrole,
34 r.name,
35 r.level,
36 r.roletype,
37 u.id,
38 u.username
39 FROM role r
40 LEFT JOIN user u
41 ON r.idrole = u.id
42 </select>
43
44 <!-- 多条件查询 通过角色对象中的条件查询角色表 -->
45 <select id="selectRoleListByRole" parameterType="Role" resultMap="roleRM">
46 <include refid="myselect"></include>
47 <where>
48 <if test="level!=null and level!=''">
49 level = #{level}
50 </if>
51 <if test="roletype!=null and roletype!=''">
52 AND roletype = #{roletype}
53 </if>
54 <if test="userid!=null">
55 AND userid = #{userid}
56 </if>
57 </where>
58 </select>
59
60 <!--多条件查询 通过角色对象中的条件查询角色表Trim -->
61 <select id="selectRoleListByTrim" parameterType="Role" resultMap="roleRM">
62 <include refid="myselect"></include>
63 <trim prefix="WHERE" suffixOverrides="AND">
64 <if test="level!=null and level!=''">
65 level = #{level} AND
66 </if>
67 <if test="roletype!=null and roletype!=''">
68 roletype = #{roletype} AND
69 </if>
70 <if test="userid!=null">
71 userid = #{userid}
72 </if>
73 </trim>
74 </select>
75
76 <!-- 更新角色表 -->
77 <update id="updateSetRole" parameterType="Role">
78 UPDATE role
79 <set>
80 <if test="name != null and name != ''">
81 name = '${name}',
82 </if>
83 <if test="level != null">
84 level = ${level},
85 </if>
86 <if test="roletype != null and roletype != ''">
87 roletype = '${roletype}',
88 </if>
89 <if test="userid != null">
90 userid = ${userid}
91 </if>
92 </set>
93 WHERE
94 idrole = #{id}
95 </update>
96
97 <!-- 使用多个ID获取角色列表 foreach遍历数组 -->
98 <select id="selectRoleListByids" resultMap="roleRM">
99 <include refid="myselect"></include>
100 WHERE idrole IN
101 <foreach collection="array" item="id" open="(" separator="," close=")">
102 ${id}
103 </foreach>
104 </select>
105
106 <!-- 使用多个ID获取角色列表 foreach遍历集合 -->
107 <select id="selectRoleListByList" resultMap="roleRM">
108 <include refid="myselect"></include>
109 WHERE idrole IN
110 <foreach collection="list" item="id" open="(" separator="," close=")">
111 ${id}
112 </foreach>
113 </select>
114
115 <select id="selectRoleListByRoleVo" resultMap="roleRM">
116 <include refid="myselect"></include>
117 WHERE idrole IN
118 <foreach collection="list" item="id" open="(" separator="," close=")">
119 ${id}
120 </foreach>
121 </select>
122
123 </mapper>
RoleMapper.xml
1 <?xml version="1.0" encoding="UTF-8" ?>
2 <!DOCTYPE mapper
3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
5 <mapper namespace="com.sikiedu.mapper.UserMapper">
6
7 <!-- 查询用户 -->
8 <select id="selectUserById" parameterType="Integer" resultType="com.sikiedu.beans.User">
9 SELECT * FROM user WHERE id = #{id}
10 </select>
11 <!-- #{}占位符 尽量选用#{}来解决问题 -->
12 <!-- ${}字符拼接 or1=1 容易被SQL注入 -->
13 <select id="selectUserLikeUsername" parameterType="String" resultType="User">
14 <!-- SELECT * FROM coke.user WHERE username LIKE '%${value}%' -->
15 SELECT * FROM user WHERE username LIKE "%"#{username}"%"
16 </select>
17
18 <!-- 添加用户 -->
19 <insert id="insertUser" parameterType="com.sikiedu.beans.User">
20 INSERT INTO user VALUES(null,#{username},#{userpassword},#{balance},#{grgisterdate})
21 </insert>
22
23 <!-- 修改用户 -->
24 <update id="updateUser" parameterType="com.sikiedu.beans.User">
25 UPDATE user SET username = #{username} WHERE id = #{id}
26 </update>
27
28 <!-- 删除用户 -->
29 <delete id="deleteUserById" parameterType="Integer">
30 DELETE FROM user WHERE id = #{id}
31 </delete>
32
33 <!-- 同过包装类UserVo查询用户 -->
34 <select id="selectUserByUserVoId" parameterType="UserVo" resultType="user">
35 SELECT * FROM user WHERE id = #{id}
36 </select>
37
38 <!-- selectUserCount -->
39 <select id="selectUserCount" resultType="Integer">
40 SELECT COUNT(*) FROM user
41 </select>
42
43 <resultMap type="UserVo" id="userVo">
44 <id property="id" column="id" />
45 <result property="username" column="username" />
46 <result property="grgisterdate" column="grgisterdate" />
47 <!-- 一对多关系 -->
48 <collection property="roleList" ofType="Role">
49 <id property="id" column="idrole" />
50 <result property="name" column="name" />
51 <result property="roletype" column="roletype" />
52 </collection>
53 </resultMap>
54 <!-- 一对多关联查询 -->
55 <select id="selectAllUserVo" resultMap="userVo">
56 SELECT
57 u.id,
58 u.username,
59 u.grgisterdate,
60 r.idrole,
61 r.name,
62 r.roletype
63 FROM user u
64 LEFT JOIN role r
65 ON u.id = r.userid
66 </select>
67
68 </mapper>
UserMapper.xml
映射配置文件里注册映射文件
1 <!--配置映射器的位置 -->
2 <mappers>
3 <!-- 单个配置 -->
4 <!-- <mapper resource="com/sikiedu/mapper/UserMapper.xml" /> -->
5 <!-- <mapper url="file:\D:JavaWorkSpaceJavaEE_SSM_Testssm_mybatissrccomsikiedumapperUserMapper.xml" /> -->
6 <!-- <mapper class="com.sikiedu.mapper.UserMapper" /> -->
7 <!-- 自动扫描包内的Mapper接口与配置文件 - 以包的形式;推荐使用 -->
8 <package name="com.sikiedu.mapper" />
9 </mappers>
● Dao原始开发方式
原始dao开发思路比较简单,写个dao接口和dao实现类即可。
需要向dao实现类中注入sqlSessionFactory,在方法体内通过sqlSessionFactory创建sqlSession。操作完成之后,关闭资源。
为什么在方法体内创建呢?
因为mybatis中sqlSession是线程不安全的。如果在方法外面以成员变量的方式创建,可能会引发线程安全问题。
① dao层接口
1 package com.sikiedu.dao;
2
3 import java.util.List;
4
5 import com.sikiedu.beans.User;
6 import com.sikiedu.beans.UserVo;
7
8 public interface UserDao {
9
10 // 根据ID查询用户
11 public User selectUserById(Integer id);
12
13 // 根据用户名模糊查询用户
14 public List<User> selectUserLikeUsername(String username);
15
16 // 同过包装类UserVo查询用户
17 public User selectUserByUserVoId(UserVo vo);
18
19 // 查询用户总条数
20 public Integer selectUserCount();
21
22 // 查询所有用户包装类
23 public List<UserVo> selectAllUserVo();
24
25 }
UserDao.java
② dao层接口实现类
1 package com.sikiedu.dao;
2
3 import java.util.List;
4
5 import org.apache.ibatis.session.SqlSession;
6 import org.apache.ibatis.session.SqlSessionFactory;
7
8 import com.sikiedu.beans.User;
9 import com.sikiedu.beans.UserVo;
10
11 public class UserDaoImpl implements UserDao {
12
13 // SQLSession工厂
14 private SqlSessionFactory ssf;
15
16 // 通过构造给ssf赋值
17 public UserDaoImpl(SqlSessionFactory ssf) {
18 super();
19 this.ssf = ssf;
20 }
21
22 @Override
23 public User selectUserById(Integer id) {
24
25 // 生产一个session
26 SqlSession sqlSession = ssf.openSession();
27 // 操作数据库
28 return sqlSession.selectOne("selectUserById", id);
29 }
30
31 @Override
32 public List<User> selectUserLikeUsername(String username) {
33 SqlSession sqlSession = ssf.openSession();
34 return sqlSession.selectList("selectUserLikeUsername", username);
35 }
36
37 @Override
38 public User selectUserByUserVoId(UserVo vo) {
39 SqlSession sqlSession = ssf.openSession();
40 return sqlSession.selectOne("selectUserByUserVoId", vo);
41 }
42
43 @Override
44 public Integer selectUserCount() {
45 SqlSession sqlSession = ssf.openSession();
46 return sqlSession.selectOne("selectUserCount");
47 }
48
49 @Override
50 public List<UserVo> selectAllUserVo() {
51 SqlSession sqlSession = ssf.openSession();
52 return sqlSession.selectList("selectAllUserVo");
53 }
54
55 }
UserDaoImpl.java
③ JUnit的测试类
1 package com.sikiedu.test;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.util.List;
6
7 import org.apache.ibatis.io.Resources;
8 import org.apache.ibatis.session.SqlSessionFactory;
9 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
10 import org.junit.Test;
11
12 import com.sikiedu.beans.User;
13 import com.sikiedu.beans.UserVo;
14 import com.sikiedu.dao.UserDaoImpl;
15
16 public class UserDaoTest {
17
18 // sqlSession工厂
19 private static SqlSessionFactory ssf;
20
21 static {
22 String resource = "sqlMapConfig.xml";
23 try {
24 // 读取配置文件
25 InputStream inputStream = Resources.getResourceAsStream(resource);
26 // 创建sqlSession工厂
27 ssf = new SqlSessionFactoryBuilder().build(inputStream);
28 } catch (IOException e) {
29 e.printStackTrace();
30 }
31 }
32
33 @Test // 根据ID查询用户
34 public void test1() {
35
36 UserDaoImpl dao = new UserDaoImpl(ssf);
37 User user = dao.selectUserById(1);
38 System.out.println(user);
39 }
40
41 @Test // 同过包装类UserVo查询用户
42 public void test2() {
43
44 UserDaoImpl dao = new UserDaoImpl(ssf);
45 List<User> list = dao.selectUserLikeUsername("");
46 for (User user : list) {
47 System.out.println(user);
48 }
49 }
50
51 @Test // 查询用户总条数
52 public void test3() {
53
54 UserDaoImpl dao = new UserDaoImpl(ssf);
55 Integer count = dao.selectUserCount();
56 System.out.println(count);
57 }
58
59 @Test // 查询所有用户包装类
60 public void test4() {
61
62 UserDaoImpl dao = new UserDaoImpl(ssf);
63 List<UserVo> list = dao.selectAllUserVo();
64 for (UserVo vo : list) {
65 System.out.println(vo);
66 }
67 }
68 }
UserDaoTest.java
● 原始Dao开发存在的问题
1、dao接口实现类方法中存在大量重复代码,从设计上来看,应该抽取。
2、调用sqlSession方法时,将satement的id硬编码了,即类似于”test.findUserById”这种,都写死了。
3、sqlSession的方法中,要求传入的参数是Object类型的(泛型),也就是说如果我传错了参数,编译不会报错,执行的时候才会报错,不利于开发。
● Dao动态代理开发方式
Mapper接口开发方式是基于入门程序的基础上,对 控制程序 进行分层开发,程序员只需要 编写mapper接口 和 Mappe.xml 配置文件即可。
程序员编写mapper接口需要遵循一些开发规范,mybatis可以自动生成mapper接口实现类代理对象。
二、SqlSession的使用范围
● SqlSessionFactoryBuilder
通过SqlSessionFactoryBuilder创建会话工厂SqlSessionFactory
将SqlSessionFactoryBuilder当成一个工具类使用即可,不需要使用单例管理SqlSessionFactoryBuilder。
在需要创建SqlSessionFactory时候,只需要new一次SqlSessionFactoryBuilder即可。
● SqlSessionFactory
通过SqlSessionFactory创建SqlSession,使用单例模式管理sqlSessionFactory(工厂一旦创建,使用一个实例)。
将来mybatis和spring整合后,使用单例模式管理sqlSessionFactory。
● SqlSession
SqlSession是一个面向用户(程序员)的接口。
SqlSession中提供了很多操作数据库的方法:如:selectOne(返回单个对象)、selectList(返回单个或多个对象)、。
SqlSession是线程不安全的,在SqlSesion实现类中除了有接口中的方法(操作数据库的方法)还有数据域属性。
SqlSession最佳应用场合在方法体内,定义成局部变量使用。
三、增删改查操作
读取配置文件,创建sqlSessionFactory,获取sqlSession
// 读取配置文件
String resource = "sqlMapConfig.xml";
InputStream in = Resources.getResourceAsStream(resource);
// 需要sqlSessionFactoryBuilder
SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder();
// 创建sqlSessionFactory
SqlSessionFactory ssf = ssfb.build(in);
// 生产一个sqlSession
SqlSession sqlSession = ssf.openSession();
♦ 增
<insert id="insertUser" parameterType="com.sikiedu.beans.User">
INSERT INTO user VALUES(null,#{username},#{userpassword},#{balance},#{grgisterdate})
</insert>
User user = new User();
user.setUsername("天猫");
user.setUserpassword("123456");
user.setBalance(Float.valueOf(1000));
user.setGrgisterdate(new SimpleDateFormat("yyyy-MM-dd").format(new Date(System.currentTimeMillis())));
sqlSession.insert("com.sikiedu.mapper.UserMapper.insertUser", user);
sqlSession.commit();
♦ 删
<delete id="deleteUserById" parameterType="Integer">
DELETE FROM user WHERE id = #{id}
</delete>
sqlSession.delete("com.sikiedu.mapper.UserMapper.deleteUserById", 100);
sqlSession.commit();
♦ 改
<update id="updateUser" parameterType="com.sikiedu.beans.User">
UPDATE user SET username = #{username} WHERE id = #{id}
</update>
User user = new User();
user.setId(44);
user.setUsername("阿羊");
sqlSession.update("com.sikiedu.mapper.UserMapper.updateUser", user);
sqlSession.commit();
♦ 查
<!-- #{}占位符 尽量选用#{}来解决问题 -->
<!-- ${}字符拼接 or1=1 容易被SQL注入 -->
<select id="selectUserById" parameterType="Integer" resultType="com.sikiedu.beans.User">
SELECT * FROM user WHERE id = #{id}
</select>
<select id="selectUserLikeUsername" parameterType="String" resultType="User">
<!-- SELECT * FROM coke.user WHERE username LIKE '%${value}%' -->
SELECT * FROM user WHERE username LIKE "%"#{username}"%"
</select>
// 查询用户
// 操作数据库;参数1-要操作的sql语句;参数2-sql语句参数
User user = sqlSession.selectOne("com.sikiedu.mapper.UserMapper.selectUserById", 3);
System.out.println(user);
// 通过username模糊 查询用户
List<User> users = sqlSession.selectList("com.sikiedu.mapper.UserMapper.selectUserLikeUsername", "天");
for (User user : users) {
System.out.println(user);
}