springboot之聯(lián)表查詢方式
springboot 聯(lián)表查詢
業(yè)務(wù)分析
在開發(fā)管理系統(tǒng)時(shí),遇到需要將 User 和 對(duì)應(yīng)的 Organization 聯(lián)表查詢起來(lái),找到用戶所對(duì)應(yīng)的組織信息
數(shù)據(jù)庫(kù)
- user表中字段有:user_id、user_name、user_age、user_org_id
- organization表字段有:org_id、org_name
entity包下的User類
@Data
public class User{
private Integer userId;
private String userName;
private Integer userAge;
private Integer userOrgId;
}entity包下的Organization類
@Data
public class Organization{
private Integer orgId;
private String orgName;
}已有的user對(duì)象并不滿足查詢需求,我們需要得到這樣一個(gè)包裝的對(duì)象以便查詢下列信息:
user_id、user_name、user_age、user_org_name
故,此業(yè)務(wù)場(chǎng)景下可以引入vo
創(chuàng)建 vo 包下 UserVo類
@Data
public class UserVo{
private Integer userId;
private String userName;
private Integer userAge;
private Organization organization; //注意這里的數(shù)據(jù)類型和名稱
}兩種辦法
推薦第一種,因?yàn)閿?shù)據(jù)庫(kù)每次連接開銷較大,第二種與數(shù)據(jù)庫(kù)進(jìn)行了多次連接,而第一種與數(shù)據(jù)庫(kù)只需交互一次,效率較高。
第一種
直接sql做join連接,在數(shù)據(jù)庫(kù)層面聯(lián)表查詢。
集成mybatis,編寫userMapper.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.xxx.mapper.UserMapper">
<resultMap id="organizationResult" type="organization">
<id property="orgId" column="org_id" />
<result property="orgName" column="org_name" />
</resultMap>
<resultMap type="UserVo" id="UserVoList">
<id property="userId" column="user_id" />
<result property="userName" column="user_name" />
<result property="userAge" column="user_age" />
<association property="organization" javaType="organization" resultMap="organizationResult" />
</resultMap>
<select id="selectUserVoList" resultMap="UserVoList">
SELECT u.user_id,
u.user_name,
u.user_age,
o.org_id,
o.org_name
FROM user u
LEFT JOIN organization o
WHERE u.user_org_id = o.org_id
</select>public List<UserVo> selectUserVoList();
上述代碼是偽代碼,如果錯(cuò)誤,歡迎指正,大致思想是這樣的。
第二種
數(shù)據(jù)庫(kù)層面單表查詢 (循環(huán)查表,效率太低,不推薦)
這種辦法沒有在本博客中刪除是因?yàn)橄刖咀约?。這是本人初學(xué)時(shí)自己摸索的辦法,那會(huì)剛?cè)腴T,沒有領(lǐng)路人走了許多彎路,能寫出方法二的爛套路就能窺見一二,當(dāng)時(shí)曾記得寫出這洋洋灑灑的文章自己還怡然自得。
時(shí)隔幾年才改正確是不該,因此添加了方法一,之前寫的這方法二現(xiàn)在看看確實(shí)是屎山,或許在過(guò)幾年回過(guò)頭看方法一又是另外的風(fēng)景。在此感謝評(píng)論區(qū)的指正,以后定當(dāng)不斷回顧,保持一顆學(xué)徒的心態(tài)繼續(xù)積累。
創(chuàng)建 vo 包下 UserVo類
@Data
public class UserVo{
private Integer userId;
private String userName;
private Integer userAge;
private Integer orgId; //注意這里的數(shù)據(jù)類型和名稱
}在 service 包下的 UserService 接口定義查詢方法
public interface UserService extends IService<User> {
public List<UserVo> voList(); //定義一個(gè)返回我們需要得到的包裝對(duì)象方法 返回的是UserVo泛型的List集合
}在 service\impl 包下的 UserServiceImpl 重寫方法 編寫業(yè)務(wù)邏輯
首先要明白:我們需要的 UserVo類中信息有兩部分,一部分是來(lái)自于User類,另外一部分是來(lái)自于根據(jù)User類的organizationId查詢到的對(duì)應(yīng)的Organization的name信息。
因此我們需要首先將UserMapper注入,通過(guò)UserMapper類中的 selectList 方法(傳入條件為空)查詢出所有的User信息
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Resource
private UserMapper userMapper;
@Override
public List<UserVo> voList() {
List<User> userList = this.userMapper.selectList(null); //封裝的是一個(gè)User泛型的List集合
}此時(shí)userList集合中有了所有的user信息(user_id,user_name,user_age,user_org_id),接下來(lái)我們對(duì) userList 進(jìn)行遍歷,拿出user_org_id查詢所有對(duì)應(yīng)的組織名稱 ==這一步操作=> userList.getUserOrgId(),這里就需要注入 OrganizationMapper ,通過(guò)this.organizationMapper.selectOne()方法進(jìn)行條件查詢
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Resource
private UserMapper userMapper;
@Resource
private OrganizationMapper organizationMapper;
@Override
public List<UserVo> voList() {
List<User> userList = this.userMapper.selectList(null); //封裝的是一個(gè)User泛型的List集合
for (User user : userList) { //重命名了userList集合
QueryWrapper<Organization> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("org_id",user.getUserOrgId()); //比較數(shù)據(jù)庫(kù)中org_id與傳入的用戶所屬組織ID
Organization org = this.organizationMapper.selectOne(queryWrapper); //將條件傳入就能拿到一個(gè)組織信息
org.getOrgName() //通過(guò)get就能拿到這個(gè)組織信息中的名稱信息
}
} //此時(shí)我們有了user信息,以及user對(duì)應(yīng)的組織名稱信息,接下來(lái)我們只需要封裝就可以封裝UserVo
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Resource
private UserMapper userMapper;
@Resource
private OrganizationMapper organizationMapper;
@Override
public List<UserVo> voList() {
List<User> userList = this.userMapper.selectList(null);
UserVo userVo = null; //定義一個(gè)userVo對(duì)象
for (User user : userList) {
userVo = new UserVo(); //每次循環(huán)創(chuàng)建一個(gè)新的vo對(duì)象。下面就是給這個(gè)vo對(duì)象存值
BeanUtils.copyProperties(user,userVo); //復(fù)制屬性
QueryWrapper<Organization> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("org_id",user.getUserOrgId())
Organization org = this.organizationMapper.selectOne(queryWrapper);
userVo.setOrgName(org.getOrgName()); //將組織名稱信息賦值給userVo中的OrgName
}
}
}注意這里每次封裝的是一條UserVo信息,因此我們還需要?jiǎng)?chuàng)建一個(gè)數(shù)組,存儲(chǔ)每次封裝好的UserVo
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Resource
private UserMapper userMapper;
@Resource
private OrganizationMapper organizationMapper;
@Override
public List<UserVo> voList() {
List<User> userList = this.userMapper.selectList(null);
UserVo userVo = null;
List<UserVo> result = new ArrayList<>(); //最終需要返回的結(jié)果集合
for (User user : userList) {
userVo = new UserVo();
BeanUtils.copyProperties(user,userVo);
QueryWrapper<Organization> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("org_id",user.getUserOrgId())
Organization org = this.organizationMapper.selectOne(queryWrapper);
userVo.setOrgName(org.getOrgName());
result.add(userVo); //每次userVo封裝好,就把它加到result集合中
}
return result; //將結(jié)果集返回
}
}controller層調(diào)用
@RestController
@RequestMapping("/user")
public class UserController {
@Resource
private UserService userService; //注入userService
@GetMapping("/list")
public List<UserVo> voList(){
return this.userService.voList();
}
}總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Idea創(chuàng)建springboot不能選擇java8的解決
在IDEA 2023版本創(chuàng)建Spring Boot項(xiàng)目時(shí),發(fā)現(xiàn)沒有Java 8選項(xiàng),只有Java 17和Java 20,解決方法包括:通過(guò)修改服務(wù)器URL(推薦)或直接在創(chuàng)建后修改pom.xml文件中的Spring Boot和Java版本2025-01-01
java通過(guò)SSE實(shí)現(xiàn)消息推送
這篇文章主要為大家詳細(xì)介紹了java如何通過(guò)SSE實(shí)現(xiàn)消息推送功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-11-11
使用spring-task定時(shí)任務(wù)動(dòng)態(tài)配置修改執(zhí)行時(shí)間
這篇文章主要介紹了使用spring-task定時(shí)任務(wù)動(dòng)態(tài)配置修改執(zhí)行時(shí)間,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11

