mybatis 同名方法_【MyBatis】 MyBatis修炼之四 MyBatis XML方式的基本用法(SELECT)...

我们执行查询操作,使用MyBatis,我们只需要在XML中添加select元素,然后写上SQL语句,然后再做一些简单的配置,就可以将查询的结果直接映射到对象中。

MyBatis参考文档:

工具

JDK 1.6及以上版本

MyBatis 3.30版本

MySQL 6.3版本

Eclipse4 及以上版本

Apache Maven 构建工具

先写一个根据用户id,查询用户信息的简单方法。在UserMapper接口中添加一个selectById方法。

package mybatis.simple.mapper;

import mybatis.simple.model.SysUser;

public interface UserMapper {

public SysUser selectById(Long id);

}

然后在对应的UserMapper.xml中添加如下的和部分的代码。

/p>

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

select * from sys_user where id = #{id}

创建接口和XML时我们知道接口和XML是通过将namespace的值设置为接口的全限定名称来进行关联的,那么接口中的方法和XML又是怎么关联的呢?

XML中的select标签的id属性值和定义的接口方法名一样,MyBatis就是通过这种方式将接口方法和XML中定义的SQL语句关联到一起的。如果接口方法没有和XML中的id属性值相对应,启动程序便会报错。

映射XML和接口的命名需要符合规则如下:

① 当只使用XML而不使用接口的时候,namespace的值可以设置为任意不重复的名称。

② 标签的id属性值在任何时候都不能出现英文的句号“.”,并且同一个命名空间下不能出现重复的id

③ 因为接口方法是可以重载的,所以接口中可以出现多个同名但是参数不同的方法,但是XML中id的值不能重复,那么接口中的多有的同名方法都对应着XML中的同一个id的方法。

标签和属性的作用:

:映射查询语句使用的标签。

id:命名空间中唯一标识符,可用来代表这条语句

resultMap:用于设置返回值得类型和映射关系。

select标签中的select * from sys_user where id = #{id}是查询语句。

#{id}:MyBatis SQL中使用预编译参数的一种方式,大括号中的id是传入的参数名。

在上面的中,使用resultMap设置返回值得类型,这里的SysUser就是中的id属性值,通过id引用需要的。

resultMap标签用于配置Java对象的属性和查询结果列的对应关系,通过resultMap中配置的column和property可以将查询列的值映射到type对应的属性上,因此当我们使用select *进行查询所有列时,MyBatis也可以将结果正确地映射到SysUser对象上。

resultMap包含的所有属性:

id:必填,并唯一,在select标签中resultMap指定的值即为此id所设置的值。

type:必填用于配置查询列所映射到的Java对象类型。

extends:选填,可以配置当前的resultMap继承自其它的resultMap,属性值为继承的resultMap的id。

autoMapping:选填,可选值为true或false,用于配饰是否启用非映射字段(没有在resultMap中配置的字段)的自动映射功能,该配置可以覆盖全局的autoMappingBehavior配置。

resultMap包含的所有标签:

constructor:配置使用构造方法注入结果,包含以下两个字标签

idArg:id参数,标记结果作为id(唯一值)

arg:注入到构造方法中的普通结果

id:一个id结果,标记作为id(唯一值)

result:注入到Java对象属性的普通结果。

association:一个复杂的类型观念,许多结果将包成这种类型

collection:复杂类型的集合。

discriminator:根据结果值来决定使用哪个结果映射

case:基于某些值的结果映射。

constructor通过构造方法注入属性的结果值。构造方法中的idArg、arg参数分别对应着resultMap标签中的id、result标签,它们的含义相同,只是注入的方式不同。

resultMap中的id和result标签包含的属性相同,不同的地方在于id代表的是主键(或唯一键)的字段(可以有多个),它们的属性值是通过setter方法注入的。

id和result标签包含的属性:

column:从数据库得到的列名,或者是列的别名。

property:映射到列结果的属性(JavaBean的属性)

javaType:一个Java类的完全限定名,或一个类型别名(通过mybatis-config.xml中的typeAlias配置或者默认的类型)。如果映射到一个JavaBean,MyBatis通常可以自动判断属性的类型。

jdbcType:列对应的数据库类型。JDBC类型仅仅需要对插入、更新、删除操作可能为空的列进行处理。

typeHandler:使用这个属性可以覆盖默认的类型处理器。

接口中定义的返回值类型必须和XML中配置的resultType类型一致,否则就会因为类型不一致而抛出异常。返回值类型是由XML中的resultType(或者resultMap中的type)决定,不是由接口中写的返回值类型决定的。

