hibernate: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException - mysql

When saving an object to database using hibernate, it sometimes fails because of certain fields in the object exceeding the maximum varchar length defined in the database.
Therefore I am using the following approach:
Attempt to save
If getting an DataException, I then truncate the fields in the object to the max length specified in the db definition, then try to save again.
However, in the second save after truncation, I'm getting the following exception:
hibernate: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails
Here's the relevant code, do you notice anything wrong with it?
public static void saveLenientObject(Object obj){
try {
save2(rec);
} catch (org.hibernate.exception.DataException e) {
// TODO Auto-generated catch block
e.printStackTrace();
saveLenientObject(rec, e);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static void saveLenientObject(Object rec, DataException e) {
Util.truncateObject(rec);
System.out.println("after truncation ");
save2(rec);
}
public static void save2(Object obj) throws Exception{
try{
beginTransaction();
getSession().save(obj);
commitTransaction();
}catch(Exception e){
e.printStackTrace();
rollbackTransaction();
//closeSession();
throw e;
}finally{
closeSession();
}
}

All Hibernate exceptions (except for NonUniqueResultException) are irrecoverable. If you get an exception you should close the session and open another one for further operations.
See also:
13.2.3. Exception handling

The hibernate documentaiton is quite clear that once an exception is thrown the session will be left in an inconsistent state so is not safe to use for further operations. I suspect that what you're getting here is that the session is left half saving your first attempt so bad things happen.
Fundamentally you should not rely on database errors to check the length of your fields, instead you should pre-validate this in java code. If you know the lengths enough to truncate, then I suggest you simply call your trucate util every time.
Alternatively use Hibernate Validator to declaratively validate the objects before saving.

Related

How to throw SystemException in java?

I saw many people wrote like:
try {
//something
}
catch (IOException e){
throw new SystemException("IO Error", e);
}
I got "Cannot instantiate the type SystemException" error and it seems SystemException is a abstract class, how can I able to throw it?
Yes, it is an abstract class and that means that it does not make sense to construct an object of type SystemException. It is recommended to use more meaningful exceptions types.
You have mentioned IOException in your code. This means an exception related to an I/O operation and the catcher can act accordingly (maybe a special log level, some I/O cleanup etc.).
In your particular case, I think you should change it to:
try {
//something
}
catch (IOException e) {
// log exception info and other context information here
// e.g. e.printStackTrace();
// just rethrowing the exception (call stack is still there)
throw e;
}
P.S. Quite offtopic, but coming from .NET world I have found about the subtle difference between throw ex; in C# vs. Java.

Combining Multiple Exceptions in Custom Exception : Optimization

I have few similar methods and there calls as follows :
methodThrowingException() throws NullPointerException, InterruptedException, TimeoutException {
<method logic>
}
Calling class :
try{
methodThrowingExceptions();
<some other logic>
}
catch (NullPointerException npx) {
npx.printStackTrace();
log more details...
}
catch (InterruptedException inx) {
inx.printStackTrace();
log more details...
}
catch (TimeoutException tox) {
tox.printStackTrace();
log more details..
}
How (if) can I put all of these three in one Custom Exception?
Other than (1) is there a way to optimise the code so that I need not write the entire same statements for multiple methods?
Since Java 7, you can use a multi-catch block:
catch (NullPointerException | InterruptedException | TimeoutException e) {
e.printStackTrace();
log more details...
}
That said, you should never catch NullPointerException: that is a bug, and if it happens, the exception should bubble up. You can't reasonably expect a NPE to happen.
In addition, doing the same thing for an InterruptedException as for the other exceptions is also very dubious. When catching an InterruptedException, you should reset the interrupted flag on the current thread, and stop what you're doing ASAP.

How not to fail Hadoop MapReduce job for one database insert failure?

I'm writing a MapReduce job to mine webserver logs. The input is from text files, output goes to a MySQL database. Problem is, if one record fails to insert, for whatever reason, like data exceeding column size, the whole job fails and nothing gets written to the database. Is there a way so that the good records are still persisted? I guess one way would be to validate the data but that couples the client with the database schema too much for my taste.
I'm not posting the code because this is not particularly a code issue.
Edit:
Reducer:
protected void reduce(SkippableLogRecord rec,
Iterable<NullWritable> values, Context context) {
String path = rec.getPath().toString();
path = path.substring(0, min(path.length(), 100));
try {
context.write(new DBRecord(rec), NullWritable.get());
LOGGER.info("Wrote record {}.", path);
} catch (IOException | InterruptedException e) {
LOGGER.error("There was a problem when writing out {}.", path, e);
}
}
Log:
15/03/01 14:35:06 WARN mapred.LocalJobRunner: job_local279539641_0001
java.lang.Exception: java.io.IOException: Data truncation: Data too long for column 'filename' at row 1
at org.apache.hadoop.mapred.LocalJobRunner$Job.runTasks(LocalJobRunner.java:462)
at org.apache.hadoop.mapred.LocalJobRunner$Job.run(LocalJobRunner.java:529)
Caused by: java.io.IOException: Data truncation: Data too long for column 'filename' at row 1
at org.apache.hadoop.mapreduce.lib.db.DBOutputFormat$DBRecordWriter.close(DBOutputFormat.java:103)
at org.apache.hadoop.mapred.ReduceTask$NewTrackingRecordWriter.close(ReduceTask.java:550)
at org.apache.hadoop.mapred.ReduceTask.runNewReducer(ReduceTask.java:629)
at org.apache.hadoop.mapred.ReduceTask.run(ReduceTask.java:389)
at org.apache.hadoop.mapred.LocalJobRunner$Job$ReduceTaskRunnable.run(LocalJobRunner.java:319)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
15/03/01 14:35:06 INFO mapred.LocalJobRunner: reduce > reduce
15/03/01 14:35:07 INFO mapreduce.Job: Job job_local279539641_0001 failed with state FAILED due to: NA
Answering my own question and looking at this SO post, I see that the database write in done in a batch, and on SQLException, the transaction is rolled back. So that explains my problem. I guess I'll just have to make the DB columns big enough, or validate first. I can also create a custom DBOutputFormat/DBRecordWriter but unless I insert one record at a time, there'll always be a risk of one bad record causing the whole batch to rollback.
public void close(TaskAttemptContext context) throws IOException {
try {
LOG.warn("Executing statement:" + statement);
statement.executeBatch();
connection.commit();
} catch (SQLException e) {
try {
connection.rollback();
}
catch (SQLException ex) {
LOG.warn(StringUtils.stringifyException(ex));
}
throw new IOException(e.getMessage());
} finally {
try {
statement.close();
connection.close();
}
catch (SQLException ex) {
throw new IOException(ex.getMessage());
}
}
}

Why not every type are throw exceptions?

"Only the types that are inherited from the Throwable class can be thrown".
Could anybody explain me. Why not every type are throwable? If in doc there no mention about function can throw exception, it's mean that it do not have exception?
For example I thought that next try-catch block would work. But it is not.
try
{
writeln("(((((((((");
latestdtonpage = dts.sort!((a,b) => a>b).front; //latest date-time. from page.
}
catch(Exception e)
{
writeln("Can't select the latest Date from parsed date");
writeln(e);
}
But output in case of exception is next (no exception text):
(((((((((
core.exception.AssertError#C:\D\dmd2\windows\bin\..\..\src\phobos\std\array.d(73
9): Attempting to fetch the front of an empty array of DateTime
----------------
0x0051C4C9 in _d_assert_msg
0x00468E78 in pure nothrow ref #property #nogc #safe std.datetime.DateTime std.r
ange.__T11SortedRangeTAS3std8datetime8DateTimeS473app19StackOverflowParser5parse
MFAyaZ9__lambda2Z.SortedRange.front() at C:\D\dmd2\windows\bin\..\..\src\phobos\
std\range.d(8418)
0x0044F908 in void app.StackOverflowParser.parse(immutable(char)[]) at D:\code\T
rendoMetr\source\app.d(173)
0x0044F700 in app.StackOverflowParser app.StackOverflowParser.__ctor(app.DBConne
ct) at D:\code\TrendoMetr\source\app.d(150)
0x0044F199 in _Dmain at D:\code\TrendoMetr\source\app.d(33)
0x0052EDCA in D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZ9__lambda1MFZv
0x0052ED9F in void rt.dmain2._d_run_main(int, char**, extern (C) int function(ch
ar[][])*).runAll()
0x0052ECB5 in _d_run_main
0x00470198 in main
0x005667D1 in mainCRTStartup
0x76D1336A in BaseThreadInitThunk
0x772A9F72 in RtlInitializeExceptionChain
0x772A9F45 in RtlInitializeExceptionChain
Error executing command run: Program exited with code 1
How I can throw exception in this code?
Your code throws an AssertError, indicating that dts.sort!((a,b) => a>b) is empty, and you shouldn't call .front on it. Instead, query .empty first, and act accordingly when it's true.
AssertError inherits from Error which in turn inherits from Throwable but not from Exception. So catch(Exception e) doesn't catch it. And you should not catch Errors anyway, as they indicate that the program is in an unrecoverable error-state.
AssertError in particular signals a logic bug in your program. Here: calling .front on an empty range. Don't catch AssertError, but fix your code instead.

Spring MVC Exceptions

I have the following code in the Controller class and for some reason although i have exception handling implemented as well as a try.....catch block i am still unable to capture my exceptions.
I am just executing a test, in the DAO class i change the sql string that inserts into the database to leave out a column just so the DAO will fail. The DAO class fails and the error is written to the logs however even thou the officerManager.RegisterOfficer(officer) was not successful the code goes on to return the model.addAttribute("results","Record Was Saved").
This is not accurate and i would like for the controller to throw an error. Under is the code.
Controller
#RequestMapping(value="officer_registration.htm", method=RequestMethod.POST)
public ModelAndView handleRequest(#Valid #ModelAttribute Officers officer,BindingResult result,ModelMap m,Model model,HttpServletRequest request,HttpServletResponse response)throws Exception{
try{
if(result.hasErrors()){
model.addAttribute("division", myDivision);
model.addAttribute("position", myPosition);
model.addAttribute("gender", myGender);
return new ModelAndView("officer_registration");
}else{
//check the request if its an update or an insert
String user_request = request.getParameter("user_request");
logger.info("The Users Request Was " + user_request);
if (user_request.equals("Save")){
officerManager.RegisterOfficer(officer);
model.addAttribute("results","Record Was Saved");
}else{
officerManager.UpdateOfficer(officer);
model.addAttribute("results","Record Was Updated");
}
model.addAttribute("division", myDivision);
model.addAttribute("position", myPosition);
model.addAttribute("gender", myGender);
return new ModelAndView("officer_registration");
}
}catch(Exception e ){
model.addAttribute("division", myDivision);
model.addAttribute("position", myPosition);
model.addAttribute("gender", myGender);
model.addAttribute("results","Error: Unable to Save Record!");
return new ModelAndView("officer_registration");
}
}
DAO
public void saveOfficer(Officers officer) {
logger.info("In saveOfficer");
//SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
try{
int count = getJdbcTemplate().update("INSERT INTO crimetrack.tblofficers (userName,password, fName, lName, oName, divisionNo, positionId, emailAdd, startDate, endDate, genderId,phoneNo, dob,badgeNo) "+
"VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
, new Object[]{officer.getUserName(),StringSecurity.EncryptString(officer.getPassword()),officer.getfName(),
officer.getlName(),officer.getoName(),officer.getDivisionNo(),officer.getPositionId(),
officer.getEmailAdd(),officer.getStartDate(),officer.getEndDate(),officer.getGenderId(),
officer.getPhoneNo(),officer.getDob(),officer.getBadgeNo()});
logger.info(count +" Rows affected in tblOfficers");
}catch(Exception e){
logger.error("Could not save officer ", e);
}
}
You're not allowing the error to bubble up back to the controller.
You're handling the exception within the DAO, in which case the method exits normally, and no exception is caught within the Controller.
Either don't surround the DAO with a try catch and let the exception bubble back to the controller (recommended), or catch and rethrow the exception (if you follow this route, throw as a RuntimeException, either create your own, or rethrow as a RuntimeException, that way you won't have to catch all the way through the call stack.)
Also, it's generally frowned upon to catch generic exception as it is tougher to nail down exactly what caused it unless you look within the logs. Knowing which exceptions to handle ahead of time is usually better practice.