JFinal ORACLE 의 timestamp 필드 해결 방법
저 는 JFinal 을 사용 한 지 오래 되 었 습 니 다.프로젝트 의 데이터 베 이 스 는 Oacle 을 보편적으로 사용 하기 때문에 Oacle 을 사용 하 는 과정 에서 불편 한 점(예 를 들 어 ORACLE 의 자동 생 성 메 인 키,Oacle 에서 timestamp 필드 는 Oacle.sql.timestamp 등)을 만 났 습 니 다.다행히@JFinal 등 사람들의 도움 으로 문 제 를 해결 하 였 습 니 다.이번 에는 Oacle 에서 timestamp 필드 를 해결 하고 Oacle.sql.timestamp 로 돌아 가 는 방법 을 말 합 니 다.
Oacle 은 항상 남 다른 점 이 있 습 니 다.예 를 들 어 필드 는 기본적으로 지원 이 증가 하지 않 았 습 니 다.더 나 쁜 것 은 필드 반환 유형 이 다른 데이터 베이스 반환 유형 과 다 릅 니 다.예 를 들 어 timestamp 필드 는 우리 에 게 Oacle.sql.Timestamp 를 되 돌려 주 었 습 니 다.Oacle 자체 에 대해 서 는 평가 하지 않 습 니 다.
예전 에 JFinal 은 하나의 작은 프로젝트 에 만 사용 되 었 고 기본적으로 저 는 개인 적 으로 유지 하고 있 었 기 때문에 timestamp 에 부 딪 혀 수 동 으로 전환 할 수 밖 에 없 었 습 니 다.그러나 현재 JFinal 은 큰 프로젝트 에 사 용 했 고 개발 자 들 도 저 뿐만 이 아 닙 니 다.처음에 JFinal 이라는 간단 하고 효율 적 인 프레임 워 크 를 좋아 했 지만 timestamp 를 수 동 으로 처리 해 야 할 때 JFinal 에 실망 하여 수 동 으로 전환 할 수 밖 에 없 었 습 니 다.JFinal 에 대한 여러분 의 신뢰 를 높이 기 위해 저 는 JFINAL 이 필드 에 대한 처리 과정 을 진지 하 게 연구 한 결과 다음 과 같은 결론 을 얻 었 습 니 다.
1、 JFinal 은 시작 할 때 등 록 된 Model 과 데이터베이스 에 대응 하 는 table 을 일일이 연결 합 니 다.연결 하 는 과정 은 주로 TableInfoBuilder.buildTableInfo()를 통 해 TableInfo 대상 을 만 듭 니 다.이 대상 은 다음 과 같 습 니 다.
private String tableName;
private String primaryKey;
private String secondaryKey = null;
@SuppressWarnings("unchecked")
private Map<String, Class<?>> columnTypeMap = DbKit.containerFactory.getAttrsMap(); // new HashMap<String, Class<?>>();
사실 가장 핵심 적 인 것 은 이 columnTypeMap 대상 입 니 다.이 MAP 는 table 각 필드 의 이름과 유형 을 기록 하고 있 습 니 다. 추적 소스 코드 를 통 해 현재 JFinal 은 기본 값 으로 Oracle 의 timestamp 를 java.lang.String 형식 으로 변환 하고 TableInfo 를 만 드 는 방법 은 다음 과 같 습 니 다.
private static TableInfo doBuildTableInfo(TableInfo tableInfo,
Connection conn) throws SQLException {
TableInfo result = tableInfo;
String sql = DbKit.getDialect().forTableInfoBuilderDoBuildTableInfo(
tableInfo.getTableName());
Statement stm = conn.createStatement();
ResultSet rs = stm.executeQuery(sql);
ResultSetMetaData rsmd = rs.getMetaData();
for (int i = 1; i <= rsmd.getColumnCount(); i++) {
String colName = rsmd.getColumnName(i);
String colClassName = rsmd.getColumnClassName(i);
if ("java.lang.String".equals(colClassName)) {
// varchar, char, enum, set, text, tinytext, mediumtext,
// longtext
result.addInfo(colName, java.lang.String.class);
} else if ("java.lang.Integer".equals(colClassName)) {
// int, integer, tinyint, smallint, mediumint
result.addInfo(colName, java.lang.Integer.class);
} else if ("java.lang.Long".equals(colClassName)) {
// bigint
result.addInfo(colName, java.lang.Long.class);
} else if ("java.sql.Date".equals(colClassName)) {
// date, year
result.addInfo(colName, java.sql.Date.class);
} else if ("java.lang.Double".equals(colClassName)) {
// real, double
result.addInfo(colName, java.lang.Double.class);
} else if ("java.lang.Float".equals(colClassName)) {
// float
result.addInfo(colName, java.lang.Float.class);
} else if ("java.lang.Boolean".equals(colClassName)) {
// bit
result.addInfo(colName, java.lang.Boolean.class);
} else if ("java.sql.Time".equals(colClassName)) {
// time
result.addInfo(colName, java.sql.Time.class);
} else if ("java.sql.Timestamp".equals(colClassName)
|| "oracle.sql.TIMESTAMP".equals(colClassName)) {
// timestamp, datetime
result.addInfo(colName, java.sql.Timestamp.class);
} else if ("java.math.BigDecimal".equals(colClassName)) {
// decimal, numeric
result.addInfo(colName, java.math.BigDecimal.class);
} else if ("[B".equals(colClassName)) {
// binary, varbinary, tinyblob, blob, mediumblob, longblob
// qjd project: print_info.content varbinary(61800);
result.addInfo(colName, byte[].class);
} else {
int type = rsmd.getColumnType(i);
if (type == Types.BLOB) {
result.addInfo(colName, byte[].class);
} else if (type == Types.CLOB || type == Types.NCLOB) {
result.addInfo(colName, String.class);
} else {
result.addInfo(colName, String.class);
}
// core.TypeConverter
// throw new RuntimeException("You've got new type to mapping.
// Please add code in " + TableInfoBuilder.class.getName() + ".
// The ColumnClassName can't be mapped: " + colClassName);
}
}
rs.close();
stm.close();
return result;
}
2、 JFinal 이 Model 에 데 이 터 를 채 울 때 주로 ModelBuilder 를 실행 합 니 다.build(ResultSets,Classmodel Class)방법 은 다음 과 같 습 니 다.사실 이 과정 에서 JFinal 은 관여 하지 않 았 습 니 다(CLOB,NCLOB,BLOB 제외).데 이 터 는 JDBC 의 기본 방식 에 따라 되 돌 아 옵 니 다.
@SuppressWarnings({"rawtypes", "unchecked"})
public static final <T> List<T> build(ResultSet rs, Class<? extends Model> modelClass) throws SQLException, InstantiationException, IllegalAccessException {
List<T> result = new ArrayList<T>();
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
String[] labelNames = new String[columnCount + 1];
int[] types = new int[columnCount + 1];
buildLabelNamesAndTypes(rsmd, labelNames, types);
while (rs.next()) {
Model<?> ar = modelClass.newInstance();
Map<String, Object> attrs = ar.getAttrs();
for (int i=1; i<=columnCount; i++) {
Object value;
if (types[i] < Types.BLOB)
value = rs.getObject(i);
else if (types[i] == Types.CLOB)
value = handleClob(rs.getClob(i));
else if (types[i] == Types.NCLOB)
value = handleClob(rs.getNClob(i));
else if (types[i] == Types.BLOB)
value = handleBlob(rs.getBlob(i));
else
value = rs.getObject(i);
attrs.put(labelNames[i], value);
}
result.add((T)ar);
}
return result;
}
해결 방향:
데이터베이스 에 대한 데이터 조작 은 2 가지 가 있 습 니 다.set/get.Oacle 의 timestamp 를 my sql 의 timestamp 와 같이 바 꾸 기 위해 서 는 set/get 시 관여 해 야 합 니 다.상기 2 시 에 각각 set/get 작업 에 대응 해 야 합 니 다.원본 코드 를 수정 한 후에 테스트 를 통 해 사고방식 이 실행 가능 하 다 는 것 을 발견 했다.
1.doBuildTable Infoy()방법 에 서 는"java.sql.Timestamp".equals(colClassName)에||"Oacle.sql.TIMESTAMP".equals(colClassName)를 추가 하여 Oacle.sql.timestamp 를 식별 할 수 있 도록 합 니 다.
} else if ("java.sql.Timestamp".equals(colClassName)
|| "oracle.sql.TIMESTAMP".equals(colClassName)) {
// timestamp, datetime
result.addInfo(colName, java.sql.Timestamp.class);
2.ModelBuilder.build()중 for (int i = 1; i <= columnCount; i++){}순환 체 수정 은 다음 과 같 습 니 다.
for (int i = 1; i <= columnCount; i++) {
Object value;
if (types[i] == Types.CLOB)
value = handleClob(rs.getClob(i));
else if (types[i] == Types.NCLOB)
value = handleClob(rs.getNClob(i));
else if (types[i] == Types.BLOB)
value = handleBlob(rs.getBlob(i));
else if (types[i] == Types.TIMESTAMP
&& DbKit.dialect.isOracle()) {
// oracle.sql.timestamp --->java.sql.Timestamp
value = rs.getTimestamp(i);
} else {
value = rs.getObject(i);
}
attrs.put(labelNames[i], value);
}
PS:본인 의 글 은 기초 가 부족 하고 손 에 익 은 편집기 가 없 으 니 여러분 이 아 쉬 운 대로 보시 면 됩 니 다.버 전 라 이브 러 리 에 코드 를 업데이트 할 수 있 는 지@JFinal 에서 고려 해 주시 기 바 랍 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Flutter×Firebase Timestamp 날짜 및 시간 정보 표시흐름으로서는 ①Firestore의 timestamp로 시간 취득 ② 그 timestamp를 datetime으로 변경 ③ 텍스트로 표시 ① 이하의 코드로 timestamp라는 필드명으로 시간 취득 ②datetime으로...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.