@@ -239,8 +239,11 @@ protected final void init(long id, String...fieldNames) throws SQLException {
239239 */
240240 public void save () throws SQLException {
241241
242+ //Get class name
243+ String className = this .getClass ().getName ();
242244
243- //Get list if fields and thier associated values
245+
246+ //Get list of fields and thier associated values
244247 LinkedHashMap <java .lang .reflect .Field , Object > fields = getFields ();
245248 Iterator <java .lang .reflect .Field > it ;
246249
@@ -267,28 +270,33 @@ public void save() throws SQLException {
267270
268271
269272 //Update values as needed
273+ int numNulls = 0 ;
270274 for (Map .Entry <java .lang .reflect .Field , Object > entry : fields .entrySet ()) {
271275 Object val = entry .getValue ();
272276 if (val !=null ){
273277 if (val instanceof Model ){
274- entry .setValue (((Model ) val ).getID ());
278+ Model model = (Model ) val ;
279+ model .save ();
280+ entry .setValue (model .getID ());
275281 }
276282 else if (val instanceof JSONObject ){
277283 JSONObject json = (JSONObject ) val ;
278284 if (json .isEmpty ()) entry .setValue (null );
279285 }
280286 }
287+ if (entry .getValue ()==null ) numNulls ++;
281288 }
282289
283290
291+ //Check if there's anything to save
292+ if (numNulls ==fields .size ()) return ;
284293
285294
286295
287296 if (id ==null ){ //insert new record using prepared statement (faster than recordset)
288297
289298
290299 //Get database fields associated with the model
291- String className = this .getClass ().getName ();
292300 Field [] dbFields ;
293301 synchronized (this .fields ){ dbFields = this .fields .get (className ); }
294302 if (dbFields ==null ) throw new SQLException (
@@ -424,8 +432,13 @@ else if (packageName.startsWith("javaxt.geospatial.geometry") ||
424432
425433
426434 //Insert record
427- Recordset .update (stmt , updates );
428- stmt .executeUpdate ();
435+ try {
436+ Recordset .update (stmt , updates );
437+ stmt .executeUpdate ();
438+ }
439+ catch (SQLException e ){
440+ throw Exception ("Failed to save " + className + ". " + e .getMessage (), e );
441+ }
429442
430443
431444 //Get id
@@ -479,7 +492,7 @@ else if (packageName.startsWith("javaxt.geospatial.geometry") ||
479492 }
480493 catch (SQLException e ){
481494 if (conn !=null ) conn .close ();
482- throw e ;
495+ throw Exception ( "Failed to update " + className + "#" + id + ". " + e . getMessage (), e ) ;
483496 }
484497 }
485498 }
@@ -500,11 +513,33 @@ public void delete() throws SQLException {
500513 }
501514 catch (SQLException e ){
502515 if (conn !=null ) conn .close ();
503- throw e ;
516+ String className = this .getClass ().getName ();
517+ throw Exception ("Failed to delete " + className + "#" + id + ". " + e .getMessage (), e );
504518 }
505519 }
506520
507521
522+ //**************************************************************************
523+ //** getException
524+ //**************************************************************************
525+ /** Used to build a custom exception when saving or deleting records.
526+ */
527+ private SQLException Exception (String err , SQLException e ){
528+ SQLException ex = new SQLException (err );
529+ ArrayList <StackTraceElement > stackTrace = new ArrayList <StackTraceElement >();
530+ boolean addElement = false ;
531+ StackTraceElement [] arr = ex .getStackTrace ();
532+ for (int i =2 ; i <arr .length ; i ++){
533+ StackTraceElement el = arr [i ];
534+ if (!el .getClassName ().contains ("reflect" )) addElement = true ;
535+ if (addElement ) stackTrace .add (el );
536+ }
537+ ex .setStackTrace (stackTrace .toArray (new StackTraceElement [stackTrace .size ()]));
538+ ex .setNextException (e );
539+ return ex ;
540+ }
541+
542+
508543 //**************************************************************************
509544 //** toJson
510545 //**************************************************************************
0 commit comments