Java 数据层次结构和行映射
Java Data Hierarchy and Row Mapping
我有一个应用程序需要用一些重复的行对一些现有的数据库表(我无法更改它们)进行建模。我正在尝试找出一个好的设计来尽可能多地重用映射代码,这样我就不必重复一堆设置调用。
这是其中两个表格的示例。
TIME_AND_EXPENSE_STAGING
Name Null Type
------------------ -------- --------------
SEQ_NUM NOT NULL NUMBER(31)
DATETIME_STAMP TIMESTAMP(6)
DEPT_ID NOT NULL VARCHAR2(10)
EMPL_ID NOT NULL VARCHAR2(11)
JOB_CODE NOT NULL VARCHAR2(6)
REGULAR_HRS NOT NULL NUMBER(4,2)
OVERTIME_HRS NOT NULL NUMBER(4,2)
MILES NOT NULL NUMBER(8,2)
COMMENTS VARCHAR2(4000)
TIME_AND_EXPENSE_APPROVED
Name Null Type
------------------ -------- --------------
SEQ_NUM NOT NULL NUMBER(31)
DATETIME_STAMP TIMESTAMP(6)
DEPT_ID NOT NULL VARCHAR2(10)
EMPL_ID NOT NULL VARCHAR2(11)
JOB_CODE NOT NULL VARCHAR2(6)
REGULAR_HRS NOT NULL NUMBER(4,2)
OVERTIME_HRS NOT NULL NUMBER(4,2)
MILES NOT NULL NUMBER(8,2)
COMMENTS VARCHAR2(4000)
APPROVE_TIME NOT NULL TIMESTAMP(6)
APPROVER_ID NOT NULL VARCHAR2(11)
我正在使用 Spring 框架和 Spring RowMapper 来填充数据对象。我觉得应该有一些优雅的方式来使用继承或多态性或一些设计模式来防止我不得不复制和粘贴一堆 set 语句。
请指教
在处理这类数据时,我个人倾向于使用不可变对象。想象以下 class:
public class TimeAndExpense {
private final String jobCode;
// and a bunch of other attributes such as department...
// Then the additional data (approval data)
private final Optional<String> approverId;
private final Optional<Timestamp> approveTime;
public TimeAndExpense(final String jobCode) {
this(jobCode, null, null);
}
public TimeAndExpense(
final String jobCode,
final Timestamp approveTime,
final String approverId) {
this.jobCode = jobCode;
// And the rest of the attributes...
this.approveTime = Optional.ofNullable(approveTime);
this.approverId = Optional.ofNullable(approverId);
}
public Optional<Timestamp> getApproveTime() {
return approveTime;
}
public Optional<String> getApproverId() {
return approverId;
}
public String getJobCode() {
return jobCode;
}
public boolean isApproved() {
return approverId.isPresent();
}
// Creates a new object with the approval data (immutable)
public TimeAndExpense withApprovalData(final Timestamp approveTime, final String approverId) {
return new TimeAndExpense(this.getJobCode(), approveTime, approverId);
}
}
方法 withApprovalData
可用于创建具有附加批准数据的 TimeAndExpense
对象。以这种方式使用时,您可以像这样设置 RowMapper
s:
// The RowMapper for the table TIME_AND_EXPENSE_STAGING
// More columns than JOB_CODE exists but are not part of the example
private final RowMapper<TimeAndExpense> timeAndExpenseRowMapper =
(rs, rowNum) -> new TimeAndExpense(rs.getString("JOB_CODE"));
// The RowMapper for the table TIME_AND_EXPENSE_APPROVED
// Reuse the timeAndExpenseRowMapper's mapping, then add additional approval data
private final RowMapper<TimeAndExpense> timeAndExpenseApprovedRowMapper =
(rs, rowNum) -> timeAndExpenseRowMapper
.mapRow(rs, rowNum) // use the timeAndExpenseRowMapper
.withApprovalData( // and add the additional approval data
rs.getTimestamp("APPROVE_TIME"),
rs.getString("APPROVER_ID"));
这种委派(一个 RowMapper
使用另一个 RowMapper
)在表非常相似并且可以实现大量代码重用时效果很好。
继承是我个人尽量少用的东西in favour of composition。但是,对于域模型来说,拥有某种包含例如一个 id(因为例如 Department
、Employee
和 TimeAndExpense
对象似乎都包含一个 id,甚至可能是一个时间戳)。
我有一个应用程序需要用一些重复的行对一些现有的数据库表(我无法更改它们)进行建模。我正在尝试找出一个好的设计来尽可能多地重用映射代码,这样我就不必重复一堆设置调用。
这是其中两个表格的示例。
TIME_AND_EXPENSE_STAGING
Name Null Type
------------------ -------- --------------
SEQ_NUM NOT NULL NUMBER(31)
DATETIME_STAMP TIMESTAMP(6)
DEPT_ID NOT NULL VARCHAR2(10)
EMPL_ID NOT NULL VARCHAR2(11)
JOB_CODE NOT NULL VARCHAR2(6)
REGULAR_HRS NOT NULL NUMBER(4,2)
OVERTIME_HRS NOT NULL NUMBER(4,2)
MILES NOT NULL NUMBER(8,2)
COMMENTS VARCHAR2(4000)
TIME_AND_EXPENSE_APPROVED
Name Null Type
------------------ -------- --------------
SEQ_NUM NOT NULL NUMBER(31)
DATETIME_STAMP TIMESTAMP(6)
DEPT_ID NOT NULL VARCHAR2(10)
EMPL_ID NOT NULL VARCHAR2(11)
JOB_CODE NOT NULL VARCHAR2(6)
REGULAR_HRS NOT NULL NUMBER(4,2)
OVERTIME_HRS NOT NULL NUMBER(4,2)
MILES NOT NULL NUMBER(8,2)
COMMENTS VARCHAR2(4000)
APPROVE_TIME NOT NULL TIMESTAMP(6)
APPROVER_ID NOT NULL VARCHAR2(11)
我正在使用 Spring 框架和 Spring RowMapper 来填充数据对象。我觉得应该有一些优雅的方式来使用继承或多态性或一些设计模式来防止我不得不复制和粘贴一堆 set 语句。
请指教
在处理这类数据时,我个人倾向于使用不可变对象。想象以下 class:
public class TimeAndExpense {
private final String jobCode;
// and a bunch of other attributes such as department...
// Then the additional data (approval data)
private final Optional<String> approverId;
private final Optional<Timestamp> approveTime;
public TimeAndExpense(final String jobCode) {
this(jobCode, null, null);
}
public TimeAndExpense(
final String jobCode,
final Timestamp approveTime,
final String approverId) {
this.jobCode = jobCode;
// And the rest of the attributes...
this.approveTime = Optional.ofNullable(approveTime);
this.approverId = Optional.ofNullable(approverId);
}
public Optional<Timestamp> getApproveTime() {
return approveTime;
}
public Optional<String> getApproverId() {
return approverId;
}
public String getJobCode() {
return jobCode;
}
public boolean isApproved() {
return approverId.isPresent();
}
// Creates a new object with the approval data (immutable)
public TimeAndExpense withApprovalData(final Timestamp approveTime, final String approverId) {
return new TimeAndExpense(this.getJobCode(), approveTime, approverId);
}
}
方法 withApprovalData
可用于创建具有附加批准数据的 TimeAndExpense
对象。以这种方式使用时,您可以像这样设置 RowMapper
s:
// The RowMapper for the table TIME_AND_EXPENSE_STAGING
// More columns than JOB_CODE exists but are not part of the example
private final RowMapper<TimeAndExpense> timeAndExpenseRowMapper =
(rs, rowNum) -> new TimeAndExpense(rs.getString("JOB_CODE"));
// The RowMapper for the table TIME_AND_EXPENSE_APPROVED
// Reuse the timeAndExpenseRowMapper's mapping, then add additional approval data
private final RowMapper<TimeAndExpense> timeAndExpenseApprovedRowMapper =
(rs, rowNum) -> timeAndExpenseRowMapper
.mapRow(rs, rowNum) // use the timeAndExpenseRowMapper
.withApprovalData( // and add the additional approval data
rs.getTimestamp("APPROVE_TIME"),
rs.getString("APPROVER_ID"));
这种委派(一个 RowMapper
使用另一个 RowMapper
)在表非常相似并且可以实现大量代码重用时效果很好。
继承是我个人尽量少用的东西in favour of composition。但是,对于域模型来说,拥有某种包含例如一个 id(因为例如 Department
、Employee
和 TimeAndExpense
对象似乎都包含一个 id,甚至可能是一个时间戳)。