我正在尝试使用QueryDSL从我的表中获取多列的列表,并自动填充我的数据库对象,如旧手册中的此示例:
List<CatDTO> catDTOs = query.from(cat)
.list(EConstructor.create(CatDTO.class, cat.id, cat.name));
Run Code Online (Sandbox Code Playgroud)
问题是看起来在版本2.2.0中删除了EConstructor类,我现在找到的所有示例都是这样的:
List<Object[]> rows = query.from(cat)
.list(cat.id, cat.name);
Run Code Online (Sandbox Code Playgroud)
这迫使我手动将所有对象强制转换为我的CatDTO类.
有没有替代方案?任何EConstructor替代?
我将开始使用非常大的数据库的新项目,因此将有大量的数据库操作.
我决定使用Spring JPA作为我的ORM.现在Spring JPA提供了在DAO层中使用的各种技术.我对Criteria builder和Query DSL感到困惑.两者似乎都很好地解决了我的问题,我想在同一个项目中使用它们并没有意义,因为它们提供相同的功能.
那么现在使用哪一个?为什么?
我目前正在使用maven apt插件来生成EntityPath基类.
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>maven-apt-plugin</artifactId>
<version>1.0.4</version>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<outputDirectory>target/generated-sources/java</outputDirectory>
<processor>com.mysema.query.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>${querydsl.version}</version>
</dependency>
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<classifier>apt</classifier>
<version>${querydsl.version}</version>
</dependency>
</dependencies>
</plugin>
Run Code Online (Sandbox Code Playgroud)
这会生成所需的Q类,它有助于构建查询谓词.但是我注意到,每当我超过四个级别时,我总是得到一个空指针异常,即:
QFoo.foo.x.y.z
Run Code Online (Sandbox Code Playgroud)
其中Z是QZ型; 生成的EntityPath也是如此.
这是QueryDSL的限制吗?
让我直截了当.我在一个项目中使用Spring Data JPA和QueryDSL,我自己也无法弄清楚这一点.
我在静态方法中有QueryDSL谓词可以接受参数,如果参数不正确,它应该返回"空谓词":
public static BooleanExpression byWhateverId(Long whateverId) {
if(whateverId == null) return [insert magic here];
// if parameter is OK return usual predicate
return QClass.property.whateverId.eq(whateverId);
}
Run Code Online (Sandbox Code Playgroud)
现在我希望能够使用AND/OR操作符链接这些谓词:
someRepository.findAll(byWhateverId(someParam).and(bySomethingElseId(1));
Run Code Online (Sandbox Code Playgroud)
这里的问题是,此时我不知道'someParam'是否为空(当然我可以查看,但那是很多IF).我也知道我可以使用BooleanBuilder类,但这看起来也像很多不需要的代码.
有谁知道可以插入什么而不是"[在这里插入魔法]"??? 或者也许我在某处丢失某些东西......
谢谢!
我是JPA,JPQL,Hibernate,Querydsl的新手,现在我看到在我的项目中使用Querydsl进行查询,我想知道为什么选择这种方法.所以你可以肯定为什么我的项目确切存在,但你可以告诉Querydsl为什么以及在什么情况下是首选.为什么我们可以使用简单的JPQL语句?
我有一个问题是使用deleteInBatch从db中删除项目.我有一个对象A有一个对象B列表,如:
class A {
private List <B>;
}
Run Code Online (Sandbox Code Playgroud)
该列表包含7k多个元素.所以现在我必须删除A及其所有元素.我试过通过deleteInBatch,但我得到了
org.springframework.web.util.NestedServletException: Handler processing failed;
nested exception is java.lang.StackOverflowError
Run Code Online (Sandbox Code Playgroud)
使用sipmle delete方法删除项目有效,但需要5分钟以上.我的删除代码是:
public void delete(Long id) {
A a = repository.findOne(id);
deleteElements(a);
repository.delete(a);
}
private void deleteElements(A a) {
repository.deleteInBatch(a.getListOfB);
}
Run Code Online (Sandbox Code Playgroud)
有没有一个很好的解决方案来加快删除过程或如何更改,以便deleteinbatch不占用所有休眠堆栈 - 不增加它?
完整的Stacktrace:
org.springframework.web.util.NestedServletException: Handler processing failed; nested exception is java.lang.StackOverflowError
org.springframework.web.servlet.DispatcherServlet.triggerAfterCompletionWithError(DispatcherServlet.java:1259)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:945)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)
javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:163)
net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:206)
net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:179)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
Run Code Online (Sandbox Code Playgroud)
等等...
root cause
java.lang.StackOverflowError
org.hibernate.hql.internal.ast.tree.SqlNode.<init>(SqlNode.java:34)
sun.reflect.GeneratedConstructorAccessor36.newInstance(Unknown Source)
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
java.lang.reflect.Constructor.newInstance(Constructor.java:526)
java.lang.Class.newInstance(Class.java:379)
org.hibernate.hql.internal.ast.SqlASTFactory.create(SqlASTFactory.java:256)
antlr.ASTFactory.create(ASTFactory.java:153)
antlr.ASTFactory.create(ASTFactory.java:186) …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用QueryDSL计算平均日期差异.
我创建了一个小项目,以简化的方式演示我想要完成的任务(真正的查询要复杂得多,有大量的连接/ where/sort子句).我们有一个带有字段的Customer类birthDate,我们正在努力获得客户的平均年龄(以秒为单位).我们也想要最大年龄,但让我们关注这篇文章的平均值.
我尝试使用querydsl-jpa编写此查询,但它失败了一个模糊的错误:
java.lang.NullPointerException
at org.hibernate.dialect.function.StandardAnsiSqlAggregationFunctions$AvgFunction.determineJdbcTypeCode(StandardAnsiSqlAggregationFunctions.java:106)
at org.hibernate.dialect.function.StandardAnsiSqlAggregationFunctions$AvgFunction.render(StandardAnsiSqlAggregationFunctions.java:100)
at org.hibernate.hql.internal.ast.SqlGenerator.endFunctionTemplate(SqlGenerator.java:233)
[...]
Run Code Online (Sandbox Code Playgroud)
我也尝试过其他方法,比如使用NumberTemplate.create(Double.class, "{0} - {1}", DateExpression.currentDate(), customer.birthDate).avg(),但它没有返回正确的值.如果我们想要以秒为单位获得日期差异,似乎我们需要找到一些方法来调用特定于数据库的日期/时间差异函数,而不仅仅是使用减号.
遗憾的是,在JPQL中似乎不可能计算日期差异,所以我猜querydsl-jpa也有局限性.因此,我们必须编写本机SQL查询,或者找到一些hack来使QueryDsl生成的JPQL调用本机数据库函数.
JPA 2.1增加了对调用数据库函数的支持,但是存在一个问题:MySQL函数采用的形式TIMESTAMPDIFF(SECOND, '2012-06-06 13:13:55', '2012-06-06 15:20:18').如果第一个参数(SECOND)是一个String,它可能是可能的,但它似乎是对某种常量的引用,并且在第一个参数未引用的情况下生成JPQL似乎很复杂.
QueryDSL增加了对日期差异的支持,但似乎大多数代码都驻留在querydsl-sql项目中,所以我想知道我是否可以通过querydsl-jpa从中受益.
这是我的问题:
是否可以使用querydsl-jpa计算平均日期差异,让它可以使用JPA 2.1支持调用本机数据库函数(可能使用Expressions.numberTemplate())?或者我们被迫使用querydsl-sql?
如果我们不得不使用querydsl-SQL,我们如何产生既QCustomer与SCustomer?QCustomer目前使用插件"com.mysema.maven:apt-maven-plugin"从Customer实体生成.如果我理解正确,我必须使用不同的插件(com.querydsl:querydsl-maven-plugin)来生成SCustomer查询类型?
在查看querydsl-sql-example时,我没有看到任何实体类,所以我猜查询类型是由QueryDSL从数据库模式生成的?有没有办法从实体生成SCustomer查询类型,就像我们使用querydsl-jpa一样?
如果我们使用querydsl-sql,有没有办法在querydsl-sql查询中"重用"我们的querydsl-jpa谓词/ sorts/joins子句?或者我们是否必须使用特定于querydsl-sql的类复制该代码?
我也在考虑创建一个委托的数据库函数TIMESTAMPDIFF(SECOND, x, y),但它不是很便携......
我错过了什么吗?有没有更简单的方法来做我想做的事情?
我想从modelA中的modelA基础上获取数据.但对于我将在modelB中记录的每条记录,并非强制性的.因此,当我使用下面的代码来获取数据时,它返回0条记录.
BooleanExpression searchCriteria = searchCriteria
.and(
qModelA.modelb.user.id.eq(userId)
)
.and ( some other conditions as well);
modelA.findAll(searchCriteria, pageable);
Run Code Online (Sandbox Code Playgroud)
当我调试我发现QueryDsl放交叉连接.任何人都可以告诉我如何解决这个问题,是否有任何方式querydsl添加左连接而不是交叉连接?下面是我的两个型号.
@Entity
public class ModelA implements Serializable {
private Long id;
private String label;
private ModelB modelB;
@Id
@SequenceGenerator(name = "modelASeq", sequenceName = "modela_id_seq", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "modelASeq")
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Column(length = 150, nullable = false)
public String getLabel() {
return label;
}
public …Run Code Online (Sandbox Code Playgroud) 我之前有这样的查询:
public List<Human> findAllHumansWithPets(){
QHuman human = QHuman.human;
QPet pet = QPet.pet;
JPAQuery query = new JPAQuery(entityManager);
//Joda-Time
LocalDate first = new LocalDate(1990, 01, 01);
LocalDate last = new LocalDate(1990, 02, 01);
return query.from(human)
.innerJoin(human.pet, pet)
.where(SQLExpressions.date(human.age).between(first.toDate(), last.toDate()))
.list(order);
}
Run Code Online (Sandbox Code Playgroud)
而且工作正常。现在,我age在Human POJO中更新了变量,以使用java.time.LocalDate代替org.joda.time.LocalDate。Querydsl不喜欢它,现在抱怨的参数SQLExpression.date。
//java.time.LocalDate
LocalDate first = LocalDate.of(1990, 01, 01);
LocalDate last = LocalDate.of(1990, 02, 01);
return query.from(human)
.innerJoin(human.pet, pet)
.where(SQLExpressions.date(human.age).between(first, last))
.list(order);
}
Run Code Online (Sandbox Code Playgroud)
SQLExpressions中的DateTimeExpression <java.lang.Comparable>不能应用于com.mysema.query.types.path.DatePath <java.time.LocalDate>
我似乎找不到关于此问题的任何解决方法。防止再次回到Joda-Time很好。有什么建议么?
有什么办法可以用 QueryDSL 获取这个查询吗?
select
person.name,
count(neighbors.*)
from person as neighbors
where person.address = neighbor.address
group by person.name
Run Code Online (Sandbox Code Playgroud)
其中address不是 FK。
querydsl ×10
java ×5
jpa ×3
jpql ×3
spring ×2
criteria-api ×1
database ×1
hibernate ×1
jpa-2.0 ×1
orm ×1
postgresql ×1
predicate ×1
spring-mvc ×1