how to get parameter when mybatis exception - exception

I'm sorry. I can't write English well.
this is my mybatis error message(e.getMessage())
### Error updating database. Cause: com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data too long for column 'name' at row 1
### The error may involve default.user-Inline
### The error occurred while setting parameters
### SQL: INSERT INTO USER (name) VALUES (?)
### Cause: com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data too long for column 'name'
at row 1; SQL []; Data truncation: Data too long for column 'name' at row 1; nested exception is
com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data too long for column 'name' at row 1
I want know parameter when Exception occur.
SQL: INSERT INTO USER (name) VALUES (?) >> I want get this question value.
i try this code
try {
sqlSessionTemplate.insert("namespace.id", parameter);
} catch (Exception e) {
if (e instanceof BadSqlGrammarException) {
logger.error("{}", e.getMessage());
} else if (e instanceof DataIntegrityViolationException) {
logger.error("{}", e.getMessage());
} else if (e instanceof MysqlDataTruncation) {
logger.error("{}", e.getMessage());
}
}
DataIntegrityViolationException, MysqlDataTruncation does not support get error paramters.
this is a sample, I want know get parameters(object) in Exception.
Can you give me some advice to solve this problem?Thanks.

Set up logging in MyBatis and set it to TRACE level. That way you will have your whole INSERT statement (with actually used parameters) written in the log file.

you can write a mybatis's plugin,as follow:
#Intercepts({ #Signature(type = ParameterHandler.class, method = "setParameters", args = { PreparedStatement.class }) })
public class SQLErrorContextInterceptor implements Interceptor {
private final ILogger logger = new LoggerImpl(this.getClass());
#Override
public Object intercept(Invocation invocation) throws Throwable {
invocation.proceed();
Object target=invocation.getTarget();
if( ! (target instanceof DefaultParameterHandler) ){
return null;
}
DefaultParameterHandler hander=(DefaultParameterHandler)target;
//obtains 5 fields from DefaultParameterHandler object
Class<?> clz =hander.getClass();
Field f = clz.getDeclaredField("mappedStatement");
f.setAccessible(true);
MappedStatement mappedStatement=(MappedStatement)f.get(hander);
Configuration configuration = mappedStatement.getConfiguration();
TypeHandlerRegistry typeHandlerRegistry=mappedStatement.getConfiguration().getTypeHandlerRegistry();
f=clz.getDeclaredField("boundSql");
f.setAccessible(true);
BoundSql boundSql=(BoundSql)f.get(hander);
Object parameterObject=hander.getParameterObject();
//used to stored parameters values order by sql parameters
List<Object> columnValues = new ArrayList<Object>();
// get parameters'value by for-each
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
if (parameterMappings != null) {
MetaObject metaObject = parameterObject == null ? null : configuration.newMetaObject(parameterObject);
for (int i = 0; i < parameterMappings.size(); i++) {
ParameterMapping parameterMapping = parameterMappings.get(i);
if (parameterMapping.getMode() != ParameterMode.OUT) {
Object value;
String propertyName = parameterMapping.getProperty();
if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
value = boundSql.getAdditionalParameter(propertyName);
} else if (parameterObject == null) {
value = null;
} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
value = parameterObject;
} else {
value = metaObject == null ? null : metaObject.getValue(propertyName);
}
columnValues.add(value);
}
}
}
// overwrite sql's context in ErrorContext, and append parameters's value-str
ErrorContext.instance().sql(boundSql.getSql() + " parameters:" + this.getParameterValueString(columnValues));
return null;
}
private String getParameterValueString(List<Object> columnValues) {
List<Object> typeList = new ArrayList<Object>(columnValues.size());
for (Object value : columnValues) {
if (value == null) {
typeList.add("null");
} else {
typeList.add(value + "(" + value.getClass().getSimpleName() + ")");
}
}
final String parameters = typeList.toString();
return parameters.substring(1, parameters.length() - 1);
}
#Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
#Override
public void setProperties(Properties properties) {
}
}

Related

NewtonSoft.Json Treating Blank Value as Null but not throwing error

