博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
mybatis基础学习(二)
阅读量:6281 次
发布时间:2019-06-22

本文共 9972 字,大约阅读时间需要 33 分钟。

在前面内容里,已经通过mybatis简单实现了一个查询功能,接下来主要通过XNL实现的方式,使用接口调用的方式,分别实现简单的CRUD的功能

mybatis XML方式

###1、select示例

以一个简单的用户权限控制为例,上面是权限控制对应表结构的ER图。在src/main/java下的tk.mybatis.simple.model包里新建对应的实体类。此处省略实体类的创建内容,五个类为SysUser,SysRole,sysPrivilege,SysUserRole,SysRolePrivilege

在src/mian/resource下的tk.mybatis.simple.mapper包内新建 mapper对应的xml文件:UserMapper.xmL、RoleMapper.xml、PrivilegeMapper.xml 、UserRoleMapper.xml和

RolePrivilegeMapper.xml 同时在src/main/java下新建tk.mybatis.simple.mapper包,在包中新建XML文件对应的接口类:UserMapper.java、RoleMapper.java、PrivilegeMapper.java、UserRoleMapper.java、RolePrivilege.java

接口类举例:

public interface UserMapper{}复制代码

xml文件举例:

复制代码

在使用接口进行方法调用的时候,mapper.xml中的namespace必须配置为接口类的全限定名称。

准备完对应的接口和XML文件后,在mybatis-config.xml配置文件的mappers元素中配置所有的mapper:

复制代码

这里支持扫包的模式,扫包的时候会对配置的包下面的所以接口进行循环操作:

1、判读接口对应的命名空间是否存在,存在则抛出异常,不存在则继续操作
2、加载接口对应的xml映射文件,通过接口的全路径名称加xml来查找并解析,这就是为什么xml文件名和接口名必须一致的原因
3、处理接口中的方法

在基本配置完成后,若要实现一个简单的查询功能,只要在xml文件中添加<select>标签,写上sql语句,做一些简单配置把查询结果映射到对象中即可。

这里做一个根据ID查询用户的示例,先在UserMapper接口中添加一个selectById方法,代码如下:

public interface UserMapper{    SysUser selectById(Long id);}复制代码

然后在对应的UserMapper.xml中添加如下的<resultMap><select>部分的代码:

复制代码

这里主要关注两点:

1、接口中的方法和XML通过<select>标签的id属性进行关联,id的属性值和接口中的方法名是一致的,若方法名和id不一致就会报错。
2、<select>标签里的resultMap属性对应上面的<resultMap>,这里是为了方便映射,做了详细配置,也可以参照前一篇内容中使用resultType属性,则无需进行额外配置,两者区别在于是否有具体的映射关系,有映射关系则可以使用select * 这样的查询操作,否则必须进行具体字段的查询,而且数据库字段必须和类字段一致,若不一致可以使用as进行转换。具体的其他用法会在后面用到的地方具体描述。

