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!

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More

Top comments (0)

Billboard image

Create up to 10 Postgres Databases on Neon's free plan.

If you're starting a new project, Neon has got your databases covered. No credit cards. No trials. No getting in your way.

Try Neon for Free →