UserMapper接口中的selectById方法,通过主键id查询,最多只会返回一条数据,所以这里的返回值是SysUser.

我们再写一个查询所有用户的方法,在UserMapper接口中添加selectAll方法;

package mybatis.simple.mapper;

import java.util.List;

import mybatis.simple.model.SysUser;

public interface UserMapper {

public SysUser selectById(Long id);

public List selectAll();

}

并在对应的UserMapper.xml中添加新的查询所有用户的部分:

/p>

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

select * from sys_user where id = #{id}

select id,

user_name userName,

user_password userPassword,

user_email userEmail,

user_info userInfo,

head_img headImg,

create_time createTime

from sys_user

观察我们selectById和selectAll我们可以发现:

1、selectById中的返回最多只有1个结果时,我们可以直接使用JavaBean对象来接收返回数据。而当执行的SQL返回多个结果时,接口必须使用List或Object[]作为返回值(Object为具体的JavaBean对象)。

2、使用resultMap和resultType都可以返回对象集合,使用resultType限定返回类型时,属性值为返回对象的权限定类名,使用resultMap限定返回类型时,属性值为resultMap标签中定义的id的值。

3、如果使用resultType来设置返回结果的类型,需要在SQL中为所有的列名和属性名不一致的列设置别名,通过设置别名来使最终的查询结果列和resultType指定对象的属性名保持一致,进而实现自动映射。

名称映射规则:

可以在resultMap中配置property属性和column属性的映射,或者在SQL中设置别名,这两种方式实现将查询列映射到对象属性的目的。

property属性或别名要和对象中属性的名字相同,但是实际匹配时,MyBatis会先将两者都转换为大写形式,然后再判断是否相同,即property=“userName”和proeprty="username"都可以匹配到对象的userName属性上。判断是否相同的时候要使用USERNAME,因此在设置property属性或别名的时候,不需要考虑大小写是否一致。

下面通过测试来验证我们的两个查询。

首先我们提取出一个基础测试类BaseMapperTest,而其他测试类,都继承此类,通过此类提供的getSqlSession()获取SqlSession对象。

BaseMapperTest基础测试类:

package mybatis.simple.test;

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);

}catch (IOException e) {

e.printStackTrace();

}

}

public SqlSession getSqlSession(){

return sqlSessionFactory.openSession();

}

}

编写UserMapperTest测试类;

package mybatis.simple.test;

import java.util.List;

import org.apache.ibatis.session.SqlSession;

import org.junit.Test;

import mybatis.simple.mapper.UserMapper;

import mybatis.simple.model.SysUser;

public class UserMapperTest extends BaseMapperTest {

@Test

public void testSelectById(){

//获取SqlSession

SqlSession sqlSession = getSqlSession();

//获取UserMapper接口

try {

UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

//调用selectById方法,查询id=1的用户

SysUser user = userMapper.selectById(1L);

} finally{

//关闭SqlSession

sqlSession.close();

}

}

@Test

public void testSelectAll(){

//获取SqlSession

SqlSession sqlSession = getSqlSession();

//获取UserMapper接口

try {

UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

//调用selectById方法,查询id=1的用户

List userList = userMapper.selectAll();

} finally{

//关闭SqlSession

sqlSession.close();

}

}

}

右键单击该类,在Run As选项中选择JUnit Test执行测试。测试通过,控制台将会打印如下日志:

DEBUG [main] - Opening JDBC Connection

DEBUG [main] - Created connection 511473681.

DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1e7c7811]

DEBUG [main] - ==> Preparing: select id, user_name userName, user_password userPassword, user_email userEmail, user_info userInfo, head_img headImg, create_time createTime from sys_user

DEBUG [main] - ==> Parameters:

TRACE [main] - <== Columns: id, userName, userPassword, userEmail, userInfo, headImg, createTime

TRACE [main] - <== Row: 1, admin, 123456, admin@mybais.alex, <>, <>, 2017-08-09 15:26:52.0

TRACE [main] - <== Row: 2, test, 123456, test@mybais.alex, <>, <>, 2017-08-09 15:27:30.0

DEBUG [main] - <== Total: 2

DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1e7c7811]

DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1e7c7811]

DEBUG [main] - Returned connection 511473681 to pool.

DEBUG [main] - Opening JDBC Connection

DEBUG [main] - Checked out connection 511473681 from pool.

DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1e7c7811]

DEBUG [main] - ==> Preparing: select * from sys_user where id = ?

DEBUG [main] - ==> Parameters: 1(Long)

TRACE [main] - <== Columns: id, user_name, user_password, user_email, user_info, head_img, create_time

TRACE [main] - <== Row: 1, admin, 123456, admin@mybais.alex, <>, <>, 2017-08-09 15:26:52.0

