像多对多的数据表关系,比如检查套餐包含检查组,检查组包含检查项,我要想做一个setmeal对象包含groupList,而gropu有itemList,写mybatis的sql怎么写,而用mybatisPlus在java代码里应该怎么写
对于多对多的数据表关系,在 MyBatis 中,通常会使用三张表来表示。以你提到的检查套餐包含检查组、检查组包含检查项为例,我们可以使用如下三张表来表示:
1. 检查套餐表:t_setmeal,包含检查套餐的基本信息,如套餐名称、价格等等。
2. 检查组表:t_checkgroup,用于表示一个检查套餐中的一个检查组,一个套餐可以对应多个检查组。
3. 检查项表:t_checkitem,用于表示一个检查组中的一个检查项,一个检查组可以对应多个检查项。
下面分别介绍在 MyBatis 和 MyBatis-Plus 中,如何写 SQL 语句来查询检查套餐及其包含的检查组和检查项信息。
## 在 MyBatis 中实现
### 查询检查套餐及其包含的检查组和检查项```xml
<select id="findSetmealById" resultMap="setmealResultMap">
SELECT s.id, s.name, s.code, s.helpCode, s.sex, s.age, s.price, s.remark, s.attention, s.img,
g.id AS groupId, g.name AS groupName,
i.id AS itemId, i.name AS itemName
FROM t_setmeal s
LEFT JOIN t_setmeal_checkgroup sc ON s.id = sc.setmeal_id
LEFT JOIN t_checkgroup g ON sc.checkgroup_id = g.id
LEFT JOIN t_checkgroup_checkitem gi ON g.id = gi.checkgroup_id
LEFT JOIN t_checkitem i ON gi.checkitem_id = i.id
WHERE s.id = #{id}
</select>
<resultMap id="setmealResultMap" type="Setmeal">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="code" column="code"/>
<result property="helpCode" column="helpCode"/>
<result property="sex" column="sex"/>
<result property="age" column="age"/>
<result property="price" column="price"/>
<result property="remark" column="remark"/>
<result property="attention" column="attention"/>
<result property="img" column="img"/>
<collection property="groupList" ofType="CheckGroup">
<id property="id" column="groupId" />
<result property="name" column="groupName" />
<collection property="itemList" ofType="CheckItem">
<id property="id" column="itemId" />
<result property="name" column="itemName" />
</collection>
</collection>
</resultMap>
```
上面的 SQL 语句使用了 JOIN 多张表,通过 LEFT JOIN 的方式来查询出检查套餐、检查组和检查项之间的关系。其中 resultMap 定义了映射结果,包含了检查套餐、检查组和检查项的信息,并通过 collection 标签来定义了集合类型的属性,把检查组和检查项映射到检查套餐中。
## 在 MyBatis-Plus 中实现
MyBatis-Plus 提供了比 MyBatis 更加简便的使用方式,可以通过实体对象直接进行 CRUD 操作,无需手写 SQL。以下简述如何通过 MyBatis-Plus 实现上面所述的功能。
### 查询检查套餐及其包含的检查组和检查项
为了方便操作,我们需要创建与实体类对应的 Mapper 接口和 Service 接口,并继承 MyBatis-Plus 提供的基类。以下是针对 t_setmeal 表的代码示例:```java
public interface SetmealMapper extends BaseMapper<Setmeal> {
}
public interface SetmealService extends IService<Setmeal> {
Setmeal findSetmealById(Long id);
}
@Service
public class SetmealServiceImpl extends ServiceImpl<SetmealMapper, Setmeal> implements SetmealService {
@Override
public Setmeal findSetmealById(Long id) {
Setmeal setmeal = baseMapper.selectById(id);
List<CheckGroup> groupList = baseMapper.findGroupListBySetmealId(id);
for (CheckGroup group : groupList) {
List<CheckItem> checkItemList = baseMapper.findItemListByGroupId(group.getId());
group.setItemList(checkItemList);
}
setmeal.setGroupList(groupList);
return setmeal;
}
}
```
在上面的代码中,我们利用了 MyBatis-Plus 提供的 BaseMapper 接口和 ServiceImpl 类,简便地实现了 t_setmeal 表的 CRUD 操作,并且通过自定义方法 findSetmealById 来查询检查套餐及其包含的检查组和检查项信息。findSetmealById 方法中使用了两个自定义方法 findGroupListBySetmealId 和 findItemListByGroupId,分别查询检查套餐包含的检查组和检查组包含的检查项信息。
关于如何实现这两个自定义方法,以下是 MyBatis XML Mapper 的代码示例:```xml
<select id="findGroupListBySetmealId" resultMap="BaseResultMap">
SELECT g.*
FROM t_setmeal_checkgroup sc
LEFT JOIN t_checkgroup g ON sc.checkgroup_id = g.id
WHERE sc.setmeal_id = #{id,jdbcType=INTEGER}
</select>
<select id="findItemListByGroupId" resultMap="BaseResultMap">
SELECT i.*
FROM t_checkgroup_checkitem gi
LEFT JOIN t_checkitem i ON gi.checkitem_id = i.id
WHERE gi.checkgroup_id = #{id,jdbcType=INTEGER}
</select>
```
上面的自定义方法使用了两个 SQL 语句,分别查询检查组和检查项的信息,并通过 resultMap 定义了映射结果。
最后,我们通过调用 SetmealService 中的 findSetmealById 方法来查询检查套餐及其包含的检查组和检查项信息。MyBatis-Plus 会自动进行对象的映射操作,将查询结果映射成对应的实体类对象。
好的,以下是使用 MyBatis-Plus 实现的 `findSetmealById` 方法:```java
@Service
public class SetmealServiceImpl extends ServiceImpl<SetmealMapper, Setmeal> implements SetmealService {
@Autowired
private CheckGroupMapper checkGroupMapper;
@Autowired
private CheckItemMapper checkItemMapper;
@Override
public Setmeal findSetmealById(Long id) {
Setmeal setmeal = this.getById(id);
// 查询所有关联的检查组对象
List<CheckGroup> groupList = checkGroupMapper.selectList(new QueryWrapper<CheckGroup>().inSql("id", "select checkgroup_id from t_setmeal_checkgroup where setmeal_id = "+id));
for (CheckGroup group : groupList) {
// 查询所有关联的检查项对象
List<CheckItem> itemList = checkItemMapper.selectList(new QueryWrapper<CheckItem>().inSql("id", "select checkitem_id from t_checkgroup_checkitem where checkgroup_id = "+group.getId()));
group.setItemList(itemList);
}
setmeal.setGroupList(groupList);
return setmeal;
}
}
```
在上述代码中,我们通过 `this.getById(id)` 方法来查询指定 ID 的检查套餐对象 `setmeal`。然后,我们通过 `checkGroupMapper.selectList` 方法,根据检查套餐与检查组之间的关系表(t_setmeal_checkgroup) 查询所有关联的检查组对象 `groupList`,并通过循环遍历每个检查组对象,再通过 `checkItemMapper.selectList` 方法,根据检查组与检查项之间的关系表(t_checkgroup_checkitem)查询所有关联的检查项对象,然后将检查项列表设置到检查组对象中,最后将检查组列表设置到检查套餐对象中,并返回它。
需要注意的是,在查询检查组和检查项的时候,我们使用了 `inSql` 方法,这是因为我们需要查询所有符合条件的对象,而不是只查询一个,而只使用 `eq` 等简单条件查询方法是无法实现的。
另外,需要在 `SetmealServiceImpl` 类中注入 `CheckGroupMapper` 和 `CheckItemMapper` 接口的实现类,这两个 Mapper 接口用于操作检查组表和检查项表。
如果要使用 MyBatis 实现以上代码逻辑,可以参考我之前回答你的问题时的答案。
好的,那么这里是使用 LambdaQueryWrapper 重写上述 `findSetmealById` 方法的示例代码:```java
@Service
public class SetmealServiceImpl extends ServiceImpl<SetmealMapper, Setmeal> implements SetmealService {
@Autowired
private CheckGroupMapper checkGroupMapper;
@Autowired
private CheckItemMapper checkItemMapper;
@Override
public Setmeal findSetmealById(Long id) {
Setmeal setmeal = this.getById(id);
// 使用 LambdaQueryWrapper 查询所有关联的检查组对象
List<CheckGroup> groupList = checkGroupMapper.selectList(new LambdaQueryWrapper<CheckGroup>()
.inSql(CheckGroup::getId, "select checkgroup_id from t_setmeal_checkgroup where setmeal_id = " + id));
// 遍历所有关联的检查组对象并查询所有关联的检查项对象
groupList.forEach(group -> {
List<CheckItem> itemList = checkItemMapper.selectList(new LambdaQueryWrapper<CheckItem>()
.inSql(CheckItem::getId, "select checkitem_id from t_checkgroup_checkitem where checkgroup_id = " + group.getId()));
group.setItemList(itemList);
});
setmeal.setGroupList(groupList);
return setmeal;
}
}
```
在上述代码中,我们在查询检查组和检查项时使用了 LambdaQueryWrapper。具体来说,我们使用 `inSql` 方法来实现子查询,使用 `LambdaQueryWrapper::inSql` 方法可以避免手写 SQL,使代码更加简洁易读。
另外,需要注意的是,在遍历所有关联的检查组对象时,我们使用了 Lambda 表达式进行函数式编程。lambda 表达式可以使代码更加简洁,易于维护。
需要提醒的是,要使用 LambdaQueryWrapper,需要在项目中引入 MyBatis-Plus 的 Lambda 模块。
```xml
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-extension</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
```
是的,`inSql()`是MyBatis-Plus中用于实现子查询的API之一。它允许我们嵌套一个子查询,将子查询的结果集作为查询条件之一,从而实现更加灵活和复杂的 SQL 查询。
使用 `inSql()` 时,我们需要先编写子查询语句,将结果集映射到某个字段或实体类中,再将子查询语句作为参数传递给 `inSql()` 方法中。例如:
```java
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.inSql("id", "select id from role where role_name like '管理员%'");
List<User> userList = userMapper.selectList(wrapper);
```
上述代码中,我们使用 `inSql()` 方法将一个子查询语句嵌套到主查询中。该子查询语句通过 `select id from role where role_name like '管理员%'` 获得一组角色ID,这些角色ID会作为过滤条件传递给 `inSql()` 方法中的第二个参数(即 `id` 字段)。该查询语句的意思是,查询角色名称以“管理员”开头的角色ID。由于 `inSql()` 方法本身不支持参数绑定,我们需要将子查询语句中的参数硬编码到语句中。文章来源:https://www.toymoban.com/news/detail-496733.html
值得一提的是,MyBatis-Plus 中还有其他用于实现子查询的 API,如 `apply()`和`exists()`等方法。这些 API 均可用于构建复杂的 SQL 查询,并能帮助我们提升查询效率和减少数据库压力。文章来源地址https://www.toymoban.com/news/detail-496733.html
到了这里,关于使用mybatisPlus的queryWrapper进行子查询(以及传统xml方式做leftjoin)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!