Question

I'm trying to implement https://stackoverflow.com/a/16392399/14731 for a table called "Modules" using QueryDSL. Here is my query:

String newName = "MyModule";
QModules modules = QModules.modules;
BooleanExpression moduleNotExists = session.subQuery().
    from(modules).where(modules.name.eq(newName)).notExists();
SimpleSubQuery<String> setModuleName = session.subQuery().
    where(moduleNotExists).unique(Expressions.constant(newName));
long moduleId = session.insert(modules).set(modules.name, setModuleName).
    executeWithKey(modules.id);

I am expecting this to translate into:

insert into modules(name)
select 'MyModule'
where not exists
(select 1 from modules where modules.name = 'MyModule')

Instead, I am getting:

NULL not allowed for column "NAME"; SQL statement:
   insert into MODULES (NAME)
   values ((select ?
   from dual
   where not exists (select 1
   from MODULES MODULES
   where MODULES.NAME = ?)))

where ? is equal to MyModule.

  1. Why does QueryDSL insert from dual? I am expecting it to omit from altogether.
  2. How do I fix this query?
Was it helpful?

Solution

For the insert into select form use

columns(...).select(...)

But your error suggests that the INSERT clause is valid, but semantically not what you want.

Using InsertClause.set(...) you don't get the conditional insertion you are aiming for.

In other words with

columns(...).select(...)

you map the full result set into an INSERT template and no rows will be inserted for empty result sets, but with

set(...)

you map query results to a single column of an INSERT template and null values will be used for empty results.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top