我目前正在尝试使用记录执行upsert(使用3.10-snapshot),并注意到当我使用{{{{}}}时,更新的set
数据未被添加到查询中1}}。在DAO我有:
addRecord(R)
在programAssignments的类中,我有:
try (Connection writeConn = DatabaseManager.getConnection(true);
final DSLContext writeContext = DatabaseManager.getBuilder(writeConn);
InsertQuery<UserProgramAssignmentsRecord> programAssignmentsUpdateQuery = writeContext
.insertQuery(AccessControlWriteDAO.userProgramAssignments)) {
programAssignmentsUpdateQuery.onDuplicateKeyUpdate(true);
programAssignments.forEach(pa -> programAssignmentsUpdateQuery.addRecord(pa.toRecord()));
if (!programAssignments.isEmpty()) {
if (AccessControlWriteDAO.logger.isInfoEnabled()) {
AccessControlWriteDAO.logger.info(writeContext.renderInlined(programAssignmentsUpdateQuery));
}
// programAssignmentsUpdateQuery.execute();
}
} catch (final SQLException e) {
throw new DAOException(e.getMessage(), e);
}
代码生成以下查询:
/**
* <p>
* This method turns the object into a {@link Record} that can then be attached to a {@link Connection} and
* {@link DSLContext}.
* </p>
*
* @return A usable {@link UserProgramAssignmentsRecord}
*/
public UserProgramAssignmentsRecord toRecord() {
UserProgramAssignmentsRecord upar = new UserProgramAssignmentsRecord();
getAdministerProgram().ifPresent(upar::setAdminister);
getCreateProjects().ifPresent(upar::setCreateProjects);
getJustification().ifPresent(upar::setJustification);
getProgramId().ifPresent(upar::setProgramId);
getUserId().ifPresent(upar::setUserId);
getViewRevisions().ifPresent(upar::setViewRevisions);
return upar;
}
我是否必须切换到使用insert into "%%removed%%"."user_project_assignments" (
"project_id",
"edit_draft",
"justification",
"user_id"
)
values (
98332,
true,
'The user created the project',
675
)
on conflict (
"project_id",
"user_id"
) do update
set [ no fields are updated ]
,addValue(Field<T>,T)
和newRecord?我会思考传递记录是等价的,但似乎并非如此,addValueForUpdateField(Field<T>,T)
似乎没有设置要更新的字段 - 或者 - 我在addRecord(R)
方法中做错了什么? toRecord()
个addRecordForUpdate(R)
对象是否有某种?这对于多行upserts有多好(这是我尝试做的事情)?
答案 0 :(得分:0)
在审核文档后,我认为这有点......缺点......虽然有人可能认为 addRecord(R)
+ onDuplicateKeyUpdate(true)
意味着更新数据设置为或,会有addValueForUpdate(R)
,这显然是错误的。我的解决方案是让我的POJO还有另一种方法toExcludedMap()
,如下所示:
/**
* <p>
* This method returns mappings that can be used in an UPSERT in the update portion of the query.
* </p>
*
* @return A map between the assignments table and the excluded table
*/
public Map<Field<?>, Field<?>> toExcludedMap() {
final UserProgramAssignments excludedTable = UserProgramAssignment.pua.as("excluded");
final Map<Field<?>, Field<?>> excludedMap = new HashMap<>(4);
getAdministerProgram()
.ifPresent(i -> excludedMap.put(UserProgramAssignment.pua.ADMINISTER, excludedTable.ADMINISTER));
getCreateProjects().ifPresent(
i -> excludedMap.put(UserProgramAssignment.pua.CREATE_PROJECTS, excludedTable.CREATE_PROJECTS));
getJustification()
.ifPresent(i -> excludedMap.put(UserProgramAssignment.pua.JUSTIFICATION, excludedTable.JUSTIFICATION));
getViewRevisions().ifPresent(
i -> excludedMap.put(UserProgramAssignment.pua.VIEW_REVISIONS, excludedTable.VIEW_REVISIONS));
return excludedMap;
}
然后我调整了我的DAO这样做:
try (Connection writeConn = DatabaseManager.getConnection(true);
final DSLContext writeContext = DatabaseManager.getBuilder(writeConn);
InsertQuery<UserProgramAssignmentsRecord> programAssignmentsUpdateQuery = writeContext
.insertQuery(AccessControlWriteDAO.userProgramAssignments)) {
programAssignmentsUpdateQuery.onDuplicateKeyUpdate(true);
programAssignments
.forEach(assignment -> AccessControlWriteDAO.addRecordToUpsert(programAssignmentsUpdateQuery,
assignment.toRecord(), assignment.toExcludedMap()));
if (!programAssignments.isEmpty()) {
if (AccessControlWriteDAO.logger.isInfoEnabled()) {
AccessControlWriteDAO.logger.info(writeContext.renderInlined(programAssignmentsUpdateQuery));
}
programAssignmentsUpdateQuery.execute();
}
} catch (final SQLException e) {
throw new DAOException(e.getMessage(), e);
}
然后,为了保持清洁,我们创建了一个更新InsertQuery的新方法:
/**
* <p>
* This method is used to add a record and the update information to an UPSERT query.
* </p>
*
* @param query
* The query to add to
* @param record
* The record to add
* @param excludedMap
* The mappings to the "excluded" table for this record
*/
private static <R extends Record> void addRecordToUpsert(final InsertQuery<R> query, final R record,
final Map<Field<?>, Field<?>> excludedMap) {
query.addRecord(record);
query.addValuesForUpdate(excludedMap);
}
有点糟透了我们没有对称性,而我1)必须制作一张地图,2)必须进行另一个方法调用来获取但是我相信这是目前唯一的方法。如果jOOQ添加更新数据或至少记录并排除PK(因为如果我们在重复键上更新,显然PK没有改变)会很好,但也许这不是&# 39; t possible。