springboot之聯(lián)表查詢方式
springboot 聯(lián)表查詢
業(yè)務(wù)分析
在開(kāi)發(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ù)每次連接開(kāi)銷(xiāo)較大,第二種與數(shù)據(jù)庫(kù)進(jìn)行了多次連接,而第一種與數(shù)據(jù)庫(kù)只需交互一次,效率較高。
第一種
直接sql做join連接,在數(shù)據(jù)庫(kù)層面聯(lián)表查詢。
集成mybatis,編寫(xiě)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)查表,效率太低,不推薦)
這種辦法沒(méi)有在本博客中刪除是因?yàn)橄刖咀约?。這是本人初學(xué)時(shí)自己摸索的辦法,那會(huì)剛?cè)腴T(mén),沒(méi)有領(lǐng)路人走了許多彎路,能寫(xiě)出方法二的爛套路就能窺見(jiàn)一二,當(dāng)時(shí)曾記得寫(xiě)出這洋洋灑灑的文章自己還怡然自得。
時(shí)隔幾年才改正確是不該,因此添加了方法一,之前寫(xiě)的這方法二現(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 重寫(xiě)方法 編寫(xiě)業(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)沒(méi)有Java 8選項(xiàng),只有Java 17和Java 20,解決方法包括:通過(guò)修改服務(wù)器URL(推薦)或直接在創(chuàng)建后修改pom.xml文件中的Spring Boot和Java版本2025-01-01java通過(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以銀行取錢(qián)為例模擬Java多線程同步問(wèn)題完整代碼
這篇文章主要介紹了以銀行取錢(qián)為例模擬Java多線程同步問(wèn)題完整代碼,具有一定借鑒價(jià)值,需要的朋友可以參考下。2017-12-12