mirror of
https://github.com/moparisthebest/JdbcMapper
synced 2024-11-26 02:42:24 -05:00
Add support for binding Blob, Clob, java.sql.Array to PreparedStatement in JdbcMapper
This commit is contained in:
parent
12fc0edbd4
commit
2162e35456
@ -65,6 +65,35 @@ public interface JdbcMapper extends Closeable {
|
|||||||
int arrayMaxLength() default -1;
|
int arrayMaxLength() default -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// these are to annotate parameters for special bind to PreparedStatement behavior
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use PreparedStatement.setBlob
|
||||||
|
*
|
||||||
|
* Only required for String
|
||||||
|
*
|
||||||
|
* Also valid for byte[], InputStream, Blob, File. But for those .setBlob is called even without this annotation
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@Target({ElementType.PARAMETER})
|
||||||
|
public @interface Blob {
|
||||||
|
/**
|
||||||
|
* The charsetName sent into String.getBytes()
|
||||||
|
*/
|
||||||
|
String charsetName() default "UTF-8";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use PreparedStatement.setClob
|
||||||
|
*
|
||||||
|
* Only valid for String
|
||||||
|
*
|
||||||
|
* Also valid for Clob, Reader. But for those .setClob is called even without this annotation
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@Target({ElementType.PARAMETER})
|
||||||
|
public @interface Clob {}
|
||||||
|
|
||||||
public enum OptionalBool {
|
public enum OptionalBool {
|
||||||
DEFAULT,
|
DEFAULT,
|
||||||
TRUE,
|
TRUE,
|
||||||
|
@ -31,8 +31,7 @@ public class JdbcMapperProcessor extends AbstractProcessor {
|
|||||||
|
|
||||||
private Types types;
|
private Types types;
|
||||||
private TypeMirror sqlExceptionType, stringType, numberType, utilDateType, readerType, clobType,
|
private TypeMirror sqlExceptionType, stringType, numberType, utilDateType, readerType, clobType,
|
||||||
byteArrayType, inputStreamType, fileType, blobType
|
byteArrayType, inputStreamType, fileType, blobType, sqlArrayType
|
||||||
//, clobStringType, blobStringType, arrayListObjectType
|
|
||||||
;
|
;
|
||||||
|
|
||||||
public JdbcMapperProcessor() {
|
public JdbcMapperProcessor() {
|
||||||
@ -58,11 +57,7 @@ public class JdbcMapperProcessor extends AbstractProcessor {
|
|||||||
//byteArrayType = this.types.getArrayType(elements.getTypeElement(byte.class.getCanonicalName()).asType());
|
//byteArrayType = this.types.getArrayType(elements.getTypeElement(byte.class.getCanonicalName()).asType());
|
||||||
//byteArrayType = elements.getTypeElement(byte.class.getCanonicalName()).asType();
|
//byteArrayType = elements.getTypeElement(byte.class.getCanonicalName()).asType();
|
||||||
byteArrayType = types.getArrayType(types.getPrimitiveType(TypeKind.BYTE));
|
byteArrayType = types.getArrayType(types.getPrimitiveType(TypeKind.BYTE));
|
||||||
/*
|
sqlArrayType = elements.getTypeElement(java.sql.Array.class.getCanonicalName()).asType();
|
||||||
clobStringType = elements.getTypeElement(ClobString.class.getCanonicalName()).asType();
|
|
||||||
blobStringType = elements.getTypeElement(BlobString.class.getCanonicalName()).asType();
|
|
||||||
arrayListObjectType = elements.getTypeElement(ArrayInList.ArrayListObject.class.getCanonicalName()).asType();
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -263,7 +258,7 @@ public class JdbcMapperProcessor extends AbstractProcessor {
|
|||||||
// now bind parameters
|
// now bind parameters
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (final VariableElement param : bindParams)
|
for (final VariableElement param : bindParams)
|
||||||
setObject(w, ++count, param.getSimpleName().toString(), param.asType());
|
setObject(w, ++count, param);
|
||||||
|
|
||||||
if (!parsedSQl.isSelect()) {
|
if (!parsedSQl.isSelect()) {
|
||||||
if (returnType.equals("void")) {
|
if (returnType.equals("void")) {
|
||||||
@ -352,54 +347,79 @@ public class JdbcMapperProcessor extends AbstractProcessor {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setObject(final Writer w, final int index, String variableName, final TypeMirror o) throws SQLException, IOException {
|
private void setObject(final Writer w, final int index, final VariableElement param) throws SQLException, IOException {
|
||||||
|
String variableName = param.getSimpleName().toString();
|
||||||
|
final TypeMirror o = param.asType();
|
||||||
w.write("\t\t\t");
|
w.write("\t\t\t");
|
||||||
// we are going to put most common ones up top so it should execute faster normally
|
|
||||||
String method = null;
|
String method = null;
|
||||||
// todo: avoid string concat here
|
|
||||||
if (o.getKind().isPrimitive() || types.isAssignable(o, stringType) || types.isAssignable(o, numberType)) {
|
// special behavior
|
||||||
method = "Object";
|
final JdbcMapper.Blob blob = param.getAnnotation(JdbcMapper.Blob.class);
|
||||||
// java.util.Date support, put it in a Timestamp
|
if(blob != null) {
|
||||||
} else if (types.isAssignable(o, utilDateType)) {
|
if (types.isAssignable(o, stringType)) {
|
||||||
method = "Object";
|
w.write("try {\n\t\t\t\tps.setBlob(");
|
||||||
// might need to wrap with Timestamp
|
w.write(Integer.toString(index));
|
||||||
if (types.isSameType(o, utilDateType))
|
w.write(", ");
|
||||||
variableName = "new java.sql.Timestamp(" + variableName + ".getTime())";
|
w.write(variableName);
|
||||||
// CLOB support
|
w.write(" == null ? null : new java.io.ByteArrayInputStream(");
|
||||||
} else if (types.isAssignable(o, readerType) || types.isAssignable(o, clobType)) {
|
w.write(variableName);
|
||||||
method = "Clob";
|
w.write(".getBytes(\"");
|
||||||
/*
|
w.write(blob.charsetName());
|
||||||
} else if (o instanceof ClobString) {
|
w.write("\")));\n\t\t\t} catch (java.io.UnsupportedEncodingException e) {\n" +
|
||||||
ps.setObject(index, ((ClobString) o).s == null ? null : ((ClobString) o).s);
|
"\t\t\t\tthrow new SQLException(\"String to Blob UnsupportedEncodingException\", e);\n" +
|
||||||
*/
|
"\t\t\t}\n");
|
||||||
// BLOB support
|
return;
|
||||||
} else if (types.isAssignable(o, byteArrayType)) {
|
} else if (!(types.isAssignable(o, inputStreamType) || types.isAssignable(o, blobType) || types.isAssignable(o, fileType) || types.isAssignable(o, byteArrayType))) {
|
||||||
method = "Blob";
|
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@JdbcMapper.Blob only valid for String, byte[], Blob, InputStream, and File", param);
|
||||||
variableName = "new java.io.ByteArrayInputStream(" + variableName + ")";
|
return;
|
||||||
} else if (types.isAssignable(o, inputStreamType) || types.isAssignable(o, blobType)) {
|
|
||||||
method = "Blob";
|
|
||||||
} else if (types.isAssignable(o, fileType)) {
|
|
||||||
// todo: does this close the InputStream properly????
|
|
||||||
w.write("\t\t\ttry {\n" +
|
|
||||||
"\t\t\t\tps.setBlob(" + index + ", new java.io.FileInputStream(" + variableName + "));\n" +
|
|
||||||
"\t\t\t} catch (java.io.FileNotFoundException e) {\n" +
|
|
||||||
"\t\t\t\tthrow new SQLException(\"File to Blob FileNotFoundException\", e);\n" +
|
|
||||||
"\t\t\t}");
|
|
||||||
return;
|
|
||||||
/*
|
|
||||||
} else if (o instanceof BlobString) {
|
|
||||||
try {
|
|
||||||
ps.setBlob(index, ((BlobString) o).s == null ? null : new ByteArrayInputStream(((BlobString) o).s.getBytes("UTF-8")));
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
throw new SQLException("String to Blob UnsupportedEncodingException", e);
|
|
||||||
}
|
}
|
||||||
} else if (o instanceof ArrayInList.ArrayListObject) {
|
|
||||||
ps.setArray(index, ((ArrayInList.ArrayListObject) o).getArray());
|
|
||||||
*/
|
|
||||||
} else {
|
} else {
|
||||||
// probably won't get here ever, but just in case...
|
final JdbcMapper.Clob clob = param.getAnnotation(JdbcMapper.Clob.class);
|
||||||
method = "Object";
|
if(clob != null) {
|
||||||
|
if (types.isAssignable(o, stringType)) {
|
||||||
|
method = "Clob";
|
||||||
|
variableName = variableName + " == null ? null : new StringReader("+variableName+")";
|
||||||
|
} else if (!(types.isAssignable(o, readerType) || types.isAssignable(o, clobType))) {
|
||||||
|
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@JdbcMapper.Clob only valid for String, Clob, Reader", param);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// end special behavior
|
||||||
|
|
||||||
|
// we are going to put most common ones up top so it should execute faster normally
|
||||||
|
// todo: avoid string concat here
|
||||||
|
if(method == null)
|
||||||
|
if (o.getKind().isPrimitive() || types.isAssignable(o, stringType) || types.isAssignable(o, numberType)) {
|
||||||
|
method = "Object";
|
||||||
|
// java.util.Date support, put it in a Timestamp
|
||||||
|
} else if (types.isAssignable(o, utilDateType)) {
|
||||||
|
method = "Object";
|
||||||
|
// might need to wrap with Timestamp
|
||||||
|
if (types.isSameType(o, utilDateType))
|
||||||
|
variableName = "new java.sql.Timestamp(" + variableName + ".getTime())";
|
||||||
|
// CLOB support
|
||||||
|
} else if (types.isAssignable(o, readerType) || types.isAssignable(o, clobType)) {
|
||||||
|
method = "Clob";
|
||||||
|
} else if (types.isAssignable(o, inputStreamType) || types.isAssignable(o, blobType)) {
|
||||||
|
method = "Blob";
|
||||||
|
} else if (types.isAssignable(o, fileType)) {
|
||||||
|
// todo: does this close the InputStream properly????
|
||||||
|
w.write("\t\t\ttry {\n" +
|
||||||
|
"\t\t\t\tps.setBlob(" + index + ", new java.io.FileInputStream(" + variableName + "));\n" +
|
||||||
|
"\t\t\t} catch (java.io.FileNotFoundException e) {\n" +
|
||||||
|
"\t\t\t\tthrow new SQLException(\"File to Blob FileNotFoundException\", e);\n" +
|
||||||
|
"\t\t\t}");
|
||||||
|
return;
|
||||||
|
} else if (types.isAssignable(o, byteArrayType)) {
|
||||||
|
method = "Blob";
|
||||||
|
variableName = "new java.io.ByteArrayInputStream(" + variableName + ")";
|
||||||
|
} else if (types.isAssignable(o, sqlArrayType)) {
|
||||||
|
method = "Array";
|
||||||
|
} else {
|
||||||
|
// probably won't get here ever, but just in case...
|
||||||
|
method = "Object";
|
||||||
|
}
|
||||||
w.write("ps.set");
|
w.write("ps.set");
|
||||||
w.write(method);
|
w.write(method);
|
||||||
w.write('(');
|
w.write('(');
|
||||||
|
@ -28,6 +28,9 @@ public interface PersonDAO {
|
|||||||
@JdbcMapper.SQL("UPDATE person SET first_name = {firstName} WHERE person_no = {personNo}")
|
@JdbcMapper.SQL("UPDATE person SET first_name = {firstName} WHERE person_no = {personNo}")
|
||||||
void setFirstNameBlob(byte[] firstName, long personNo) throws SQLException;
|
void setFirstNameBlob(byte[] firstName, long personNo) throws SQLException;
|
||||||
|
|
||||||
|
@JdbcMapper.SQL("UPDATE person SET first_name = {firstName} WHERE person_no = {personNo}")
|
||||||
|
void setFirstNameBlob(@JdbcMapper.Blob String firstName, long personNo) throws SQLException;
|
||||||
|
|
||||||
@JdbcMapper.SQL("SELECT first_name FROM person WHERE person_no = {personNo}")
|
@JdbcMapper.SQL("SELECT first_name FROM person WHERE person_no = {personNo}")
|
||||||
String getFirstName(long personNo) throws SQLException;
|
String getFirstName(long personNo) throws SQLException;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user