DEBUG [main] - <== Total: 1

DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1e7c7811]

DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1e7c7811]

DEBUG [main] - Returned connection 511473681 to pool.

上面的两个SELECT查询仅仅是简单的单表查询,而我们在实际情况下,通常需要进行多表关联查询,关联查询的结果也会有多种情况。

第一种情况:根据用户id获取用户拥有的所有角色,返回的结果为角色集合,结果只有角色的信息,不包含额外的其他字段信息。

在UserMapper接口中添加一个方法selectRoleByUserId

public List selectRoleByUserId(Long userId);

并在UserMapper.xml中添加如下代码;

select r.id,

r.role_name roleName,

r.enabled,

r.create_by createBy,

r.create_time createTime

from sys_user_role ur , sys_role r where

ur.role_id=r.id

and ur.user_id =

#{userId}

虽然这是从多张表中查询出的数据,但是结果值包含一个表(sys_role)中的信息,所以直接返回SysRole即可。

第二种情况:在第一种情况的基础下,返回的结果不仅包含角色的信息,还包含当前用户的部分信息(用户名)。

实现此种情况,我们有三种方法

1、在SysRole对象中直接添加userName属性,这样仍然使用SysRole作为返回值。

public class SysRole {

//其他原字段

private String userName;

public String getUserName() {

return userName;

}

public void setUserName(String userName) {

this.userName = userName;

}

//原字段的getter和setter

}

2、新建一个类,继承SysRole,在该类中添加属性userName,最后返回该类即可。

package mybatis.simple.model;

public class SysRoleUser extends SysRole{

private String userName;

public String getUserName() {

return userName;

}

public void setUserName(String userName) {

this.userName = userName;

}

}

3、将用户对象最为一个属性添加到角色中

public class SysRole {

//其他原字段

private SysUser user;

//原字段的getter和setter

}

直接在SysRole中增加SysUser对象,字段名为user,增加这个字段后,修改XML中的selectRoleByUserId方法

select r.id,

r.role_name roleName,

r.enabled,

r.create_by createBy,

r.create_time createTime,

u.user_name as "user.userName"

from sys_user u

inner join sys_user_role ur on u.id=ur.user_id

inner join sys_role r on ur.role_id=r.id

where u.id =

#{userId}

注意 u.user_name as "user.userName",这里设置别名时,使用的是“user.属性名”,user是SysRole中添加的属性,userName是SysUser对象中的属性,通过这种方式直接将值赋给user字段中的属性。

在UserMapperTest中添加测试代码:

@Test

public void testSelectRoleByUserId() {

// 获取SqlSession

SqlSession sqlSession = getSqlSession();

// 获取UserMapper接口

try {

UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

// 调用selectById方法,查询id=1的用户

List roleList = userMapper.selectRoleByUserId(1L);

} finally {

// 关闭SqlSession

sqlSession.close();

}

}

右键单击该类,在Run As选项中选择JUnit Test执行测试。测试通过,控制台将会打印如下日志:

DEBUG [main] - Opening JDBC Connection

DEBUG [main] - Created connection 2011986105.

DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@77ec78b9]

DEBUG [main] - ==> Preparing: select r.id, r.role_name roleName, r.enabled, r.create_by createBy, r.create_time createTime, u.user_name as "user.userName" from sys_user u inner join sys_user_role ur on u.id=ur.user_id inner join sys_role r on ur.role_id=r.id where u.id = ?

DEBUG [main] - ==> Parameters: 1(Long)

TRACE [main] - <== Columns: id, roleName, enabled, createBy, createTime, user.userName

TRACE [main] - <== Row: 1, 管理员, 1, 1, 2017-08-09 15:26:52.0, admin

TRACE [main] - <== Row: 2, 普通用户, 1, 1, 2017-08-09 15:26:52.0, admin

DEBUG [main] - <== Total: 2

DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@77ec78b9]

DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@77ec78b9]

DEBUG [main] - Returned connection 2011986105 to pool.

从输出的日志中我们可以很明显的看到增加了用户名的列数据。

总结:

① SELECT语句返回的数据只为一个对象(表)的数据,可以直接使用对象接收。

② SELECT语句返回的数据为多个对象(多个表)中的字段,此时可以新建一个类,包含所有要返回的字段,然后使用该类作为返回数据类型。

③ SELECT语句返回的数据包含大量的其他对象(表)的字段,则可以将额外字段所属对象最为属性,添加到主对象中,而后在配置Mapper.xml中的SQL语句时,采用“对象.属性”的方式作为别名,将值赋给额外的字段。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值