MybatisPlus+Postgresql整合的几个坑

本文介绍如何将用户管理服务从MySQL迁移到PostgreSQL,并与MyBatis框架进行整合。文章详细记录了配置过程、自增字段的实现方式、递归获取单位树列表的方法及如何使用递归查询获取单位下的所有用户。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近把用户管理服务切换成PostgreSql数据库,和Mybatis整合时遇到了几个坑,记录一下。

基础设置

application.yml设置,注意schema的设置

spring:
  datasource:
    platform: postgres
    url: jdbc:postgresql://192.188.1.245:5432/uum?currentSchema=uum
    schemaName: uum
    username: xxxx
    password: xxxx
    driver-class-name: org.postgresql.Driver

自增字段

关于自增字段,postgresql中没有自增字段,用的是sequence,比如user表中的主键id字段:

create sequence uum.userid_seq start with 1 increment by 1 no minvalue no maxvalue cache 1;
alter sequence uum.userid_seq owner to smartsys;

alter table uum.user alter column id set default nextval('uum.userid_seq');

插入时的sql,id不传入。

<insert id="insertUser" useGeneratedKeys="true" keyProperty="id" keyColumn="id" parameterType="com.sifang.uum.model.Cuser">
    insert into cuser(uname, realname, password, phone, email, user_type, deleted, birthday) values(#{uname}, #{realname}, #{password}, #{phone}, #{email}, #{userType}, #{deleted}, #{birthday})
</insert>

service层中获取插入的id:

baseMapper.insertUser(user);
int id= user.getId();

递归获取单位树列表

获取一个单位所有子单位,company表中含有cid和pcid,分别是单位的id和父单位的id,最顶层的单位id为null。想查询出树列表。

class Company是直接根据数据库生成的model,class CompanyVo在Company基础上加了字段

private List<CompanyVo> children;

通过递归调用获取单位的树列表:

public List<CompanyVo> companyTree() {
    // 调用mybatisplus的默认函数获取所有单位
    List<Company> list = this.list(); 

    // 获取所有最顶层的单位
    List<CompanyVo> parentList = getParentList(list);

    // 递归调用填充子单位
    List<CompanyVo> allList = getChildrenList(list, parentList);

    return allList;
}

private List<CompanyVo> getParentList(List<Company> list) {
    List<CompanyVo> parentList = new ArrayList<>();

    list.forEach(comp ->{
        if(comp.getPcid() == null) {
            parentList.add(new CompanyVo((comp)));
        }
    });

    return parentList;
}

private List<CompanyVo> getChildrenList(List<Company> list, List<CompanyVo> parentList) {
    parentList.forEach(parent -> {
        List<CompanyVo> childrenList = new ArrayList<CompanyVo>();
        list.forEach(comp -> {
            if(parent.getCid() == comp.getPcid()) {
                childrenList.add(new CompanyVo(comp));
            }
        });

        parent.setChildren(getChildrenList(list, childrenList));
    });

    return parentList;
}

Swagger页面测试:

 

获取一个单位及其子单位下所有用户列表

每个单位通过一个rel_comp_user关系表和用户表做了关联,想获取一个单位及其所有子单位的人员列表。

service层代码

public Page<Cuser> listAllUser(Page<Cuser> page, int cid) {
    // 获取编号为cid的单位的所有子单位的列表
    List<Integer> allChile = baseMapper.listAllChildComp(cid);

    if(allChile.size() > 0) {
        String str = "'";
        for(int i=0; i<allChile.size(); i++) {
            str += allChile.get(i).toString();

            if(i != allChile.size() - 1) {
                str += ",";
            }
        }
        str += "'";

        System.out.println(str);

        // 获取所有这些单位的人员列表
        return baseMapper.listAllChildUser(page, str);
    }
    else {
        return null;
    }
}

Mapper层,不能直接写in语句,需要用where position,把获取的所有单位编号转换成一个字符串传入:

<select id="listAllChildComp" parameterType="java.lang.Integer" resultType="java.lang.Integer">
    WITH RECURSIVE T ( cid, pcid ) AS (
        SELECT
            A.cid,
            A.pcid
        FROM
            company A
        WHERE
            A.cid = #{cid} UNION ALL
        SELECT
            b.cid,
            b.pcid
        FROM
            company b,
            T
        WHERE
            b.pcid = T.cid
    ) SELECT cid FROM T
</select>

<select id="listAllChildUser" resultType="com.sifang.uum.model.Cuser">
    select cuser.id id, cuser.uname uname
    from cuser
        left join rel_comp_user on cuser.id=rel_comp_user.uid
    where position(','||rel_comp_user.cid||',' in ','||${childComp}||',')>0
</select>

swagger页面测试:

 

### 关于 Spring Boot 和 MyBatis Plus 结合 PostgreSQL 使用的相关信息 #### 配置教程 为了使应用程序能够连接到 PostgreSQL 并利用 JSON 字段,需在 `application.properties` 或者 `application.yml` 中指定相应的属性[^1]。 对于 `application.properties` 文件: ```properties spring.datasource.url=jdbc:postgresql://localhost:5432/your_database_name spring.datasource.username=your_username spring.datasource.password=your_password spring.datasource.driver-class-name=org.postgresql.Driver mybatis-plus.type-handlers-package=com.example.yourproject.handlers ``` 其中最后一行用于自定义类型处理器包路径,这对于处理特定数据类型的映射非常有用,比如 JSON 类型的数据。 #### 示例代码 创建实体类来表示带有 JSON 字段的表结构。假设有一个名为 `UserPreferences` 的表,它包含一个存储用户偏好设置的 JSON 列 `preferences_jsonb`: ```java @TableField(typeHandler = JsonTypeHandler.class) private Map<String, Object> preferencesJsonb; ``` 这里使用了 `@TableField` 注解并指定了一个自定义的 `typeHandler` 来转换 Java 对象和数据库中的 JSON 数据之间的关系。 接着是在启动类中添加 `@MapperScan` 注解以便自动发现所有的 Mapper 接口文件[^3]: ```java @SpringBootApplication @MapperScan("com.example.yourproject.mapper") public class YourApplication { public static void main(String[] args) { SpringApplication.run(YourApplication.class, args); } } ``` #### 最佳实践 当涉及到复杂查询时,建议采用 XML 映射器或内联 SQL 而不是依赖默认 CRUD 方法;这允许更灵活地操作 JSON 数据和其他高级特性[^2]。 此外,考虑到性能优化方面,应该合理设计索引来加速频繁访问的操作,特别是针对经常作为条件过滤依据的字段建立 B-tree 索引或是 GIN/GiST 索引来支持全文检索等功能。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值