有多少 Java 程序员用 jOOQ ? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Jex
V2EX    Java

有多少 Java 程序员用 jOOQ ?

  •  3
     
  •   Jex
    CJex 2018-11-12 21:35:26 +08:00 9246 次点击
    这是一个创建于 2575 天前的主题,其中的信息可能已经有所发展或是发生改变。

    都是习惯用 Mybatis 在 XML 里面拼 SQL ? (看了隔壁关于 SQL 的讨论产生了这个疑问

    38 条回复    2019-01-15 09:07:26 +08:00
    dJ4232i1CPlr690R
        1
    dJ4232i1CPlr690R  
       2018-11-12 21:45:25 +08:00
    XML 拼接对维护比较好 比较灵活
    letitbesqzr
        2
    letitbesqzr  
       2018-11-12 21:58:06 +08:00   4
    querydsl + jpa 多爽,搞不懂 mybatis 党,一天天哪有那么多复杂的 sql 需要丢给数据库处理,宁愿多查几次用 stream 去处理。
    springmarker
        3
    springmarker  
       2018-11-12 22:30:37 +08:00 via Android
    用 mybatis-plus,复杂和简单的都能搞定
    rayingecho
        4
    rayingecho  
       2018-11-12 22:57:25 +08:00
    jOOQ 搭配 flyway, 基本上碰不到 SQL 异常了
    wysnylc
        5
    wysnylc  
       2018-11-12 22:57:57 +08:00   1
    @letitbesqzr #2 多查几次丢 stream 处理这个赞同. 然后推荐一个通用 Mapper 绝对比 jpa 好用而且语法优雅
    mysunshinedreams
        6
    mysunshinedreams  
       2018-11-12 23:38:04 +08:00
    研究过,不过很多人连 mybatis 都用不好,别提新框架了。。。
    Cbdy
        7
    Cbdy  
       2018-11-13 05:16:55 +08:00 via Android
    jooq 要代码生成,不喜欢,要是能直接生成字节码就好了
    godoway
        8
    godoway  
       2018-11-13 08:19:58 +08:00
    我也在观望 jooq,不过 jooq 的 pojo 不支持关系,需要自己添加关系。
    EricFuture
        9
    EricFuture  
       2018-11-13 08:20:08 +08:00 via iPhone
    好吧,第一次听说 jooq (汗颜)
    Suddoo
        10
    Suddoo  
       2018-11-13 08:32:54 +08:00 via Android   1
    我也是第一次听说 jooq
    changhe626
        11
    changhe626  
       2018-11-13 08:40:08 +08:00
    我也是第一次听说 jooq
    wmhack
        12
    wmhack  
       2018-11-13 08:50:28 +08:00 via iPhone
    @wysnylc 可以发一下 mapper 吗?
    sagaxu
        13
    sagaxu  
       2018-11-13 08:54:04 +08:00 via Android
    简单的用 spring data jpa,复杂的在代码里直接拼 sql,mybatis 就是个鸡肋,简单的做不好,复杂的做不了,美其名曰提高可维护性,你约定好 JAVA 拼 sql 的文件名和路径规则,效果也是一样的。
    iamniconico
        14
    iamniconico  
       2018-11-13 09:00:44 +08:00 via Android
    用 ourbatis
    loongwang
        15
    loongwang  
       2018-11-13 09:04:00 +08:00
    还在用 hibernate 的 criteria....会被鄙视吗
    lixm
        16
    lixm  
       2018-11-13 09:16:09 +08:00
    我用 ebean, 是不是太小众了?但是对 kotlin 支持很好啊
    tatelucky
        17
    tatelucky  
       2018-11-13 09:33:55 +08:00
    公司一半都是自研
    KingOfUSA
        18
    KingOfUSA  
       2018-11-13 09:49:20 +08:00
    两年前已经在生产环境上使用过 jooq. 很爽.
    tonyl4
        19
    tonyl4  
       2018-11-13 09:50:53 +08:00
    一直在用
    519718366
        20
    519718366  
       2018-11-13 10:06:46 +08:00   1
    @letitbesqzr 赞同多次单表查询,然后 stream 去处理, 但是复杂的分页列表是不是只能乖乖去写 join join 的 sql 了?
    letitbesqzr
        21
    letitbesqzr  
       2018-11-13 10:24:19 +08:00
    @519718366 #20 对,如果到 join 已经严重影响性能的地步,其实更好的选择是进行冗余,像很多高迸发的程序肯定是不允许进行 join 操作的,多加几个字段进行冗余会比较好。
    letitbesqzr
        22
    letitbesqzr  
       2018-11-13 10:24:59 +08:00
    @wysnylc #5 jpa 的语法的确很难用,所以配合了 querydsl,那个 api 设计的就很不错了。
    clearbug
        23
    clearbug  
       2018-11-13 10:33:34 +08:00 via Android
    第一次听说,之前比较喜欢 mybatis
    wysnylc
        24
    wysnylc  
       2018-11-13 11:00:26 +08:00
    BQsummer
        25
    BQsummer  
       2018-11-13 12:49:22 +08:00 via Android
    难道不是每个公司都封装了通用 mapper 吗
    xypcn
        26
    xypcn  
       2018-11-13 12:57:18 +08:00   1
    https://github.com/ecdiy/goserver 看看这个项目,后台程序员的福音,苦逼的 Mybatis
    specita
        27
    specita  
       2018-11-13 13:27:54 +08:00
    我其实是比较讨厌 xml 的,但是又觉得在代码写着 table().where().find()这种代码还不如 xml 里直接看 sql 来得直观.....
    mineqiqi
        28
    mineqiqi  
       2018-11-13 14:16:05 +08:00
    我觉得不管什么框架 如果需要在代码里写 sql 或者类似 sql 的函数 都不如直接在 xml 写 sql 直观和更好维护
    jorneyr
        29
    jorneyr  
       2018-11-13 15:01:38 +08:00
    看一个我们的 mapper 吧, 绝大部分都不是单表语句, 觉得 MyBatis 比较合适:

    ```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">

    <!--namespace 非常重要:必须是 Mapper 类的全路径-->
    <mapper namespace="ebag.mapper.ClazzMapper">
    <!-- 老师或者学生的列 -->
    <sql id="student_or_teacher_columns">
    user.id AS id,
    user.username A username,
    user.nickname AS nickname,
    user.avatar AS avatar,
    user.school_id AS school_id,
    user.is_enabled AS is_enabled,
    user.gender AS gender,
    clazz.name AS clazz_name,
    clazz.code AS clazz_code,
    clazz.phase AS clazz_phase,
    clazz.id AS clazz_id,
    cts.subject AS clazz_subject
    </sql>

    <!-- 查找学校的班级 -->
    <select id="findClazzesBySchoolId" resultType="Clazz">
    SELECT id, school_id AS schoolId, code, name, phase, grade, type,
    enrollment_year AS enrollmentYear, graduation_year AS graduationYear
    FROM clazz
    WHERE school_id = #{schoolId} AND is_history=#{history}
    </select>

    <!-- 查询指定 ID 的班级 -->
    <select id="findClazzById" parameterType="long" resultType="Clazz">
    SELECT id, school_id AS schoolId, code, name, phase, grade, type,
    enrollment_year AS enrollmentYear, graduation_year AS graduationYear
    FROM clazz WHERE id = #{clazzId}
    </select>

    <!-- 查找学校的老师 -->
    <select id="findTeachersBySchoolId" resultMap="teacherResultMap">
    SELECT <include refid="student_or_teacher_columns"/>
    FROM (
    SELECT * FROM user
    WHERE school_id = #{schoolId} AND role = 'ROLE_TEACHER'
    LIMIT #{offset}, #{count}
    ) AS user
    LEFT JOIN clazz_teacher_subject AS cts ON cts.teacher_id = user.id
    LEFT JOIN clazz ON clazz.id = cts.clazz_id
    </select>

    <!-- 使用账号查找学校的老师 -->
    <select id="findTeachersBySchoolIdAndUsernameLike" resultMap="teacherResultMap">
    SELECT <include refid="student_or_teacher_columns"/>
    FROM (
    SELECT * FROM user
    WHERE school_id = #{schoolId} AND role = 'ROLE_TEACHER' AND username LIKE CONCAT('%', #{username}, '%')
    LIMIT #{offset}, #{count}
    ) AS user
    LEFT JOIN clazz_teacher_subject AS cts ON cts.teacher_id = user.id
    LEFT JOIN clazz ON clazz.id = cts.clazz_id
    </select>

    <!-- 使用昵称查找学校的老师 -->
    <select id="findTeachersBySchoolIdAndNicknameLike" resultMap="teacherResultMap">
    SELECT <include refid="student_or_teacher_columns"/>
    FROM (
    SELECT * FROM user
    WHERE school_id = #{schoolId} AND role = 'ROLE_TEACHER' AND nickname LIKE CONCAT('%', #{nickname}, '%')
    LIMIT #{offset}, #{count}
    ) AS user
    LEFT JOIN clazz_teacher_subject AS cts ON cts.teacher_id = user.id
    LEFT JOIN clazz ON clazz.id = cts.clazz_id
    </select>

    <!-- 查找学校的学生 -->
    <select id="findStudentsBySchoolId" resultMap="studentResultMap">
    SELECT <include refid="student_or_teacher_columns"/>
    FROM (
    SELECT * FROM user
    WHERE school_id = #{schoolId} AND role='ROLE_STUDENT'
    LIMIT #{offset}, #{count}
    ) AS user
    LEFT JOIN clazz_student AS cs ON cs.student_id = user.id
    LEFT JOIN clazz ON clazz.id = cs.clazz_id
    LEFT JOIN clazz_teacher_subject cts ON cts.clazz_id = cs.clazz_id
    </select>

    <!-- 使用账号查找学校的学生 -->
    <!-- 注意 LIMIT 必须放到子查询内部,否则数量限制不对 -->
    <select id="findStudentsBySchoolIdAndUsernameLike" resultMap="studentResultMap">
    SELECT <include refid="student_or_teacher_columns"/>
    FROM (
    SELECT * FROM user
    WHERE school_id = #{schoolId} AND role='ROLE_STUDENT' AND username LIKE CONCAT('%', #{username}, '%')
    LIMIT #{offset}, #{count}
    ) AS user
    LEFT JOIN clazz_student AS cs ON cs.student_id = user.id
    LEFT JOIN clazz ON clazz.id = cs.clazz_id
    LEFT JOIN clazz_teacher_subject cts ON cts.clazz_id = cs.clazz_id
    </select>

    <!-- 使用名字查找学校的学生 -->
    <select id="findStudentsBySchoolIdAndNicknameLike" resultMap="studentResultMap">
    SELECT <include refid="student_or_teacher_columns"/>
    FROM (
    SELECT * FROM user
    WHERE school_id = #{schoolId} AND role='ROLE_STUDENT' AND nickname LIKE CONCAT('%', #{nickname}, '%')
    LIMIT #{offset}, #{count}
    ) AS user
    LEFT JOIN clazz_student AS cs ON cs.student_id = user.id
    LEFT JOIN clazz ON clazz.id = cs.clazz_id
    LEFT JOIN clazz_teacher_subject cts ON cts.clazz_id = cs.clazz_id
    </select>

    <!-- 查找班级下的老师 -->
    <select id="findTeachersByClazzId" resultMap="teacherResultMap">
    SELECT <include refid="student_or_teacher_columns"/>
    FROM clazz_teacher_subject cts
    LEFT JOIN clazz ON clazz.id = cts.clazz_id
    LEFT JOIN user ON user.id = cts.teacher_id
    WHERE cts.clazz_id = #{clazzId}
    </select>

    <!-- 查找班级下的所有学生 -->
    <select id="findStudentsByClazzId" resultMap="studentResultMap">
    SELECT <include refid="student_or_teacher_columns"/>
    FROM clazz_student cs
    LEFT JOIN user ON user.id = cs.student_id
    LEFT JOIN clazz ON clazz.id = cs.clazz_id
    LEFT JOIN clazz_teacher_subject cts ON cts.clazz_id = cs.clazz_id
    WHERE cs.clazz_id=#{clazzId}
    ORDER BY cs.student_username
    </select>

    <!-- 查找指定 ID 的老师 -->
    <select id="findTeacherById" resultMap="teacherResultMap">
    SELECT <include refid="student_or_teacher_columns"/>
    FROM clazz_teacher_subject cts
    LEFT JOIN clazz ON clazz.id = cts.clazz_id
    LEFT JOIN user ON user.id = cts.teacher_id
    WHERE cts.teacher_id = #{teacherId}
    </select>

    <!-- 查找指定 ID 的老师 -->
    <select id="findTeacherByClazzIdAndSubject" resultMap="teacherResultMap">
    SELECT <include refid="student_or_teacher_columns"/>
    FROM clazz_teacher_subject cts
    LEFT JOIN clazz ON clazz.id = cts.clazz_id
    LEFT JOIN user ON user.id = cts.teacher_id
    WHERE cts.clazz_id = #{clazzId} AND cts.subject = #{subject}
    </select>

    <!-- 查找指定 ID 的学生 -->
    <select id="findStudentById" parameterType="long" resultMap="studentResultMap">
    SELECT <include refid="student_or_teacher_columns"/>
    FROM clazz_student cs
    LEFT JOIN clazz ON clazz.id = cs.clazz_id
    LEFT JOIN clazz_teacher_subject cts ON cts.clazz_id = cs.clazz_id
    LEFT JOIN user ON user.id = cs.student_id
    WHERE cs.student_id = #{studentId}
    </select>

    <!--查询班级学生人数-->
    <select id="findStudentCount" resultType="int">
    SELECT count(*) FROM clazz_student WHERE clazz_student.clazz_id = #{clazzId}
    </select>

    <!-- 启用或禁用老师 -->
    <update id="enableTeacher">
    UPDATE clazz_teacher_subject SET is_enabled=#{enabled} WHERE teacher_id=#{teacherId};
    UPDATE user SET is_enabled=#{enabled} WHERE id=#{teacherId};
    </update>

    <!-- 启用或禁用学生 -->
    <update id="enableStudent">
    UPDATE clazz_student SET is_enabled=#{enabled} WHERE student_id=#{studentId};
    UPDATE user SET is_enabled=#{enabled} WHERE id=#{studentId};
    </update>

    <!-- 删除老师 -->
    <delete id="deleteTeacher">
    DELETE FROM user WHERE id = #{teacherId};
    DELETE FROM clazz_teacher_subject WHERE teacher_id = #{teacherId};
    </delete>

    <!-- 删除学生 -->
    <delete id="deleteStudent">
    DELETE FROM user WHERE id = #{studentId};
    DELETE FROM clazz_student WHERE student_id = #{studentId};
    </delete>

    <!-- 插入或更新已有班级 -->
    <insert id="insertOrUpdateClazz" parameterType="Clazz">
    INSERT INTO clazz (id, school_id, code, name, phase, grade, type, enrollment_year, graduation_year, created_time)
    VALUES (#{id}, #{schoolId}, #{code}, #{name}, #{phase}, #{grade}, #{type}, #{enrollmentYear}, #{graduationYear}, now())

    ON DUPLICATE KEY
    UPDATE name = #{name}, phase = #{phase}, grade = #{grade}, type = #{type},
    enrollment_year = #{enrollmentYear}, graduation_year = #{graduationYear}
    </insert>

    <!-- 插入班级学生关系 -->
    <insert id="insertClazzStudent">
    INSERT INTO clazz_student (school_id, clazz_code, student_username, created_time)
    SELECT #{schoolId}, #{clazzCode}, #{studentUsername}, now()
    FROM dual
    WHERE NOT EXISTS (
    SELECT 1 FROM clazz_student
    WHERE school_id = #{schoolId} AND clazz_code = #{clazzCode} AND student_username = #{studentUsername}
    )
    </insert>

    <!-- 插入班级老师学科关系 -->
    <insert id="insertClazzTeacherSubject">
    INSERT INTO clazz_teacher_subject (school_id, clazz_code, teacher_username, subject, created_time)
    SELECT #{schoolId}, #{clazzCode}, #{teacherUsername}, #{subject}, now()
    FROM dual
    WHERE NOT EXISTS (
    SELECT 1 FROM clazz_teacher_subject
    WHERE school_id = #{schoolId} AND clazz_code = #{clazzCode} AND teacher_username = #{teacherUsername} AND subject = #{subject}
    )
    </insert>
    ...
    ```
    zcsz
        30
    zcsz  
       2018-11-13 15:09:30 +08:00
    后端用 Mybatis,SQL 都写 Dao 里,还算简单明了,讲道理现在心思都在前端上,后端快速搭建就成
    hsuvee
        31
    hsuvee  
       2018-11-13 15:39:36 +08:00
    自研超爽,性能堪比 jdbc,使用感觉堪比....堪比什么想不到,反正剩下的都是垃圾,说 jpa 好的看看性能分析 0.0
    Jex
        32
    Jex  
    OP
       2018-11-13 15:53:08 +08:00   1
    @jorneyr 我回复你一下,只为让评论早点翻页让你那坨 XML 消失
    qiyuey
        33
    qiyuey  
       2018-11-13 16:03:13 +08:00
    @jorneyr 你这个 xml 感觉不具备可读性
    godoway
        34
    godoway  
       2018-11-13 16:04:37 +08:00
    面对着 Oracle,想用 jooq 都用不了。
    面对着一堆 Oracle 自定义函数,jpa 又很麻烦(貌似还不能在插入的时候调用,其实是我不懂...)
    最后只能上 mybatis 了,蛋疼...
    jorneyr
        35
    jorneyr  
       2018-11-13 16:12:19 +08:00
    @qiyuey 有更好的办法吗?
    Jex
        36
    Jex  
    OP
       2018-11-23 12:27:24 +08:00   1
    @jorneyr 在 XML 里面拼 SQL 跟直接在 Java 里面拼 SQL 有多大区别?
    applehater
        37
    applehater  
       2019-01-15 04:29:26 +08:00 via iPhone
    @letitbesqzr 发现工作一年多,还真没写过 join 语句。。
    letitbesqzr
        38
    letitbesqzr  
       2019-01-15 09:07:26 +08:00
    @applehater #37 互联网产品吧? 企业产品几乎不可能的,那几千上万张表的业务,不关联很麻烦。。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1177 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 16:59 PVG 00:59 LAX 08:59 JFK 11:59
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86