gpt4 book ai didi

hibernate - 在 JPA 条件中具有复合主键的 IN 子句

转载 作者:行者123 更新时间:2023-12-04 11:24:14 27 4
gpt4 key购买 nike

我有一张名为 group_table 的表在只有两列的 MySQL 中 user_group_idgroup_id (它们都是 VARCHAR 类型)。这两个列共同构成一个复合主键。

我需要使用子选择执行语句 IN()根据传递给查询的值列表选择行。

@Override
@SuppressWarnings("unchecked")
public List<GroupTable> getList(List<GroupTable> list)
{
CriteriaBuilder criteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaQuery<GroupTable> criteriaQuery=criteriaBuilder.createQuery(GroupTable.class);
Root<GroupTable> root = criteriaQuery.from(entityManager.getMetamodel().entity(GroupTable.class));
criteriaQuery.where(root.in(list));
return entityManager.createQuery(criteriaQuery).getResultList();
}

该实现产生以下查询。

SELECT group_id, 
user_group_id
FROM projectdb.group_table
WHERE ((?, ?) IN ((?, ?), (?, ?)))

/*Binding parameters.*/
bind => [null, null, ROLE_AAA, aaa, ROLE_BBB, aaa]

请注意,与组合键本身有关的前两个参数是 null .他们应该是 user_group_idgroup_id分别。

为什么它们在参数列表中没有被替换?

虽然我对在表中形成复合主键不感兴趣,但这对于我用于身份验证的 JAAS 来说(可能)是强制性的。

在这种情况下,查询返回与从数据库提供的列表相同的列表,这实际上是不必要的。我实际上需要这个查询来删除多行。

最佳答案

这是 eclipse 链接中缺少的功能。我为此开发了一个补丁

/** *****************************************************************************
* Copyright (c) 1998, 2013 Oracle and/or its affiliates. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Oracle - initial API and implementation from Oracle TopLink
* Nicolas Marcotte <nicolas.marcotte@usherbrooke.ca> - patch for IN on composite keys comming from expression builder

***************************************************************************** */
package org.eclipse.persistence.internal.expressions;

import java.io.*;
import java.util.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.eclipse.persistence.internal.helper.*;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.queries.*;
import org.eclipse.persistence.exceptions.*;
import org.eclipse.persistence.expressions.*;
import org.eclipse.persistence.internal.databaseaccess.*;
import org.eclipse.persistence.internal.sessions.AbstractRecord;