```是一种和重要的配置结果映射的方法

具体的使用可以参照Mybatis---resultMap部分的具体解析

接口中定义的返回值类型必须和泊位中配置的resultType 类型一致,否则就会因为类型不一致而抛出异常。这里新增一个查询所有用户的方法,来区分不同返回值的情况,新增代码如下:

public interface UserMapper{    SysUser selectById(Long id);    List
selectAll();}复制代码

#

select id, user_name userName, user_password userPassword, user_ema userEmail, user_info userInfo, head_img headImg, create_time createTime from sys_user
观察一下U serMapper.xmJ 中selectByid 和selectAll 的区别: selectByid 中使用了resultMap 来设置结果映射,而se lectAll 中则通过result Type 直接指定了返回结果的类型。可以发现,如果使用result Type 来设置返回结果的类型,需要在SQL 中为所有列名和属性名不一致的列设置别名,通过设置别名使最终的查询结果列和result Type 指定对象的属性名保持一致,进而实现自动映射。

在数据库中,由于大多数数据库设置不区分大小写,因此下画线方式的命名很常见,如user_name、user_email 。在Java中,一般都使用驼峰式命名,如userName、userEmail。因为数据库和Java中的这两种命名方式很常见,因此MyBatis还提供了一个全局属性apUnderscoreToCamelCase,通过配置这个属性为true 可以自动将以下画线方式命名的数据库列映射到Java对象的驼峰式命名属性中。这个属性默认为false,如果想要使用该功能,需要在MyBatis的配置文件增加如下配置:

复制代码

使用该配置的时候,前面的selectAll方法就无需as起别名。

测试:

为方便测试,编写一个基础测试类,用于初始化数据库连接:

public class BaseMapperTest {private static SqlSessionFactory sqlSessionFactory;@BeforeClasspublic static void init(){    try {        Reader reader = Resources.getResourceAsReader("mybatis-config.xml");        sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);        reader.close();    }catch (Exception e){        e.printStackTrace();    }}public static SqlSession getSqlSessionFactory() {    return sqlSessionFactory.openSession();}}复制代码

编写测试类XXXMapperTest继承基础测试类BaseMapperTest:

public class SysuserTest extends BaseMapperTest {@Testpublic void selectByIdTest(){    SqlSession sqlSession = getSqlSessionFactory();    try {        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);        SysUser user = userMapper.selectById(1L);        System.out.println("ID:"+user.getId()+"===name:"+user.getUserName()+"===password:"+user.getUserPassword()+                "===info:"+user.getUserInfo()+"===email:"+user.getUserEmail()+"===createtime:"+user.getCreateTime());    }catch (Exception e){        e.printStackTrace();    }finally {        sqlSession.close();    }}@Testpublic void selectAllTest(){    SqlSession sqlSession = getSqlSessionFactory();    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);    List
users = userMapper.selectAll(); for(SysUser user : users ){ System.out.println("ID:"+user.getId()+"===name:"+user.getUserName()+"===password:"+user.getUserPassword()+ "===info:"+user.getUserInfo()+"===email:"+user.getUserEmail()+"===createtime:"+user.getCreateTime()); }}}复制代码

到这里,简单的select查询就结束了,复杂的查询主要区别在于sql已经和返回对象,在后面再详细描述。

###2、insert示例

在UserMapper中新增insert方法:

int insert(SysUser sysUser);复制代码

在UserMapper.xml中新增insert标签

insert into sys_user( id,user_name,user_password,user_ema, user_info,head_img,create_time) values( #{id},#{userName},#{userPassword},#{userEmail}, #{userInfo},#{headImg,jdbcType=BLOB},#{createTime,jdbcType = TIMESTAMP} )
复制代码

看一下<insert>元素的具体属性:

1、id:命名空间中的唯一标识符,需要与接口中的方法名一致
2、parameterType:指定传入的参数类名或别名,可选。不建议配置
3、flushCache:默认为true,任何时候只要语句被执行,则清空一二级缓存
4、timeout:设置在抛出异常之前,驱动程序等待数据库返回请求结果的秒数
5、statementType:对于STATMENT、PREPARED、CALLABLE,mybatis会使用对应的Statement、PrepareStatement、CallableStatement,默认值为PREPARED.
6、useGenerateKeys:默认为false。如果设置为true,mybatis会使用JDBC默认的getGeneraedKeys方法来去除由数据库内部生产的主键。
7、keyProperty:mybatis通过getGeneratedKeys获取主键值后将要赋值的属性名。如果希望得到多个数据库自动生产的列,属性值也可以以逗号分割作为属性名称列表
8、keyColumn:仅对INSERT和UPDATE有效。通过生成的键值设置表中的列名,这个设置仅在某些数据库中是必须的,当主键不是表的第一列的时候需要设置。如果需要得到多个生产的列,也可以逗号分隔
9、databaseId:如果配置了databaseIdProvider,mybatis会加载所有不带databaseId的或匹配当前databaseId的语句。如果同时存在带databaseId和不带databaseId的语句,后者会被忽略。
为防止类型错误,对于特殊的数据类型,建议指定具体的jdbcType值。

测试:

@Testpublic  void insertTest(){    SysUser sysUser = new SysUser();    sysUser.setId(0000000000101L);    sysUser.setUserName("testuser01");    sysUser.setUserPassword("test01");    sysUser.setUserEmail("test01@test.com");    sysUser.setUserInfo("he is test01 for test!");    sysUser.setHeadImg(null);    sysUser.setCreateTime(new Date());    SqlSession sqlSession = getSqlSessionFactory();    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);    Integer n = userMapper.insert(sysUser);    //默认的sqlsession是不会自动提交的    sqlSession.commit();    System.out.println(n);}复制代码

一个简单的insert方法就实现了,注意在这里,方法的返回值是int类型的,这里的返回值是改变数据数据条数。

这里提供两个方法获取insert对象的主键:

#####a、jdbc方式回显

新增一个insert2方法方便测试

int insert2(SysUser sysUser);复制代码

在XML文件中配置insert2的sql如下:

insert into sys_user( user_name,user_password,user_ema, user_info,head_img,create_time) values( #{userName},#{userPassword},#{userEmail}, #{userInfo},#{headImg,jdbcType=BLOB},#{createTime,jdbcType = TIMESTAMP} )
复制代码

这里使用了useGeneratedKeys方法来获取自增的主键值,通过keyProperty属性把主键值付给id。

测试方法中insert2执行并commit后,获取sysuser对象的id发现回显了,带回了id的值

#####b、使用selectkey方法获取id

新增一个insert3方法方便测试

int insert3(SysUser sysUser);复制代码

在XML文件中配置insert3的sql如下:

insert into sys_user( user_name,user_password,user_ema, user_info,head_img,create_time) values( #{userName},#{userPassword},#{userEmail}, #{userInfo},#{headImg,jdbcType=BLOB},#{createTime,jdbcType = TIMESTAMP} )
select last_insert_id()
复制代码

这里在<insert>标签里面新增了一个<selectKey>的标签,keyColumn、keyProperty和上面insert2方法中的用法一样,resultType是指定返回值对象,order是根据数据库类型指定,mysql使用‘AFTER’,因为主键值是insert语句执行完之后才能获取到,oracle使用‘BEFOR’,因为oracle数据库需要先从序列获取值,然后将值作为 主键插入到数据库中。

oracle中使用如下:

select SEQ_ID.nextval from dual
insert into sys_user( id,user_name,user_password,user_ema, user_info,head_img,create_time) values( #{id},#{userName},#{userPassword},#{userEmail}, #{userInfo},#{headImg,jdbcType=BLOB},#{createTime,jdbcType = TIMESTAMP} )
复制代码

这里把<selectKey>标签放到前面只是为了表示执行顺序,具体放在上面还是下面对代码没影响,决定执行顺序的是order字段的值。sql语句中明确写出了id是因为这里插入id的是根据查询出来的值再进行插入的,如果没有会报错。

###3、update示例

写一个根据主键更新数据的方法作为示例:
在UserMapper接口中新增方法:
int updateById(SysUser sysUser);
在UserMapper.xml中新增update标签:

update sys_user set user_name=#{userName}, user_password=#{userPassword}, user_ema=#{userEmail}, user_info=#{userInfo}, head_img=#{headImg,jdbcType=BLOB}, create_time=#{createTime,jdbcType=TIMESTAMP} where id=#{id}
复制代码

测试:

@Testpublic void updateByIdTest(){    SysUser sysUser = new SysUser();    sysUser.setId(1001L);    sysUser.setUserName("testuser05_update");    sysUser.setUserPassword("test05_update");    sysUser.setUserEmail("test05_update@test.com");    sysUser.setUserInfo("he is test05_update for test!");    sysUser.setHeadImg(null);    sysUser.setCreateTime(new Date());    SqlSession sqlSession = getSqlSessionFactory();    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);    Integer n = userMapper.updateById(sysUser);    //默认的sqlsession是不会自动提交的    sqlSession.commit();    System.out.println(sysUser.getId());    System.out.println(n);}复制代码

###4、delete示例

写一个根据id删除数据的方法作为示例:
在UserMapper接口里新增一个删除方法:
int deleteById(Long id);
在UserMapper.xml中新增对应的delete标签:

delete from sys_user where id=#{id}
复制代码

测试:

@Testpublic void deleteById(){    SqlSession sqlSession = getSqlSessionFactory();    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);    Integer n = userMapper.deleteById(1005L);    //默认的sqlsession是不会自动提交的    sqlSession.commit();    System.out.println(n);}复制代码

当然这里如果传参传User对象也是可以的,xml文件中不需要修改,直接修改接口参数为User对象就行。

###5、多个参数作为方法参数时的处理

如果要执行的CRUD方法有多个参数的时候应该如何处理?一般有两种方法:
1、新建一个map对象:把多个参数通过key和value传进去,但是这种方式要自己新建map对象,一般不推荐。
2、使用@Param注解的方式:
例:根据用户ID和角色的enabled状态获取角色对象
List<SysRole> selectRolesByUserIdAndRoleEnabled(@Param("userId")Long userId,@Param("enabled")Integer enabled);
在xml中使用如下:

复制代码

若要传入的不是基本类型而是javaBean对象也是可以的,对应的则使用.的方式来获取:

List<SysRole> selectRolesByUserIdAndRoleEnabled(@Param("user")SysUser sysUser,@Param("role")SysRole sysRole);
xml中则使用where u.id=#{user.id) and r.enabled=#{role.enabled)从javaBean对象中获取对应的值。

转载于:https://juejin.im/post/5a0cf89d51882531ba107ea3

你可能感兴趣的文章
ipsec ***经常无法ping通处理方法
查看>>
Windows Server 2008 之 终端服务TS WEB ACCESS
查看>>
单臂路由实现DHCP功能
查看>>
Server 2012 Hyper-v新功能之四:存储迁移
查看>>
spring boot https配置
查看>>
Servlet----------在servlet中输出js代码
查看>>
List中判断是否有重复的元素
查看>>
HIVE安装
查看>>
初识UGUI之Scroll Rect,实现滚动效果
查看>>
定时器(Quartz)快速入门
查看>>
某网站安全检测之数据库手工注入
查看>>
十年磨一剑,霜刃未曾试——杀猪越货利器放送
查看>>
HashMap其实就那么一回事儿之源码浅析
查看>>
01Exchange Server 2010跨站点部署-环境介绍
查看>>
nessus 离线安装插件plugins
查看>>
使用通用二进制方式安装MariaDB或者MySQL
查看>>
用js写1-33随机抽取几个不同数字
查看>>
QQ终于不再崩溃
查看>>
centos 6.8 linux iscsi服务器配置和客户端连接iscsi
查看>>
一些很不错的话
查看>>