Environment
.net 7
Using Both System.Text.Json
Also NewtonSoft.Json ( 13.0.2)
Example code
string str = #"{
""DateTimeNull"":""""
}";
try
{
var t = System.Text.Json.JsonSerializer.Deserialize<Test>(str);
}
catch (JsonException ex)
{
Console.WriteLine(new { Field = ex.Path , Message = ex.Message });
}
try
{
var t = Newtonsoft.Json.JsonConvert.DeserializeObject<Test>(str);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
public class Test
{
public DateTime? DateTimeNull { get; set; }
}
In above System.Text.Json Deserlizer throw exception but newtonsoft.json line is not throwing any exception. It is converting empty value to null but I want it should thow error and due to limitation I can not move to System.Text.Json as of now.
Payload ( This is i already set in str)
Sample one
#"{
""DateTimeNull"":""""
}";
Expected result: Throw error and should not convert to null.
Sample two.
#"{
""DateTimeNull"": null
}";
Expected result: Should not throw error and it is null value and destination type is null.
I usually recommend to use a JsonConstructor:
var json = #"{
""DateTimeNull"":""""
}";
Test test = JsonConvert.DeserializeObject<Test>(json);
public class Test
{
public DateTime? DateTimeNull { get; set; }
[Newtonsoft.Json.JsonConstructor]
public Test(JToken DateTimeNull)
{
if (DateTimeNull.Type == JTokenType.Null) this.DateTimeNull = null;
else if ((string)DateTimeNull == string.Empty)
throw new JsonException("DateTimeNull property should not be an empty string");
else this.DateTimeNull = DateTimeNull.ToObject<DateTime>();
}
}

Why org.apache.commons.lang.StringUtils.isBlank() returns false for empty and null values

I saw the implementation of StringUtils.isBlank() and was surprised that in my case, it is not working as expected.
I was writing a Junit and I faced this issue.
AmazonSNSRegistrationService.java:
public String doAWSSNSNDeviceRegistration(Map<String, Object> jsonBody){
String deviceId = (String) jsonBody.get(PushNotificationsConstants.DEVICE_ID);
String pushToken = (String) jsonBody.get(PushNotificationsConstants.PUSH_TOKEN);
String appId = (String) jsonBody.get(PushNotificationsConstants.APP_ID);
if (StringUtils.isBlank(deviceId) || StringUtils.isBlank(pushToken) || StringUtils.isBlank(appId)) {
System.out.println("$$$$$ Empty");
throw new Exception("Required parameters are empty.");
}
return registerWithSNS(pushToken, deviceId, appId);
}
AmazonSNSRegistrationServiceTest.java:
#Test
public void doAWSSNSNDeviceRegistrationBlankTest() {
Map<String, Object> jsonBody = new HashMap<String, Object>();
jsonBody.put(PushNotificationsConstants.APP_ID, "");
jsonBody.put(PushNotificationsConstants.DEVICEID, " ");
try{
amazonSNSRegistrationService.doAWSSNSNDeviceRegistration(jsonBody);
}
catch(Exception e){
}
}
I'm not passing Push Token , so it will be null. Other values are either "" or " ".
But in if condition, none of the statements give true. All return false and the Exception is not thrown. I want this code to throw exception when any of the statement in if (StringUtils.isBlank(deviceId) || StringUtils.isBlank(pushToken) || StringUtils.isBlank(appId)) returns true.

Java Service Error - webMethods

In a java service, without a function declaration, a function call is there and only compile time error comes. But the output is as expected with no run time errors. How is that possible? Can anyone please explain?
"The method functionName() is undefined" is the error it shows.
Below is the code.
public static final void documentToStringVals(IData pipeline)
throws ServiceException {
// pipeline
IDataCursor pipelineCursor = pipeline.getCursor();
String success = "false";
IData inputDoc = null;
String outputValue = "";
String headerYN = "N";
boolean headerValue = false;
String delimiter = ",";
String newline = System.getProperty("line.separator");
if (pipelineCursor.first("inputDocument") ) {
inputDoc = (IData) pipelineCursor.getValue();
}
else {
throw new ServiceException("inputDocument is a required parameter");
}
if (pipelineCursor.first("delimiter") ) {
delimiter = (String) pipelineCursor.getValue();
}
if (pipelineCursor.first("headerYN") ) {
headerYN = (String) pipelineCursor.getValue();
}
if (headerYN.equalsIgnoreCase("Y")) {
headerValue = true;
}
try {
outputValue = docValuesToString(inputDoc, headerValue, delimiter);
outputValue += newline;
success = "true";
}
catch (Exception e) {
System.out.println("Exception in getting string from document: " + e.getMessage());
pipelineCursor.insertAfter("errorMessage", e.getMessage());
}
pipelineCursor.insertAfter("success", success);
pipelineCursor.insertAfter("outputValue", outputValue);
pipelineCursor.destroy();
}
The code you posted has no reference to "functionName", so I suspect there's a reference to it either in the shared code section or in another Java service in the same folder. Given that all Java services in a folder get compiled into a single class, and therefore all those services need to be compiled together, this could cause the error message when you're compiling the service above.

jdbcTemplate pass in null value

I'm working with mysql and spring 4.1.6, but am having trouble sending in a null variable to the data base. I know to send a null value the syntax IS NULL is used but the field being sent into the data base is optional(the only optional value in the entire object), so it may be null or may have a value.
My request to database that simple checks if the address exists called by CRUD methods:
Note: the variable in question is street2
public boolean doesExist(Address address){
String sql = "SELECT EXISTS(SELECT * FROM Address WHERE contactType=? AND street1=? AND street2 ? AND city=? AND state=? AND zip=? AND country=?);";
String s = isNullDBQuery(address.getStreet2());
jdbcTemplate = new JdbcTemplate(dataSource);
int exist = jdbcTemplate.queryForObject(sql, new Object[] {address.getContactType().name(), address.getStreet1(), isNullDBQuery(address.getStreet2()), address.getCity(), address.getState().name(), address.getZip(), address.getCountry().name()}, Integer.class);
if(exist == 1){
return true;
} else {
return false;
}
}
My isNullDBQuery:
private String isNullDBQuery(String s){
if(s == null){
return "IS NULL";
} else {
return "=" + s;
}
}
The error that's being returned is a syntax error with 'IS NULL'. The query sent to the database is street2 'IS NULL' rather then street2 IS NULL. Is it possible to get rid of the single quotation marks in my request? or is there a better way to do this?
any help is appreciated
No. Only values may be passed as parameters of a prepared statement. Not arbitrary portions of the query.
You need to use two different SQL queries (or generate it dynamically based on the nullness of the street2).
I managed to figure out how to achieve what I wanted:
public boolean doesExist(Address address){
String street2 = stringIsNull(address.getStreet2());
String sql = "SELECT EXISTS(SELECT * FROM Address WHERE contactType=? AND street1=? AND street2 " + street2 + " AND city=? AND state=? AND zip=? AND country=?);";
jdbcTemplate = new JdbcTemplate(dataSource);
int exist;
if(street2.equals("IS NULL")){
exist = jdbcTemplate.queryForObject(sql, new Object[] {address.getContactType().name(), address.getStreet1(), address.getCity(), address.getState().name(), address.getZip(), address.getCountry().name()}, Integer.class);
} else {
exist = jdbcTemplate.queryForObject(sql, new Object[] {address.getContactType().name(), address.getStreet1(), address.getStreet2(), address.getCity(), address.getState().name(), address.getZip(), address.getCountry().name()}, Integer.class);
}
if(exist == 1){
return true;
} else {
return false;
}
}
private String stringIsNull(String string){
if(string == null) {
return "IS NULL";
} else {
return "=?";
}
}

Google end point returns JSON for long data type in quotes

I am using Google cloud end point for my rest service. I am consuming this data in a GWT web client using RestyGWT.
I noticed that cloud end point is automatically enclosing a long datatype in double quotes which is causing an exception in RestyGWT when I try to convert JSON to POJO.
Here is my sample code.
#Api(name = "test")
public class EndpointAPI {
#ApiMethod(httpMethod = HttpMethod.GET, path = "test")
public Container test() {
Container container = new Container();
container.testLong = (long)3234345;
container.testDate = new Date();
container.testString = "sathya";
container.testDouble = 123.98;
container.testInt = 123;
return container;
}
public class Container {
public long testLong;
public Date testDate;
public String testString;
public double testDouble;
public int testInt;
}
}
This is what is returned as JSON by cloud end point. You can see that testLong is serialized as "3234345" rather than 3234345.
I have the following questions.
(1) How can I remove double quotes in long values ?
(2) How can I change the string format to "yyyy-MMM-dd hh:mm:ss" ?
Regards,
Sathya
What version of restyGWT are you using ? Did you try 1.4 snapshot ?
I think this is the code (1.4) responsible for parsing a long in restygwt, it might help you :
public static final AbstractJsonEncoderDecoder<Long> LONG = new AbstractJsonEncoderDecoder<Long>() {
public Long decode(JSONValue value) throws DecodingException {
if (value == null || value.isNull() != null) {
return null;
}
return (long) toDouble(value);
}
public JSONValue encode(Long value) throws EncodingException {
return (value == null) ? getNullType() : new JSONNumber(value);
}
};
static public double toDouble(JSONValue value) {
JSONNumber number = value.isNumber();
if (number == null) {
JSONString val = value.isString();
if (val != null){
try {
return Double.parseDouble(val.stringValue());
}
catch(NumberFormatException e){
// just through exception below
}
}
throw new DecodingException("Expected a json number, but was given: " + value);
}
return number.doubleValue();
}