Mybatis高级查询要点
1、resultMap与resultType:
resultType: 将查询结果按照sql列名pojo属性名一致性映射到pojo中。
场合:常见一些明细记录的展示,比如用户购买商品明细,将关联查询信息全部展示在页面时,此时可直接使用resultType将每一条记录映射到pojo中,在前端页面遍历list(list中是pojo)即可。
resultMap:使用association和collection完成一对一和一对多高级映射(对结果有特殊的映射要求)。
2、association
作用: 将关联查询信息映射到一个pojo对象中。(一个对象)
场合:为了方便查询关联信息可以使用association将关联订单信息映射为用户对象的pojo属性中,比如:查询订单及关联用户信息。使用resultType无法将查询结果映射到pojo对象的pojo属性中,根据对结果集查询遍历的需要选择使用resultType还是resultMap。
3、collection
作用:将关联查询信息映射到一个list集合中。
场合:为了方便查询遍历关联信息可以使用collection将关联信息映射到list集合中,比如:查询用户权限范围模块及模块下的菜单,可使用collection将模块映射到模块list中,将菜单列表映射到模块对象的菜单list属性中,这样的作的目的也是方便对查询结果集进行遍历查询。
数据库准备
四张表:书籍表、书籍详细信息表、作者表、读者表
四表关系:一本书对一个作者,一本书对多个详细信息,多个书籍详细信息对多个读者
完成数据库编辑后运行***GeneratorUtils.java***得到下面效果:
注意:
1.由MBG生成的domain包存放的是实体类文件,Mapper包存放的是Java客户端代码文件(也就是Mapper接口文件),resources目录下的Mapper包存放的是sql映射文件(xxxMapper.xml);而Utils包是自己新建的包,可用于存放工具类文件如:刚刚运行代码生成器的Java文件GeneratorUtils.java;
2.代码生成器的相关配置可参考本人上一个博客;
MBG代码生成器
高级查询的实现(以实体类Book为例)
1.首先在实体类Book添加 bookdetails,writer,reader对象
代码如下:
package com.ice.mybatis.domain;
public class Book {
private Long bookId;
private String bookName;
//书籍详细信息
private Bookdetails bookdetails;
//读者信息
private Reader reader;
//作者信息
private Writer writer;
public Bookdetails getBookdetails() {
return bookdetails;
}
public void setBookdetails(Bookdetails bookdetails) {
this.bookdetails = bookdetails;
}
public Reader getReader() {
return reader;
}
public void setReader(Reader reader) {
this.reader = reader;
}
public Writer getWriter() {
return writer;
}
public void setWriter(Writer writer) {
this.writer = writer;
}
public Long getBookId() {
return bookId;
}
public void setBookId(Long bookId) {
this.bookId = bookId;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName == null ? null : bookName.trim();
}
}
2.在接口BookMapper.java中定义新的查询方法
代码如下·:
package com.ice.mybatis.Mapper;
import com.ice.mybatis.domain.Book;
import java.util.List;
public interface BookMapper {
int deleteByPrimaryKey(Long bookId);
int insert(Book record);
Book selectByPrimaryKey(Long bookId);
List<Book> selectAll();
int updateByPrimaryKey(Book record);
//添加如下方法
//一对一
public Book selectbookandwriter(Integer id);
//一对多
public Book selectbookandbookdetails(Integer id);
//多对多
public List<Book> selectbookdetailsandreader(Integer id);
}
3.在sql映射文件BookMapper.xml中配置实现一对一,一对多,多对多查询相关代码
如修改resultMap标签,添加sql语句;
注意:
(1)书对作者是是一个一对一的关系,使用association
(2) 书对书的详细信息是一个一对多的关系,使用collection
(3)多个书籍详细信息对多个读者是一个多对多关系,也可以使用collection*
BookMapper.xml代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ice.mybatis.Mapper.BookMapper">
<resultMap id="BaseResultMap" type="com.ice.mybatis.domain.Book">
<id column="book_id" jdbcType="BIGINT" property="bookId" />
<result column="book_name" jdbcType="VARCHAR" property="bookName" />
<!--查询书关联查询作者信息 书对作者是是一个一对一的关系,使用association-->
<!--关联到作者的信息-->
<association javaType="com.ice.mybatis.domain.Writer" property="writer">
<id column="book_id" jdbcType="BIGINT" property="bookId" />
<id column="writer_id" jdbcType="BIGINT" property="writerId" />
<result column="book_name" jdbcType="VARCHAR" property="bookName" />
</association>
<!--查询书关联查询书的详细信息, 书对书的详细信息是一个一对多的关系,使用collection-->
<collection ofType="com.ice.mybatis.domain.Bookdetails" property="bookdetails">
<id column="book_id" jdbcType="BIGINT" property="bookId" />
<id column="writer_id" jdbcType="BIGINT" property="writerId" />
<result column="book_type" jdbcType="VARCHAR" property="bookType" />
<result column="book_name" jdbcType="VARCHAR" property="bookName" />
<result column="book_writer" jdbcType="VARCHAR" property="bookWriter" />
<result column="book_price" jdbcType="VARCHAR" property="bookPrice" />
<result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
</collection>
<collection ofType="com.ice.mybatis.domain.Reader" property="reader">
<id column="reader_id" jdbcType="BIGINT" property="readerId" />
<id column="book_id" jdbcType="BIGINT" property="bookId" />
<result column="reader_name" jdbcType="VARCHAR" property="readerName" />
<result column="book_name" jdbcType="VARCHAR" property="bookName" />
</collection>
</resultMap>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
delete from book
where book_id = #{bookId,jdbcType=BIGINT}
</delete>
<insert id="insert" parameterType="com.ice.mybatis.domain.Book">
insert into book (book_id, book_name)
values (#{bookId,jdbcType=BIGINT}, #{bookName,jdbcType=VARCHAR})
</insert>
<update id="updateByPrimaryKey" parameterType="com.ice.mybatis.domain.Book">
update book
set book_name = #{bookName,jdbcType=VARCHAR}
where book_id = #{bookId,jdbcType=BIGINT}
</update>
<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
select book_id, book_name
from book
where book_id = #{bookId,jdbcType=BIGINT}
</select>
<select id="selectAll" resultMap="BaseResultMap">
select book_id, book_name
from book
</select>
<!--一对一-->
<select id="selectbookandwriter" resultType="com.ice.mybatis.domain.Book">
select*from book,writer where book.book_id= writer.book_id and book.book_id=#{id}
</select>
<!--一对多-->
<select id="selectbookandbookdetails" resultType="com.ice.mybatis.domain.Book">
select*from book,bookdetails where book.book_id=bookdetails.book_id and book.book_id=#{id}
</select>
<!--多对多 书的详细信息对书的读者-->
<select id="selectbookdetailsandreader" resultType="com.ice.mybatis.domain.Book">
select*from bookdetails,reader where bookdetails.book_id=reader.book_id and bookdetails.book_id=#{id}
</select>
</mapper>
4.resources目录添加mybatis全局配置核心文件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">
<!-- mybatis的主配置文件 -->
<configuration>
<!--指定properties文件的路径-->
<properties resource="jdbc.properties"/>
<!--控制mybatis全局行为-->
<settings>
<!--设置输出日志-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!-- 配置环境 -->
<environments default="mysql">
<!-- 配置mysql的环境-->
<environment id="mysql">
<!-- 配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源(连接池) -->
<dataSource type="POOLED">
<!-- 配置连接数据库的4个基本信息 -->
<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>
<!-- 指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件 -->
<mappers>
<mapper resource="com/ice/mybatis/Mapper/BookMapper.xml"/>
</mappers>
</configuration>
5.在src/test/java/com/ice/mybatis路径下新建测试类mybatisTest.java用于实现查询功能
代码如下:
package com.ice.mybatis;
import com.ice.mybatis.Mapper.BookMapper;
import com.ice.mybatis.Utils.mybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
public class mybatisTest {
int a=1,
b=2,
c=3;
@Test
//一对一查询,一本书对一个作者
public void selectbookandwriter(){
SqlSession sqlSession= mybatisUtils.getSqlsession();
BookMapper bookMapper=sqlSession.getMapper(BookMapper.class);
bookMapper.selectbookandwriter(a);
}
@Test
//一对多查询,一本书对书的详细信息
public void selectbookandbookdetails(){
SqlSession sqlSession=mybatisUtils.getSqlsession();
BookMapper bookMapper=sqlSession.getMapper(BookMapper.class);
bookMapper.selectbookandbookdetails(b);
}
@Test
//多对多查询,书的详细信息对书的读者
public void selectbookdetailsandreader(){
SqlSession sqlSession=mybatisUtils.getSqlsession();
BookMapper bookMapper=sqlSession.getMapper(BookMapper.class);
bookMapper.selectbookdetailsandreader(c);
}
}
以为到这里就完成了吗?
工具类mybatisUtils的实现
好处:由于创建 sqlsessionfactory对象会耗时较长,使用资源较多,整个项目一个足以,使用mybatis工具类可以解决这个问题,简化繁琐的代码
在Utils包新建工具类文件mybatisUtils.java
代码如下:
package com.ice.mybatis.Utils;
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 java.io.IOException;
import java.io.InputStream;
public class mybatisUtils {
private static SqlSessionFactory factory=null;
static {
String comfig="SqlMapConfig.xml";
try {
InputStream in=Resources.getResourceAsStream(comfig);
factory=new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlsession(){
SqlSession sqlSession =null;
if(factory!=null){
sqlSession=factory.openSession();//非自动提交事务
}
return sqlSession;
}
}
以下是运行结果
分别是一对多,一对一,多对多的查询