I am facing this problem when migrating some legacy ibatis sql code.
The sql code(oracle) is put here:
Code:
select id, report_id, file_name, file_type, file_size, page_size,flag,
nvl2(pdf_content,1,0) as pdf_exist,
nvl2(swf_content,1,0) as swf_exist
from report_files
where id = #id#
and the according data model is as below:
Code:
public class ReportAttachModel {
private String fileType;
public String getFileType() {
return fileType;
}
public void setFileType(String fileType) {
this.fileType = fileType;
}
private String fileName;
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
private Integer fileId;
public Integer getFileId() {
return fileId;
}
public void setFileId(Integer fileId) {
this.fileId = fileId;
}
private String fileMainName;
public String getFileMainName() {
return fileMainName;
}
public void setFileMainName(String fileMainName) {
this.fileMainName = fileMainName;
}
private Integer pdfContentExist;
public Integer getPdfContentExist() {
return pdfContentExist;
}
public void setPdfContentExist(Integer pdfContentExist) {
this.pdfContentExist = pdfContentExist;
}
}
My first try is using "UserType", and here is my implementation:
Code:
public class HibernateLobExistenceFlagUserType implements UserType {
private static final int[] SQL_TYPES = {java.sql.Types.BLOB, java.sql.Types.CLOB, java.sql.Types.NCLOB};
@Override
public Object assemble(Serializable cached, Object owner) throws HibernateException {
return cached;
}
@Override
public Object deepCopy(Object value) throws HibernateException {
return value;
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
return (Boolean) value;
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
if (x == y) {
return true;
} else if (x == null || y == null) {
return false;
} else {
return x.equals(y);
}
}
@Override
public int hashCode(Object x) throws HibernateException {
return x.hashCode();
}
@Override
public boolean isMutable() {
return false;
}
private int getRsColumnIndex(ResultSetMetaData rsMeta, String colName) throws SQLException {
for (int i = 1, s = rsMeta.getColumnCount(); i <= s; i++) {
String refColName = rsMeta.getColumnName(i);
if (rsMeta.isCaseSensitive(i)) {
if (colName.equals(refColName)) {
return i;
}
} else {
if (colName.equalsIgnoreCase(refColName)) {
return i;
}
}
}
return -1;
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
int colIdx = getRsColumnIndex(rs.getMetaData(), names[0]);
if (colIdx <= 0) {
throw new SQLException("col " + names[0] + " found in result set meta, fatal error");
}
int sqlType = rs.getMetaData().getColumnType(colIdx);
switch (sqlType) {
case java.sql.Types.BLOB:
Blob blob = rs.getBlob(colIdx);
if (blob != null) {
return true;
}
break;
case java.sql.Types.CLOB:
Clob clob = rs.getClob(colIdx);
if (clob != null) {
return true;
}
break;
case java.sql.Types.NCLOB:
NClob nclob = rs.getNClob(colIdx);
if (nclob != null) {
return true;
}
break;
}
return false;
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
if (!(value instanceof Boolean)) {
throw new HibernateException("type not expected, expected Boolean");
}
//this is just a flag, not updatable.
return;
}
@Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return original;
}
@SuppressWarnings("unchecked")
@Override
public Class returnedClass() {
return Boolean.class;
}
@Override
public int[] sqlTypes() {
return SQL_TYPES;
}
}
However, I am a little concerned the efficiency of this approach when comparing to the old one , since if the "rs.getXLob()" operation actually load the content, the design goal of this existence flag is meaningless then.
Any suggestion or discussion is much appreciated. Thanks ;-)