Hacker News new | ask | show | jobs
by agentgt 3818 days ago
They are not the same and probably many modern ORM's share more in common with jOOQ than Torgue has in common with jOOQ. An example would be schema generation. jOOQ is reverse schema based. You make your schema with whatever schema evolution tools you like (Flyway is the most common) and then run the code generator. Torque is the opposite (notice they say starting point not final) not to mention its also XML based.

Oh and jOOQ has an extremely powerful DSL that is close to 1-1 with SQL and whole bunch of reflection based conversion abilities (including dotted path data binding which I am happy to say I inspired the author of jOOQ to add :) )

2 comments

Torque does code-gen as well. This was before any fancy tools so we basically just had hand generated DDL.

https://db.apache.org/torque/torque-4.0/documentation/orm-re...

Regen, then fix compile issues. Thats how I used it a long long (10 years?) time ago.

jOOQ DSL is nice, this is just as readable(ABC is a generated class)

  Criteria crit = new Criteria()
    .where(ABC.A, 1, Criteria.LESS_THAN)
    .and(ABC.B, 2, Criteria.GREATER_THAN)
    .or(ABC.A, 5, Criteria.GREATER_THAN);
Working with XML, not the nicest thing, i do agree, but also not the worst thing.

Not a flag-bearer in any way, but I just wanted to point out that if code-gen db access is your thing, there are also other tools to consider. It most certainly had its warts. Like issues handling complicated joins. Or more seriously, whos maintaining it. Its been a long time since i've look at it with any seriousness, not sure if they have fixed them or not.

edit: formatting

Here's a jOOQ example from the "PostgresDatabase" class, which is used to reverse-engineer the meta data. How would you write it in Torque?

    .select()
    .from(
         select(
            TABLES.TABLE_SCHEMA,
            TABLES.TABLE_NAME,
            TABLES.TABLE_NAME.as("specific_name"),
            inline(false).as("table_valued_function"),
            inline(false).as("materialized_view"),
            PG_DESCRIPTION.DESCRIPTION)
        .from(TABLES)
        .join(PG_NAMESPACE)
            .on(TABLES.TABLE_SCHEMA.eq(PG_NAMESPACE.NSPNAME))
        .join(PG_CLASS)
            .on(PG_CLASS.RELNAME.eq(TABLES.TABLE_NAME))
            .and(PG_CLASS.RELNAMESPACE.eq(oid(PG_NAMESPACE)))
        .leftOuterJoin(PG_DESCRIPTION)
            .on(PG_DESCRIPTION.OBJOID.eq(oid(PG_CLASS)))
            .and(PG_DESCRIPTION.OBJSUBID.eq(0))
        .where(TABLES.TABLE_SCHEMA.in(getInputSchemata()))
    
        // To stay on the safe side, if the INFORMATION_SCHEMA ever
        // includs materialised views, let's exclude them from here
        .and(row(TABLES.TABLE_SCHEMA, TABLES.TABLE_NAME).notIn(
            select(
                PG_NAMESPACE.NSPNAME,
                PG_CLASS.RELNAME)
            .from(PG_CLASS)
            .join(PG_NAMESPACE)
                .on(PG_CLASS.RELNAMESPACE.eq(oid(PG_NAMESPACE)))
            .where(PG_CLASS.RELKIND.eq(inline("m")))
        ))
    
    // [#3254] Materialised views are reported only in PG_CLASS, not
    //         in INFORMATION_SCHEMA.TABLES
    .unionAll(
        select(
            PG_NAMESPACE.NSPNAME,
            PG_CLASS.RELNAME,
            PG_CLASS.RELNAME,
            inline(false).as("table_valued_function"),
            inline(true).as("materialized_view"),
            PG_DESCRIPTION.DESCRIPTION)
        .from(PG_CLASS)
        .join(PG_NAMESPACE)
            .on(PG_CLASS.RELNAMESPACE.eq(oid(PG_NAMESPACE)))
        .leftOuterJoin(PG_DESCRIPTION)
            .on(PG_DESCRIPTION.OBJOID.eq(oid(PG_CLASS)))
            .and(PG_DESCRIPTION.OBJSUBID.eq(0))
        .where(PG_NAMESPACE.NSPNAME.in(getInputSchemata()))
        .and(PG_CLASS.RELKIND.eq(inline("m"))))
    
    // [#3375] [#3376] Include table-valued functions in the set of tables
    .unionAll(
        tableValuedFunctions()
    
        ?   select(
                ROUTINES.ROUTINE_SCHEMA,
                ROUTINES.ROUTINE_NAME,
                ROUTINES.SPECIFIC_NAME,
                inline(true).as("table_valued_function"),
                inline(false).as("materialized_view"),
                inline(""))
            .from(ROUTINES)
            .join(PG_NAMESPACE).on(ROUTINES.SPECIFIC_SCHEMA.eq(PG_NAMESPACE.NSPNAME))
            .join(PG_PROC).on(PG_PROC.PRONAMESPACE.eq(oid(PG_NAMESPACE)))
                          .and(PG_PROC.PRONAME.concat("_").concat(oid(PG_PROC)).eq(ROUTINES.SPECIFIC_NAME))
            .where(ROUTINES.ROUTINE_SCHEMA.in(getInputSchemata()))
            .and(PG_PROC.PRORETSET)
    
        :   empty)
    .asTable("tables"))
    .orderBy(1, 2)
    .fetch()) {
That was a great steal. Thanks again for the idea, Adam! :)