/**
* <p>
* <b>Purpose</b>: Expression SQL printer.
* <p>
* <b>Responsibilities</b>:<ul>
* <li> Print an expression in SQL format.
* <li> Replaces FIELD types with field names from the descriptor.
* <li> Replaces PARAMETER types with row or object values.
* <li> Calls accessor to print primitive types.
* </ul>
* <p>
* @author Dorin Sandu
* @since TOPLink/Java 1.0
*/
public class ExpressionSQLPrinter {

/**
* Stores the current session. The session accessor
* is used to print all the primitive types.
*/
protected AbstractSession session;

/**
* Stores the current platform to access platform specific functions.
*/
protected DatabasePlatform platform;

/**
* Stores the call being created.
*/
protected SQLCall call;

/**
* Stores the row. Used to print PARAMETER nodes.
*/
protected AbstractRecord translationRow;

/**
* Indicates whether fully qualified field names
* (owner + table) should be used or not.
*/
protected boolean shouldPrintQualifiedNames;

// What we write on
protected Writer writer;

/** Used for distincts in functions. */
protected boolean requiresDistinct;

// Used in figuring out when to print a comma in the select line
protected boolean isFirstElementPrinted;
private final ExpressionBuilder builder;

public ExpressionSQLPrinter(AbstractSession session, AbstractRecord translationRow, SQLCall call, boolean printQualifiedNames, ExpressionBuilder builder) {
this.session = session;
this.translationRow = translationRow;
this.call = call;
this.shouldPrintQualifiedNames = printQualifiedNames;
// reference session's platform directly if builder or builder's descriptor is null
if (builder == null || builder.getDescriptor() == null) {
this.platform = getSession().getPlatform();
} else {
this.platform = (DatabasePlatform) getSession().getPlatform(builder.getDescriptor().getJavaClass());
}
this.requiresDistinct = false;
this.builder = builder;
isFirstElementPrinted = false;
}

/**
* Return the call.
*/
public SQLCall getCall() {
return call;
}

/**
* INTERNAL:
* Return the database platform specific information.
*/
public DatabasePlatform getPlatform() {
return this.platform;
}

protected AbstractSession getSession() {
return session;
}

/**
* INTERNAL:
* Return the row for translation
*/
protected AbstractRecord getTranslationRow() {
return translationRow;
}

public Writer getWriter() {
return writer;
}

/**
* INTERNAL:
* Used in figuring out when to print a comma in the select clause
*/
public boolean isFirstElementPrinted() {
return isFirstElementPrinted;
}

public void printExpression(Expression expression) {
translateExpression(expression);
}

public void printField(DatabaseField field) {
if (field == null) {
return;
}
//start of patch 1
//resolve alias if is was not already done
if (builder.getTableAliases() != null) {
DatabaseTable keyAtValue = builder.getTableAliases().keyAtValue(field.getTable());
if (keyAtValue != null) {
field.setTableName(keyAtValue.getName());
}
}
//end of patch 1
try {
// Print the field using either short or long notation i.e. owner + table name.
if (shouldPrintQualifiedNames()) {
getWriter().write(field.getQualifiedNameDelimited(platform));
} else {
getWriter().write(field.getNameDelimited(platform));
}
} catch (IOException exception) {
throw ValidationException.fileError(exception);
}
}

public void printParameter(ParameterExpression expression) {
try {
final Logger logger = LogManager.getLogger();

getCall().appendTranslationParameter(getWriter(), expression, getPlatform(), getTranslationRow());

} catch (IOException exception) {
throw ValidationException.fileError(exception);
}
}

public void printParameter(DatabaseField field) {
getCall().appendTranslation(getWriter(), field);
}

public void printPrimitive(Object value) {
if (value instanceof Collection) {
printValuelist((Collection) value);
return;
}

session.getPlatform().appendLiteralToCall(getCall(), getWriter(), value);
}

public void printNull(ConstantExpression nullValueExpression) {
if (session.getPlatform().shouldBindLiterals()) {
DatabaseField field = null;
Expression localBase = nullValueExpression.getLocalBase();
if (localBase.isFieldExpression()) {
field = ((FieldExpression) localBase).getField();
} else if (localBase.isQueryKeyExpression()) {
field = ((QueryKeyExpression) localBase).getField();
}
session.getPlatform().appendLiteralToCall(getCall(), getWriter(), field);
} else {
session.getPlatform().appendLiteralToCall(getCall(), getWriter(), null);
}
}

public void printString(String value) {
try {
getWriter().write(value);

} catch (IOException exception) {
throw ValidationException.fileError(exception);
}
}

public void printValuelist(Collection values) {
try {
getWriter().write("(");
Iterator valuesEnum = values.iterator();
while (valuesEnum.hasNext()) {
Object value = valuesEnum.next();
// Support nested arrays for IN.
if (value instanceof Collection) {
printValuelist((Collection) value);
} else if (value instanceof Expression) {
((Expression) value).printSQL(this);
//start of patch 2
} else if (value instanceof DatabaseField) {

printExpression(builder.getField((DatabaseField) value));
//end of patch 2
} else {
session.getPlatform().appendLiteralToCall(getCall(), getWriter(), value);
}
if (valuesEnum.hasNext()) {
getWriter().write(", ");
}
}
getWriter().write(")");
} catch (IOException exception) {
throw ValidationException.fileError(exception);
}
}

/*
* Same as printValuelist, but allows for collections containing expressions recursively
*/
public void printList(Collection values) {
try {
getWriter().write("(");
Iterator valuesEnum = values.iterator();
while (valuesEnum.hasNext()) {
Object value = valuesEnum.next();
if (value instanceof Expression) {
((Expression) value).printSQL(this);
} else {
session.getPlatform().appendLiteralToCall(getCall(), getWriter(), value);
}
if (valuesEnum.hasNext()) {
getWriter().write(", ");
}
}
getWriter().write(")");
} catch (IOException exception) {
throw ValidationException.fileError(exception);
}
}

/**
* If a distinct has been set the DISTINCT clause will be printed.
* This is required for batch reading.
*/
public boolean requiresDistinct() {
return requiresDistinct;
}

protected void setCall(SQLCall call) {
this.call = call;
}

/**
* INTERNAL:
* Used in figuring out when to print a comma in the select clause
*/
public void setIsFirstElementPrinted(boolean isFirstElementPrinted) {
this.isFirstElementPrinted = isFirstElementPrinted;
}

/**
* If a distinct has been set the DISTINCT clause will be printed.
* This is required for batch reading.
*/
public void setRequiresDistinct(boolean requiresDistinct) {
this.requiresDistinct = requiresDistinct;
}

protected void setSession(AbstractSession theSession) {
session = theSession;
}

protected void setShouldPrintQualifiedNames(boolean shouldPrintQualifiedNames) {
this.shouldPrintQualifiedNames = shouldPrintQualifiedNames;
}

/**
* INTERNAL:
* Set the row for translation
*/
protected void setTranslationRow(AbstractRecord theRow) {
translationRow = theRow;
}

public void setWriter(Writer writer) {
this.writer = writer;
}

public boolean shouldPrintParameterValues() {
return getTranslationRow() != null;
}

protected boolean shouldPrintQualifiedNames() {
return shouldPrintQualifiedNames;
}

/**
* Translate an expression i.e. call the appropriate
* translation method for the expression based on its
* type. The translation method is then responsible
* for translating the subexpressions.
*/
protected void translateExpression(Expression theExpression) {
theExpression.printSQL(this);
}
}

补丁由 分隔//补丁n的开始//补丁n结束
我会尝试向上游提交它,但这可能需要时间

关于hibernate - 在 JPA 条件中具有复合主键的 IN 子句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24109412/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com