在上一篇博客中,我们初识了Mybatis,了解了怎样使用Mybatis来对数据库进行操作,在本篇博客中,我们将实现单个参数的增删改查功能,分别了解select,insert,update,delete的基本用法。
在很多系统中都需要权限管理,因此我们在这里对权限管理进行需求分析,建立其数据库表和对应的实体类。在数据库中我们建立了用户表sys_user,角色表sys_role,权限表sys_privilege,用户角色关联表sys_user_role,角色权限关联表sys_role_privilege。这五个表结构如下所示。建好五个表之后,在tk.mybatis.sample.model中创建对应的实体类,如何建立实体类在上篇博客中学习,在这里不在赘述。
首先根据数据库中的五个表在src/main/resources中tk.mybatis.sample.mapper下创建对应的xml文件分别是UserMapper.xml,RoleMapper.xml,PrivilegeMapper.xml,UserRoleMapper.xml,RolePrivilegeMapper.xml,然后在src/main/java中创建包tk.mybatis.sample.mapper创建对应的接口类,类名同xml文件。创建xml文件在上一篇博客中也有叙述。创建完毕后在mybatis-config.xml配置文件中配置所有mapper文件。
但是这种配置方式需要将所有映射文件都列举出来,如果增加了新的映射文件还需要记得添加,操作起来比较麻烦,所有在这里我们采用另外一种配置方式如下:
这种配置方式会查找tk.mybatis.sample.mapper包下所有的接口,加载接口对应的xml映射文件。
在很多时候我们需要查询系统中的用户、角色、权限等数据,这就需要写查询语句。先写一个根据用户ID查询用户信息的方法,首先我们在UserMapper接口类中添加一个selectById方法
/**
* 通过ID查询用户
*
* @param ID
* @return
*
*/
SysUser selectById(Long id);
然后在对应的UserMapper.xml文件中添加
可以发现,在接口中的方法名和xml文件中select的id属性是一样的,在Mybatis中就是通过这种方式将接口方法和xml的sql语句关联在一起的,所以在xml文件中不能出现重复的id属性值。而在select中的#{id}则是Mybatis中使用预编译参数的一种方式,大括号中的内容就是传入的参数名。resultMap是用于设置返回值的类型和映射关系的,如果在select中不使用配置的resultmap而是使用resultType,那么需要在sql语句中为所有列名和属性名不一致的列设置别名,从而实现自动映射(在接下来的方法中可以看到)。
接下来我们添加一个selectAll的方法。
/**
* 查询全部用户
*
* @return
*/
List selectAll();
同样的,我们在UserMapper.xml文件中添加对应的select,这里使用的返回值就是resultType,可以看到将表中列名重命名成为SysUser类中属性名。
而如果我们需要通过用户ID返回对应的角色信息,同时需要返回一部分的用户信息,那该怎么办呢?在这里我们添加这样一个方法selectRoleByUserId。
/**
* 根据用户ID获取角色信息
*
* @param userId
* @return
*/
List selectRoleByUserId(Long userId);
接着在xml文件中添加相应的select语句。这里有两种简单方法设置其返回值,一是在SysRole对象中直接添加我们需要的属性(例如直接添加userName和userEmail属性)或是在SysRole中直接添加SysUser对象,这里我们使用的是第二种。
我们在UserMapper中添加一个增加新用户的方法insert。
/**
* 增加新用户
*
* @param SysUser
* @return
*/
int insert(SysUser sysUser);
同时在xml文件中添加对应的对应代码。在该insert中,可以看到为headImg和createTime两个参数配置了jdbcType属性,这是为了防止出现类型错误。同时在insert中我们配置了useGeneratedKeys和keyProperty两个属性,配置这两个属性之后,Mybatis会使用jdbc的方法提取数据库内部的主键,将其赋值给keyProperty配置的id属性(当有多个属性时,要使用逗号隔开,同时要设置keyColumn属性)。还有一种selectKey方法可以返回主键值,大家感兴趣可以去搜索学习。
insert into sys_user(id,user_name,user_password,user_email,
user_info,head_img,create_time)
values(
#{id},#{userName},#{userPassword},#{userEmail},
#{userInfo},#{headImg, jdbcType=BLOB},
#{createTime, jdbcType=TIMESTAMP})
首先我们添加一个根据主键更新数据的方法updateById。
/**
* 根据主键更新
*
* @param sysUser
* @return
*/
int updateById(SysUser sysUser);
在xml中添加对应的
update sys_user
set user_name = #{userName},
user_password = #{userPassword},
user_email = #{userEmail},
user_info = #{userInfo},
head_img = #{headImg, jdbcType=BLOB},
create_time = #{createTime, jdbcType=TIMESTAMP}
where id = #{id}
delete和update用法基本类似,以一个简单的例子说明。我们添加一个方法deleteById。
/**
* 根据主键删除
*
* @param ID
* @return
*/
int deleteById(Long id);
接着添加相应的代码到xml文件中。
delete from sys_user where id = #{id}
由于以后我们需要更多的测试类,所以在这里创建一个测试基类BaseMapperTest,将所有测试类中通用的部分添加进去。
/*
* 基础测试类
* */
package tk.mybatis.sample.mapper;
import java.io.IOException;
import java.io.Reader;
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.junit.BeforeClass;
public class BaseMapperTest {
private static SqlSessionFactory sqlSessionFactory;
@BeforeClass
public static void init(){
try{
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
reader.close();
} catch (IOException e){
e.printStackTrace();
}
}
public SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
我们将根据从上之下的顺序将本篇文章中介绍的所有方法的测试方法及其结果展示出来。
@Test
public void testSelectById(){
SqlSession sqlSession = getSqlSession();
try{
UserMapper usermapper = sqlSession.getMapper(UserMapper.class);
SysUser user = usermapper.selectById(1l);
//Assert.assertNotNull(user);
//Assert.assertEquals("admin", user.getUserName());
} finally{
sqlSession.close();
}
}
@Test
public void testSelectAll(){
SqlSession sqlSession = getSqlSession();
try{
UserMapper usermapper = sqlSession.getMapper(UserMapper.class);
List userList = usermapper.selectAll();
//Assert.assertNotNull(userList);
//Assert.assertTrue(userList.size()>0);
} finally{
sqlSession.close();
}
}
@Test
public void testSelectRoleByUserId(){
SqlSession sqlSession = getSqlSession();
try{
UserMapper usermapper = sqlSession.getMapper(UserMapper.class);
List roleList = usermapper.selectRoleByUserId(1l);
//Assert.assertNotNull(userList);
//Assert.assertTrue(userList.size()>0);
} finally{
sqlSession.close();
}
}
@Test
public void testInsert(){
SqlSession sqlSession = getSqlSession();
try{
UserMapper usermapper = sqlSession.getMapper(UserMapper.class);
SysUser user = new SysUser();
user.setUserName("test1");
user.setUserPassword("123456");
user.setUserEmail("[email protected]");
user.setUserInfo("test info");
user.setHeadImg(new byte[]{1,2,3});
user.setCreateTime(new Date());
int result = usermapper.insert(user);
System.out.println(user.getId());
} finally{
sqlSession.commit();
sqlSession.close();
}
}
@Test
public void testUpdateById(){
SqlSession sqlSession = getSqlSession();
try{
UserMapper usermapper = sqlSession.getMapper(UserMapper.class);
SysUser user = usermapper.selectById(1l);
user.setUserName("admin_test");
user.setUserEmail("[email protected]");
int result = usermapper.updateById(user);
user = usermapper.selectById(1l);
} finally{
sqlSession.rollback();
sqlSession.close();
}
}
@Test
public void testDeleteById(){
SqlSession sqlSession = getSqlSession();
try{
UserMapper usermapper = sqlSession.getMapper(UserMapper.class);
SysUser user1 = usermapper.selectById(1l);
int result = usermapper.deleteById(1l);
SysUser user2 = usermapper.selectById(1l);
} finally{
sqlSession.rollback();
sqlSession.close();
}
}
在这里值得一提的是,在执行update,insert,delete三个操作时,需要对sqlSession进行commit操作,否则这三个操作将不会影响到数据库,因为sqlSessionFactory.openSession()是不自动提交的,在测试中,我们为了不影响其他测试的结果,所以选择进行操作回滚。
整个项目结构如下所示:
上一篇:Mybatis学习日记(一)——初识Mybatis,一个简单demo
下一篇:Mybatis学习日记(三)——使用@param方法传递多个参数