DEV Community

Composite
Composite

Posted on

3 2

How to use SQLQueryFactory with your QueryDSL JPA Entities

Even you want QueryDSL SQL features such as bulk insert, you are using queryDSL JPA, unfortunately there is no way to generate RelationalPath<T> from EntityPath<T> automatically.

As @timo Westkämper feedback You can't turn it into a RelationalPath automatically

but you can create RelationalPathBase using your entityPath

RelationalPathBase relationalPathBase= new RelationalPathBase(this.entityPath.getType(), this.entityPath.getMetadata(), "yourSchemaName","yourTableName");

But there's a good news. you can wrap RelationalPath<T> from EntityPath<T> manually like this. so, I made util class that wrap RelationalPath<T> from EntityPath<T>.

TL;DR: copy the class below, apply it, and use it.

import com.querydsl.core.types.EntityPath;
import com.querydsl.sql.RelationalPath;
import com.querydsl.sql.RelationalPathBase;
import javax.persistence.Table;
import java.lang.reflect.AnnotatedElement;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public final class QueryDslUtils {
/**
* Simple Type cache (If you want another cache strategy, make it your own.)
*/
private static final ConcurrentMap<EntityPath<?>, RelationalPath<?>> relationalMap = new ConcurrentHashMap<>();
/**
* Entity Class to SQLQueryFactory RelationalPath
* @param entityPath
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T> RelationalPath<T> asRelational(EntityPath<T> entityPath) {
AnnotatedElement annotatedElement = Objects.requireNonNull(Objects.requireNonNull(entityPath, "entityPath is null").getAnnotatedElement(), "no annotation");
Table table = Objects.requireNonNull(annotatedElement.getAnnotation(Table.class), "no entity table");
RelationalPath<?> result = relationalMap.get(entityPath);
if(result == null)
relationalMap.put(entityPath, result = new RelationalPathBase<T>(entityPath.getType(), entityPath.getMetadata(), table.schema(), table.name()));
return (RelationalPath<T>) result;
}
}

How to use? that's very simple. when you are using SQLQueryFactory, then just call QueryDslUtils.asRelational to wrap RelationalPath entity and use any SQLQueryFactory's clause.

@Entity
@Table(name = "my_table", schema = "my_schema") // MUST HAVE THIS ANNOTATION!
@Data // for Lombok
public class SomeEntity {
  @Column("some_col")
  private String someColumn;
  // ...getter, setter, etc.
}

EntityPath<SomeEntity> myEntity = QSomeEntity.someEntity;
RelationalPath<SomeEntity> sqlEntity = QueryDslUtils.asRelational(myEntity);

sqlQueryFactory.insert(sqlEntity)...execute();
Enter fullscreen mode Exit fullscreen mode

That's all. happy coding!

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay