Java PostgreSQL使用记录进行Upsert

Java PostgreSQL使用记录进行Upsert,java,sql,jooq,Java,Sql,Jooq,我目前正在尝试使用记录执行upsert(使用3.10-snapshot),并注意到当我使用addRecord(R)时,更新的set数据没有添加到查询中。在DAO中,我有: try(connectionwritecon=DatabaseManager.getConnection(true); 最终DSLContext writeContext=DatabaseManager.getBuilder(writeConn); InsertQuery programAssignmentsUpdateQue

我目前正在尝试使用记录执行upsert(使用3.10-snapshot),并注意到当我使用
addRecord(R)
时,更新的
set
数据没有添加到查询中。在DAO中,我有:

try(connectionwritecon=DatabaseManager.getConnection(true);
最终DSLContext writeContext=DatabaseManager.getBuilder(writeConn);
InsertQuery programAssignmentsUpdateQuery=writeContext
.insertQuery(AccessControlWriteDAO.userProgramAssignments)){
programAssignmentsUpdateQuery.onDuplicateKeyUpdate(true);
programAssignmentsUpdateQuery.addRecord(pa.toreCold());
如果(!programAssignments.isEmpty()){
if(AccessControlWriteDAO.logger.IsInfo已启用()){
AccessControlWriteDAO.logger.info(writeContext.RenderLined(programAssignmentsUpdateQuery));
}
//programAssignmentsUpdateQuery.execute();
}
}捕获(最终SQLE异常){
抛出新的异常(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;
}

我是否必须切换到使用
addValue(字段,T)
addValueForUpdateField(字段,T)
和newRecord?我本以为传递记录是等效的,但事实似乎并非如此,因为
addRecord(R)
似乎没有设置要更新的字段-或者-我在
toRecord()方法中是否做错了什么?对于
InsertQuery
对象,是否存在某种类型的
addRecordForUpdate(R)
?这对多行upserts(我正试图这么做)有多好?

在查看文档后,我认为这有点。。。缺乏。。。。虽然有人可能认为
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;
}
    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);
    }
/**
*
*此方法返回可在查询的更新部分的UPSERT中使用的映射。
*

* *@返回分配表和排除表之间的映射 */ 公共地图>toExcludedMap(){ 最终UserProgramAssignments excludedTable=UserProgramAssignment.pua.as(“排除”); 最终映射>excludedMap=新哈希映射(4); getAdministerProgram() .ifPresent(i->excludedMap.put(UserProgramAssignment.pua.administrate,excludedTable.administrate)); getCreateProjects().ifPresent( i->excludedMap.put(UserProgramAssignment.pua.CREATE_PROJECTS,excludedTable.CREATE_PROJECTS)); getjustion() .ifPresent(i->excludedMap.put(UserProgramAssignment.pua.JUSTIFICATION,excludedTable.JUSTIFICATION)); getViewRevisions().ifPresent( i->excludedMap.put(UserProgramAssignment.pua.VIEW_REVISIONS,excludedTable.VIEW_REVISIONS)); 返回排除地图; }
然后我调整了我的刀,这样做:

/**
 * <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;
}
    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);
    }
try(connectionwritecon=DatabaseManager.getConnection(true);
最终DSLContext writeContext=DatabaseManager.getBuilder(writeConn);
InsertQuery programAssignmentsUpdateQuery=writeContext
.insertQuery(AccessControlWriteDAO.userProgramAssignments)){
programAssignmentsUpdateQuery.onDuplicateKeyUpdate(true);
课程作业
.forEach(赋值->AccessControlWriteDAO.addRecordToUpsert(programAssignmentsUpdateQuery,
assignment.toRecord()、assignment.toExcludedMap());
如果(!programAssignments.isEmpty()){
if(AccessControlWriteDAO.logger.IsInfo已启用()){
AccessControlWriteDAO.logger.info(writeContext.RenderLined(programAssignmentsUpdateQuery));
}
programAssignmentsUpdateQuery.execute();
}
}捕获(最终SQLE异常){
抛出新的异常(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);
}
/**
*
*此方法用于向UPSERT查询添加记录和更新信息。
*

* *@param查询 *要添加到的查询 *@param记录 *要添加的记录 *@param excludedMap *此记录到“排除”表的映射 */ 私有静态void addRecordToUpsert(最终插入查询、最终R记录、, 最终地图>不包括地图){ query.addRecord(记录); query.addValuesForUpdate(不包括dMap); }
这有点糟糕,我们没有对称性,我1)必须制作一个地图,2)必须进行另一个方法调用以获取数据,但我相信这是目前唯一的方法。如果jOOQ添加了更新数据或者至少接收了一条记录并排除了PK(因为如果我们更新的是重复的密钥,那么PK显然没有改变),那就太好了,但这可能是不可能的