我想让Table的Generated Ids返回给用户。这是我的代码:
1)POJO
public class AuditRecord<K, U> {
private K id;
private String context;
private U contextIdentifier;
@JsonSerialize(using = JsonJodaDateTimeSerializer.class)
@JsonDeserialize(using = JsonJodaDateTimeDeSerializer.class)
private DateTime time;
private String code;
private String description;
private PartyRole<?> creator;
private Collection<Session<?>> sessions;
/**
* Default constructor,reflectively picked by frameworks like jaxb to create and initialise the state of object.
*/
private AuditRecord() {
}
private AuditRecord(final AuditRecordBuilder<K, U> builder) {
this();
this.id = builder.id;
this.context = builder.context;
this.contextIdentifier = builder.contextIdentifier;
this.time = builder.time;
this.description = builder.description;
this.creator = builder.creator;
this.sessions = builder.sessions;
this.code = builder.code;
}
public K getId() {
return id;
}
public String getCode() {
return code;
}
public String getDescription() {
return description;
}
public String getContext() {
return context;
}
public U getContextIdentifier() {
return contextIdentifier;
}
public DateTime getTime() {
return time;
}
public Collection<Session<?>> getSessions() {
return sessions;
}
public PartyRole<?> getCreator() {
return creator;
}
/**
* Builder Class of AuditRecord which populates mandatory fields and allows some of its fields to be populated
* optionally,
* making AuditRecord immutable at the same time.
* @param <K> Identifier for the record.
* @param <U> Identifier for the context Identifier.
*/
public static class AuditRecordBuilder<K, U> {
private K id;
private String context;
private U contextIdentifier;
private DateTime time;
private String code;
private String description;
private PartyRole<?> creator;
private Collection<Session<?>> sessions;
/**
* Builder constructor only receives the required attributes.
* @param id
* @param time
* @param code
* @param description
*/
public AuditRecordBuilder(final K id, final DateTime time, final String code, final String description) {
this.code = code;
this.id = id;
this.time = time;
this.description = description;
}
/**
* Initialise optional attributes context.
* @param contextForAuditRecord
* @return
*/
public AuditRecordBuilder<K, U> setContext(final String contextForAuditRecord) {
this.context = contextForAuditRecord;
return this;
}
/**
* Initialise optional attributes sessions.
* @param sessionsForAuditRecord
* @return
*/
public AuditRecordBuilder<K, U> setSessions(final Collection<Session<?>> sessionsForAuditRecord) {
this.sessions = sessionsForAuditRecord;
return this;
}
/**
* Initialise optional attributes creator.
* @param creatorForAuditRecord
* @return
*/
public AuditRecordBuilder<K, U> setCreator(final PartyRole<?> creatorForAuditRecord) {
this.creator = creatorForAuditRecord;
return this;
}
/**
* Initialise optional attributes context identifier.
* @param contextIdentifierForAuditRecord
* @return
*/
public AuditRecordBuilder<K, U> setCreator(final U contextIdentifierForAuditRecord) {
this.contextIdentifier = contextIdentifierForAuditRecord;
return this;
}
/**
* Method finally returns the built instance.
* @return
*/
public AuditRecord<K, U> build() {
return new AuditRecord<K, U>(this);
}
}
@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
@Override
public boolean equals(final Object obj) {
return EqualsBuilder.reflectionEquals(this, obj);
}
@Override
public final String toString() {
return ToString.generateToString(this);
}
}
2)Mapper as below
@Component
public interface AuthenticationAuditMapper {
/**
* Insert the audit record in History table and returned the generated sequence ID.
* @param auditRecord
* @return
*/
void
createAuditRecord(@Param("auditRecord") AuditRecord<Long, String> auditRecord, @Param("seqNumber") Long seqNumber);
}
3)Mapping xml as
<mapper namespace="com.avios.domain.repository.audit.support.mybatis.AuthenticationAuditMapper">
<insert id="createAuditRecord" parameterType="com.avios.domain.model.audit.AuditRecord" useGeneratedKeys="true"
keyProperty="auditRecord.id" keyColumn="AUTH_HISTORY_ID" >
INSERT INTO TAUTHHIST
(USER_SEQ_NO, HISTORY_DESCRIPTION, APP_SESSION_ID, CMS_SESSION_ID,
CREATED_BY,
FK_TAUTHHISTYPAUTH_HISTORY_ENT)
VALUES (
#{auditRecord.contextIdentifier},
#{auditRecord.description},
#{auditRecord.sessions[0].id},
null, #{auditRecord.creator.id}, #{auditRecord.code}
)
</insert>
</mapper>
问题是我无法取回用户生成的密钥。但是,如果我在插入语句中使用<selectKey>
,我能够得到它,如下所示:
<selectKey keyProperty="auditRecord.id" resultType="java.lang.Long" order="AFTER"> select SEQ_TAUTHHIST.currval from dual </selectKey>
答案 0 :(得分:0)
我假设您正在使用Oracle DB。在Oracle中,使用Statement#getGeneratedKeys()
检索自动生成的密钥的传统JDBC方法不起作用。 MyBatis也使用这个JDBC函数。有关详细说明,请参阅BalusC的this和that答案。实际上,Oracle的自动生成ID通常只是SEQUENCE
和BEFORE TRIGGER
用法的组合。
来自MyBatis doc:
首先,如果您的数据库支持自动生成的密钥字段(例如MySQL) 和SQL Server),然后你可以简单地设置useGeneratedKeys =“true”和 将keyProperty设置为target属性,然后就完成了。 [code here] MyBatis有另一种方法可以处理不支持自动生成的列类型的数据库的密钥生成,或者可能还不支持对自动生成的密钥的JDBC驱动程序支持。
另请参阅Oracle Docs中的Retrieval of Auto-Generated Keys。
答案 1 :(得分:0)
您可以通过以下更改从插入中获取自动生成的值:
用户选择标记而不是插入标记,并返回生成的查询结束ID
完整代码如下所示:
<select id="createAuditRecord" parameterType="com.avios.domain.model.audit.AuditRecord" useGeneratedKeys="true"
keyProperty="auditRecord.id" keyColumn="AUTH_HISTORY_ID" >
INSERT INTO TAUTHHIST
(USER_SEQ_NO, HISTORY_DESCRIPTION, APP_SESSION_ID, CMS_SESSION_ID,
CREATED_BY,
FK_TAUTHHISTYPAUTH_HISTORY_ENT)
VALUES (
#{auditRecord.contextIdentifier},
#{auditRecord.description},
#{auditRecord.sessions[0].id},
null, #{auditRecord.creator.id}, #{auditRecord.code}
)RETURNING "auth_history_id" <!-- this is your generated table id column name -->
</select>