Java PostgreSQL使用记录进行Upsert
我目前正在尝试使用记录执行upsert(使用3.10-snapshot),并注意到当我使用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
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显然没有改变),那就太好了,但这可能是不可能的