MyBatis多表查詢
在全局配置文件中中設置MyBatis執(zhí)行日志
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
1. 多表一對一查詢
假設有一個用戶表和文章表,實體類中一個關聯(lián)關系。
用戶實體類
@Getter
@Setter
@ToString
public class UserInfo {
private int id;
private String name;
private String password;
}
文章實體類
@Data
public class BlogInfo {
private int blogId;
private String title;
private String content;
private Integer userId;
private Timestamp postTime;
private String time;
private UserInfo userInfo;
}
如果想查詢的結果包含UserInfo的信息就需要使用,?對?映射要使? <association>
標簽,因為一篇文章只能對應一個作者。
Controller控制器代碼
@Controller
@ResponseBody
public class BlogController {
@Resource
private BlogService blogService;
@RequestMapping("/getAllBlog")
public List<BlogInfo> getAllBlog() {
return blogService.getAllBlog();
}
}
Service服務層代碼
@Service
public class BlogService {
@Resource
private BlogMapper blogMapper;
public List<BlogInfo> getAllBlog() {
return blogMapper.getAllBlog();
}
}
BlogMap接口定義
@Mapper
public interface BlogMapper {
List<BlogInfo> getAllBlog();
}
MyBatis接口實現(xiàn)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.example.demo.mapper.BlogMapper">
<resultMap id="BlogBean" type="com.example.demo.model.BlogInfo">
<!-- 映射主鍵 -->
<id column="blogId" property="blogId"></id>
<!-- 普通列映射(表字段->實體類) -->
<result column="title" property="title"></result>
<result column="content" property="content"></result>
<result column="userId" property="userId"></result>
<result column="postTime" property="postTime"></result>
<!-- 關聯(lián)關系 -->
<association property="userInfo"
resultMap="com.example.demo.mapper.UserMapper.UserBean"
columnPrefix="u_">
</association>
</resultMap>
<select id="getAllBlog" resultMap="BlogBean">
select u.userId u_userId,u.username u_username,b.blogId,b.title,b.postTime,b.userId from blog b left join user u on u.userId=b.userId
</select>
</mapper>
使用<association>
標簽,表示一對一的結果映射:
-
property
屬性:指定文章類BlogInfo
中對應的關聯(lián)屬性,也就是用戶實例userInfo
-
resultMap
屬性:指定的是關聯(lián)關系的結果集映射,也就是UserInfo對象的屬性和表之間的映射關系 -
columnPrefix
屬性:綁定一對一對象的時候,是通過columnPrefix
+association.resultMap.column
來映射結果集字段。association.resultMap.column
是指<association>
標簽中 resultMap屬性,對應的結果集映射中,column
字段 。
Postman測試打印的部分結果
[
{
"blogId": 2,
"title": "Java基礎",
"content": null,
"userId": 1,
"postTime": "2022-02-25T11:50:52.000+00:00",
"time": null,
"userInfo": {
"id": 1,
"name": "admin",
"password": null
}
},
{
"blogId": 5,
"title": "我的第一篇博客",
"content": null,
"userId": 1,
"postTime": "2022-02-25T14:05:22.000+00:00",
"time": null,
"userInfo": {
"id": 1,
"name": "admin",
"password": null
}
},
columnPrefix 如果省略,并且恰好兩個表中如果有相同的字段,那么就會導致查詢出錯
2. 多表一對多
一對多需要使用<collection>
標簽,用法和<association>
相同,比如說一個用戶可以發(fā)布多篇文章。
用戶實體類
@Getter
@Setter
@ToString
public class UserInfo {
private int id;
private String name;
private String password;
private List<BlogInfo> blogList;
}
映射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.example.demo.mapper.UserMapper">
<resultMap id="UserMap" type="com.example.demo.model.UserInfo">
<!-- 映射主鍵的(表中主鍵和程序實體類中的主鍵) -->
<id column="userId" property="id"></id>
<!-- 普通字段映射 -->
<result column="username" property="name"></result>
<result column="password" property="password"></result>
<!-- 外部關聯(lián)管理 -->
<collection property="blogList"
resultMap="com.example.demo.mapper.BlogMapper.BlogBean"
columnPrefix="b_">
</collection>
</resultMap>
<select id="getAll" resultMap="UserMap">
select u.userId,u.username,b.blogId b_blogId,b.title b_title,b.postTime b_postTime from user u left join blog b on u.userId=b.userId
</select>
</mapper>
-
property
屬性對應的是UserInfo類中的屬性blogList
Postman部分測試結果
動態(tài)SQL
動態(tài)SQL是MyBatis強大特征之一,在JDBC拼接SQL時候的痛處,不能忘記必要的空格添加,最后一個列名的逗號也要注意,利用動態(tài)SQL就能完成不同場景的SQL拼接。
MyBatis動態(tài)SQL
1.<if>標簽
在注冊某些賬號的填寫信息的時候,有必填項和非必填項,如果非必填項和少多寫個接口就好了,但如果非必填項非常多的話就不行了,這個時候就需要動態(tài)標簽<if>
來判斷了。
這里假設性別和年齡是非必填項。
接口定義
int logonUser(String name, String password, String sex, Integer age);
數(shù)據(jù)表
+----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(50) | NO | | NULL | |
| password | varchar(25) | NO | | NULL | |
| sex | varchar(10) | YES | | NULL | |
| age | int(11) | YES | | NULL | |
+----------+-------------+------+-----+---------+----------------+
注意if<test=>
是固定語法,里面的判斷的字段要和接口中定義的名字對應。
- 如果滿足條件才會添加
<if>
里的文字
<?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.example.demo.mapper.UserMapper">
<insert id="logonUser">
insert into userInfo(id,name,password
<if test="sex!=null">
,sex
</if>
<if test="age!=null">
,age
</if>
) value(null,#{name},#{password}
<if test="sex!=null">
,#{sex}
</if>
<if test="age!=null">
,#{age}
</if>
)
</insert>
</mapper>
如果age和sex都為null那么執(zhí)行的sql 就是
insert into userInfo(id,name,password ) value(null,?,? );
2.<trim>標簽
前面的新增用戶操作,age和sex可能是選填項,如果有多個字段,一般考慮用<trim>
標簽結合<if>
標簽,對多個字段都采用動態(tài)生成的方式
<trim>
標簽中有如下屬性
- prefix:它表示整個語句塊,以prefix的值作為前綴(在語句塊最前面添加prefix字符)
- suffix:它表示整個語句塊,以suffix的值作為后綴(在語句塊最后添加suffix字符)
- prefixOverrides:表示整個語句塊要去除掉的前綴(刪除語句塊最前面滿足條件的字符)
- suffixOverrides:表示整個語句塊要去除的后綴 (刪除語句塊最后面滿足條件的字符)
那么就可以將插入語句改成如下:
<?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.example.demo.mapper.UserMapper">
<insert id="logonUser">
insert into userInfo
<trim prefix="(" suffix=")" suffixOverrides=",">
id,name,password,
<if test="sex!=null">
sex,
</if>
<if test="age!=null">
age
</if>
</trim>
value
<trim prefix="(" suffix=")" suffixOverrides=",">
null,#{name},#{password},
<if test="sex!=null">
#{sex},
</if>
<if test="age!=null">
#{age}
</if>
</trim>
</insert>
</mapper>
假設調用接口的代碼是
userMapper.logonUser("張輝","123456","男",null);
最后執(zhí)行的SQL就是
insert into userInfo ( id,name,password, sex ) value ( null,?,?, ? )
- 基于prefix 配置,開始部分加上
(
- 基于suffix 配置,結束部分加上
)
- 多個
if
都已,
結尾,使用suffixOverrides就可以把末尾的,
給去掉
3. <where>標簽
在使用查詢語句的時候,如果有多個條件就會用到邏輯運算,如果有些條件不滿足就會出現(xiàn)and前面沒有條件判,導致sql報錯
select * from userInfo where and sex!=null and age!=null;
使用<where>
就可以很好的解決這個問題
- 生成where,如果有查詢條件就會生成where,如果沒有查詢條件就會忽略where
- where會判斷第一個查詢條件前面有沒有and,如果有則會刪除
查找接口定義
List<User> findAllUser(String sex, int age);
<?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.example.demo.mapper.UserMapper">
<select id="findAllUser" resultType="com.example.demo.model.User">
select * from userInfo
<where>
<if test="sex!=null">
sex=#{sex}
</if>
<if test="age!=null">
and age=#{age}
</if>
</where>
</select>
</mapper>
以上<where>標簽也可以使 <trim prefix=“where” prefixOverrides="and> 替換
4.<set>標簽
根據(jù)傳入的用戶對象屬性來更新用戶數(shù)據(jù),可以使用<set>
標簽來指定動態(tài)內容.
示例:
根據(jù)用戶Id來修改其它不為null的屬性
接口定義
int updateUserId(User user);
xml文件的接口實現(xiàn)
-
<set>
也是會自動去除末尾的,
的 -
<set>
標簽也可以使?<trim prefix="set" suffixOverrides=",">
替換
<?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.example.demo.mapper.UserMapper">
<update id="updateUserId">
update userInfo
<set>
<if test="name!=null">
name=#{name},
</if>
<if test="password!=null">
password=#{password},
</if>
<if test="sex!=null">
sex=#{sex},
</if>
<if test="age!=null">
age=#{age},
</if>
</set>
where id=#{id}
</update>
</mapper>
最后拼接的SQL
update userInfo SET name=?, password=?, sex=?, age=? where id=?
5. <foreach>標簽
對集合遍歷的時候可以使用該標簽,<foreach
標簽有以下屬性:
- conection:綁定方法中的集合,如 List、Set、Map或者數(shù)組對象
- item:遍歷時的每一個對象
- open:語句塊開頭的字符串
- close:語句塊結束的字符串
- separtor:每次遍歷之間間隔的字符串
假設要通過多個用戶id刪除多個用戶
接口定義和測試代碼
@Mapper
public interface UserMapper {
// 方法定義
int deleteListId(List<Integer> listId);
}
@SpringBootTest
class UserMapperTest {
@Resource
private UserMapper userMapper;
@Test
void deleteListId() {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
userMapper.deleteListId(list);
}
}
xml文件文章來源:http://www.zghlxwxcb.cn/news/detail-418393.html
<?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.example.demo.mapper.UserMapper">
<delete id="deleteListId">
delete from userInfo where id in
<foreach collection="listId" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</delete>
</mapper>
我的list集合里有3個用戶Id,最后拼裝的SQL文章來源地址http://www.zghlxwxcb.cn/news/detail-418393.html
delete from userInfo where id in ( ? , ? , ? )
到了這里,關于MyBatis多表查詢+動態(tài)sql的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!