作者:whisper
链接:http://proprogrammar.com:443/article/778
声明:请尊重原作者的劳动,如需转载请注明出处
本人也没系统学习过mybatis,也并不了解mybatis的全貌,只是在工作中学习过别人的代码和了解过一些基本的知识,然后说一说工作中遇到过的问题及解决,也就是mybatis参数和返回值的问题,文章内容来源于网络,摘录下一些对自己有用的东西,只是大致介绍一下,具体内容请自己找资料查看
内容来源于:https://my.oschina.net/KingPan/blog/266650
可以接受的参数类型有基本类型和复杂类型。
mapper接口方法一般接受一个参数,可以通过使用@Param注释将多个参数绑定到一个map做为输入参数。
上面说了多个无关参数可以通过@Param来处理,下面来说一说一个参数的情况
Mapper中的接口方法:
public Posts getPostsById(int id);
sql映射:
<!-- 这里的id必须和PostsMapper接口中的接口方法名相同,不然运行的时候也要报错 -->
<select id="getPostsById" resultType="Posts" parameterType="int">
select * from posts where id=#{id}
</select>
对于简单数据类型,sql映射语句中直接#{变量名}这种方式引用就行了,其实这里的”变量名”可以是任意的。mapper接口方法传递过来的值,至于其叫什么名字其实是不可考也没必要知道的。
而且JAVA反射只能获取方法参数的类型,是无从得知方法参数的名字的。
传入JAVA复杂对象类型的话,sql映射语句中就可以直接引用对象的属性名了,这里的属性名是实实在在的真实的名字,不是随意指定的。
Mapper中的接口方法:
public void addPosts(Posts posts);
sql映射:
<insert id="addPosts" parameterType="Posts">
insert into posts(title,context) values(#{title},#{context})
<!-- 这里sql结尾不能加分号,否则报“ORA-00911”的错误 -->
</insert>
虽然可以明确的引用对象的属性名了,但如果要在if元素中测试传入的posts参数,仍然要使用_parameter来引用传递进来的实际参数,因为传递进来的Posts对象的名字是不可考的。如果测试对象的属性,则直接引用属性名字就可以了。
传入map类型,直接通过#{keyname}就可以引用到键对应的值。使用@param注释的多个参数值也会组装成一个map数据结构,和直接传递map进来没有区别。
Mapper接口:
int updateByExample(@Param("user") User user, @Param("example") UserExample example);
SQL映射:
<update id="updateByExample" parameterType="map" >
update tb_user
set id = #{user.id,jdbcType=INTEGER},
...
<if test="_parameter != null" >
<include refid="Update_By_Example_Where_Clause" />
</if>
注意这里测试传递进来的map是否为空,仍然使用_parameter
可以传递一个List或Array类型的对象作为参数,MyBatis会自动的将List或Array对象包装到一个Map对象中,List类型对象会使用list作为键名,而Array对象会用array作为键名。
集合类型通常用于构造IN条件,sql映射文件中使用foreach元素来遍历List或Array元素。
Mapper接口:
public void batchUpdate(List<Posts> list);
SQL映射:
<update id="batchUpdate" parameterType="java.util.List">
update posts set badcount=3,goodcount=5 where id in
<foreach collection="list" item="item" open="(" close=")" index="index" separator=",">
#{item.id}
</foreach>
</update>
对于单独传递的List或Array,在SQL映射文件中映射时,只能通过list或array来引用。但是如果对象类型有属性的类型为List或Array,则在sql映射文件的foreach元素中,可以直接使用属性名字来引用。
Mapper接口:
List<User> selectByExample(UserExample example);
SQL映射:
<where >
<foreach collection="oredCriteria" item="criteria" separator="or" >
<if test="criteria.valid" >
内容来源于:https://www.cnblogs.com/ye-feng-yu/p/10987587.html
mybatis的返回值有下面几种情况
1、mapper接口,我们简单查询所有记录,返回Long类型的值。
public interface PersonMapper
{
Long getTotalNumberOfPerson();
}
2、mapper映射文件
<select id="getTotalNumberOfPerson" resultType="long">
select count(*) from person
</select>
注意在mapper文件中,只需要 resultType 为 long 类型即可。
3、测试
public class Main
{
public static void main(String[] args)
throws IOException
{
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
Long totalNumberOfPerson= mapper.getTotalNumberOfPerson();
System.out.println(totalNumberOfPerson); //10
sqlSession.close();
}
}
这种查询直接返回和数据库表对应的相关实体,并且只有一条记录,一般都是按照id去查询,也就是第一节:mybatis入门中演示的样例,我们再次说明下。
1、mapper接口
public interface PersonMapper
{
Person getPerson(Integer id);
}
2、mapper映射文件
<select id="getPerson" resultType="com.yefengyu.mybatis.entity.Person">
select id, first_name firstName, last_name lastName, age, email, address from person where id = #{id}
</select>
3、测试
public class Main
{
public static void main(String[] args)
throws IOException
{
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
Person person = mapper.getPerson(1);
System.out.println(person);
sqlSession.close();
}
}
总结:在查询单个对象,返回的是实体类型的时候,只需要将resultType设置为全类名即可。
这种查询一般是根据某种条件,查询出很多个结果,然后使用List封装起来。
1、mapper接口,根据address查询多个Person对象
public interface PersonMapper
{
List<Person> getPersons(String address);
}
2、mapper映射文件,注意对于mapper接口中返回List类型的,mapper映射文件的resultType只需要设置List所包含的对象的类型即可。
<select id="getPersons" resultType="com.yefengyu.mybatis.entity.Person">
select id, first_name firstName, last_name lastName, age, email, address from person where address = #{address}
</select>
3、测试
public class Main
{
public static void main(String[] args)
throws IOException
{
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
List<Person> persons = mapper.getPersons("beijing");
for (int i = 0; i < persons.size(); i++)
{
System.out.println(persons.get(i));
}
sqlSession.close();
}
}
4、结果:
Person{id=1, firstName='Schmitt', lastName='Carine', age=25, email='null', address='beijing'}
Person{id=2, firstName='King', lastName='Jean', age=36, email='Jean@163.com', address='beijing'}
Person{id=8, firstName='Gao', lastName='Diego', age=45, email='66666@qq.com', address='beijing'}
Person{id=9, firstName='Piestrzeniewicz', lastName='Schmitt', age=36, email='44444@qq.com', address='beijing'}
Person{id=10, firstName='Frdrique', lastName='Juri', age=25, email='99999@qq.com', address='beijing'}
这里说一下,并不一定要对应一个java对象,这里使用map的key(列名),value(列值)形式就是一种比较自由的方式了
这种情况,类似第二小节,也是单个对象,只不过我们需要返回的是一个map,将单个对象封装成map,数据库的列名对应的属性名称作为key,返回的结果作为value.
1、mapper接口
public interface PersonMapper
{
Map<String, Object> getPersonMap(Integer id);
}
2、mapper映射文件,此时需要把resultType设置为map
<select id="getPersonMap" resultType="map">
select id, first_name firstName, last_name lastName, age, email, address from person where id = #{id}
</select>
3、测试
public class Main
{
public static void main(String[] args)
throws IOException
{
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
Map<String, Object> personMap = mapper.getPersonMap(1);
System.out.println(personMap);
sqlSession.close();
}
}
4、结果如下,注意在使用map接收返回值的时候,如果某个字段为null,那么就不会封装到map中,比如下面的结果中就没有Email字段的结果。
{firstName=Schmitt, lastName=Carine, address=beijing, id=1, age=25}
这个情况,一般是查询多条记录,使用主键作为key,使用对象作为value,见下面mapper接口。
1、mapper接口
public interface PersonMapper
{
@MapKey("id")
Map<Integer, Person> getPersonsMap(String address);
}
2、mapper映射文件
<select id="getPersonsMap" resultType="map">
select id, first_name firstName, last_name lastName, age, email, address from person where address = #{address}
</select>
3、测试
public class Main
{
public static void main(String[] args)
throws IOException
{
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
Map<Integer, Person> personMap = mapper.getPersonsMap("beijing");
for (Map.Entry<Integer, Person> personEntry : personMap.entrySet())
{
System.out.println(personEntry.getKey() + " : " + personEntry.getValue());
}
sqlSession.close();
}
}
4、结果
1 : {firstName=Schmitt, lastName=Carine, address=beijing, id=1, age=25}
2 : {firstName=King, lastName=Jean, address=beijing, id=2, age=36, email=Jean@163.com}
8 : {firstName=Gao, lastName=Diego, address=beijing, id=8, age=45, email=66666@qq.com}
9 : {firstName=Piestrzeniewicz, lastName=Schmitt, address=beijing, id=9, age=36, email=44444@qq.com}
10 : {firstName=Frdrique, lastName=Juri, address=beijing, id=10, age=25, email=99999@qq.com}
注意:mapper接口需要使用MapKey注解指定将某个属性的值作为map的key。本例中使用person表的主键id对应的实体的属性id作为key。除此之外,mapper映射文件中resultType设置为map。此外如果某个字段为null,那么就不插入到map中。
我在看mybatis文档的时候还看到一种ResultSets多结果集的情况,这里也说一下,看一下官方文档是怎么说的
属性 | 描述 |
---|---|
column | 当使用多个结果集时,该属性指定结果集中用于与 foreignColumn 匹配的列(多个列名以逗号隔开),以识别关系中的父类型与子类型。 |
foreignColumn | 指定外键对应的列名,指定的列将与父类型中 column 的给出的列进行匹配。 |
resultSet | 指定用于加载复杂类型的结果集名字。 |
从版本 3.2.3 开始,MyBatis 提供了另一种解决 N+1 查询问题的方法。
某些数据库允许存储过程返回多个结果集,或一次性执行多个语句,每个语句返回一个结果集。 我们可以利用这个特性,在不使用连接的情况下,只访问数据库一次就能获得相关数据。
在例子中,存储过程执行下面的查询并返回两个结果集。第一个结果集会返回博客(Blog)的结果,第二个则返回作者(Author)的结果。
SELECT * FROM BLOG WHERE ID = #{id}
SELECT * FROM AUTHOR WHERE ID = #{id}
在映射语句中,必须通过 resultSets 属性为每个结果集指定一个名字,多个名字使用逗号隔开。
<select id="selectBlog" resultSets="blogs,authors" resultMap="blogResult" statementType="CALLABLE">
{call getBlogsAndAuthors(#{id,jdbcType=INTEGER,mode=IN})}
</select>
现在我们可以指定使用 “authors” 结果集的数据来填充 “author” 关联:
<resultMap id="blogResult" type="Blog">
<id property="id" column="id" />
<result property="title" column="title"/>
<association property="author" javaType="Author" resultSet="authors" column="author_id" foreignColumn="id">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="password" column="password"/>
<result property="email" column="email"/>
<result property="bio" column="bio"/>
</association>
</resultMap>
对于这种属性为复杂数据类型或者集合类型的,可以用association和collection
亲爱的读者:有时间可以点赞评论一下
全部评论