Martin Vajsar

Sheriff
+ Follow
since Aug 22, 2010
Martin likes ...
Chrome Netbeans IDE Oracle
Forum Moderator
Martin Vajsar currently moderates these forums:
Cows and Likes
Cows
Total received
62
In last 30 days
0
Total given
123
Likes
Total received
624
Received in last 30 days
0
Total given
711
Given in last 30 days
0
Forums and Threads
Scavenger Hunt
(keep public parts private until JForum day)
expand Rancher Scavenger Hunt
expand Ranch Hand Scavenger Hunt
expand Greenhorn Scavenger Hunt
Moderation Tools

Recent posts by Martin Vajsar

When I was using Oracle DCN (in the Oracle 11 database), the documentation specifically mentioned that the functionality is meant for tables which are mostly read-only, ie. only rarely modified. It probably wasn't designed for the heavy updates you're experiencing in your DB. We had much lower volume of updates and still decided to ditch DCN, as it wasn't practical for us.

Are the inserts made by a single, or a few large transactions, or are there lots and lots of small transactions inserting a few rows each? The latter would quite certainly be more problematic, as it would trigger lots and lots of notifications. I'm afraid you might have to choose a different solution to the entire problem.
I think Dave is right about the batch rewrite.

If you don't use the rewrite, does the index of the first -3 (ie. Statement.EXECUTE_FAILED) in the array correspond to the index of the bad statement? If this is so, you could obtain the first failing statement this way and disregard anything that happened afterwards (you'll rollback the transaction).

However, without the rewrite, there's probably no significant speedup using batches with the Connector/J driver. And without batches, the situation would be much easier to handle.

Generally speaking, your application should only attempt to execute SQL statements that are expected to go through. In this case, if something fails, you'd log as much about the problem as possible and have the situation handled as an incident.

If you want to use the database to identify problems with the data you're writing to it, and the end user to be able to identify and resolve the issue, that's a much, much more complex situation to handle (even without using update batching).
Which database are you using?

Unfortunately, different JDBC drivers might implement this functionality differently. If you're lucky, the documentation of the JDBC driver you're using will contain a section on batch update error handling.

If you're using a specific database/JDBC driver, you might create a specific handling of the BatchUpdateException tailored to the JDBC driver in question. If you don't know in advance which JDBC driver is going to be used, your best bet is to log as much information as possible and use it when the exception happens to figure out what went wrong.
I guess that the problem lies here:

John Francis Ochotorina wrote:



This loop goes through all records in the resultset, and calls setSelectedItem on individual combo boxes. Note that setSelectedItem doesn't add new item into the combo box's list, it just sets the text in the combo box.

Let's say that there are N records returned by your query. On the first execution of the body of the while loop, the combo boxes are set up with the texts contained in the first record. On the second execution, the cmbo boxes are set up with the texts contained in the second record - setSelectedItem overwrites what was there before. And so on for the third, fourth, ... Nth record.

The loop terminates when all records are processed, leaving your combo boxes set to the contents of the last record. For simple SELECT queries, databases sometimes (not always) return rows in the order in which they were inserted to the database - therefore you always end up with values from the last record in your combo boxes. Note: if you want to obtain rows in a specific order, always use the ORDER BY clause to specify that order.

If you want your combo boxes to contain all of the records returned by the query, use the addItem or insertItem method - see Javadoc.
The solution you've posted seems okay (assuming you fix the issue pointed out by Fred!) - you don't call overridable method of your own class from your MyAddItem method. The disadvantage of this solution is that you duplicate code of the original AddItem method. If the original AddItem changes for any reason, you (or someone else) must not forget to update MyAddItem as well. The chances of updating that method are slim, but this kind of code duplication is very unfortunate.

My advice would be:
  • If you can't foresee the MachineSelect having any children, make it final. Document why it is final.
  • If you think it could have a subclass sometime, you could still make the AddItem method final inside the MachineSelect class (and document why is it made final).
  • Other than that, the solution #5 I've posted yesterday avoids both duplicate code and unexpected side effects.

  • None of these solutions creates a time bomb of any sort (at least as far as calling overridable methods from constructor goes).
    2 years ago

    Fred Kleinschmidt wrote:The private method could even call super.addItem() if desired (for example, if it wants to do whatever its superclass does, plus add logging).


    In this case, any extended functionality (logging) has to be put into the same class. It wouldn't work in a subclass. So, if we have to modify the MachineSelect class anyway, we can make the method or the entire class final - it will fix the issue and it will be transparent.

    In almost all cases, your solution is very good. I'm not saying that it would be a problem for OP's case. My logging example is artificial; I just wanted to point out that it makes the call from the constructor non-overridable, and it can lead to unexpected behavior, especially in complicated class hierarchies.
    2 years ago
    It can be made to work and even re-use the inherited functionality:

    This produces:
    Parent
    Child
    Instance constructed
    Parent
    Child
    Grandchild, value=5


    It still has a small disadvantage that the (indirect) method call in the constructor doesn't invoke Grandchild's implementation. Of course, we did it precisely to avoid Grandchild's method from being called this way, but it's not immediately obvious.

    Let's say someone would want to monitor item creation in the OP's class. He could extend MachineSelect, override AddItem and add logging to the overriden method. However, he would then observe items being created by the class constructor, and no trace about them in the log. In other words, it's a solution which has some non-obvious side effects. In a really, really complicated projects, it could give some headaches.
    2 years ago

    Fred Kleinschmidt wrote:NO - you NEVER call the overridden method from the private method. It's the other way around. The overridden method calls the private method, and the private method does all the work.


    You're right, that's a good approach.

    However, if I have understood this particular case well, the method which needs to be called from the constructor is the AddItem method, which is inherited from the parent class. That approach therefore can't be employed here directly, some more refactoring of the class hierarchy would be needed.
    2 years ago

    J. Kevin Robbins wrote:That did it! No warnings, the code works the same, and I feel better about having more robust code in the project.


    Depending on exact circumstances, that might not actually fix the issue. If you call an overridable method from your private method (edit: I assume you do; you need to call AddItem inherited from the parent class), you don't get the warning, but still can get the wrong behavior. Consider:

    This code produces the following output:

    Grandchild, value=0
    Grandchild, value=5


    We can see the value of a final attribute has changed. This is one of the ways this problem manifests itself.

    Note: in my IDE, I don't get any warning on this code, but I don't get any even when I call method directly in the constructor - don't know why. Static code checkers, such as FindBugs, should be able to identify this issue in both forms, though.

    In my opinion, there are a few options of handling this case:

    1) Do nothing. Just document methods that are called from constructors, so that developers are aware what's happening. That's obviously risky, especially if some developers on the team aren't well acquainted with the ramifications of this arrangement.

    2) Make the method final in the class that calls the method in its constructor. That is a good solution if the child classes of the problematic class do not need to override the method. It might work for you, if I understand your case well. The code would look like this:

    3) Make your entire Child class final. This obviously fixes the issue, but you can't create subclasses.

    4) If you don't override the method in your class, you can call the super version of the method in constructor:
    Caveat: in your case, someone might want to create a child from your class and override AddItem to do some additional action. He or she will wonder why his/her overriden method wasn't called when you were adding the items in your constructor calls.

    5) Move the logic from your constructor elsewhere. You could create a static method that will create the instance and then call the overridable methods from the outside of the constructor. You don't introduce unwanted side effects, the class is still inheritable and the method isn't final. Applied to your case it might look like this:
    This is probably the cleanest solution, if you can't make your class final. The only downside is that the logic that was originally in the constructor isn't inheritable now.

    Note: this code mixes JDBC code and UI creation, and I think it isn't a good idea. I'd suggest separating these two pieces of code, having a DAO class that would read from the database into some data class (perhaps just a list of POJO items) and use that list to construct the GUI controls. But this is unrelated to the issue you've asked about.
    2 years ago
    When you call an overridable method from a constructor, there is a risk that a child class will override that method and access attributes it declares. When the constructor executes, the overriden method is called, but the attributes declared in the child class aren't initialized yet. Even its constructor hasn't been called finished yet (edit: it has been called, but it called parent class constructor as its first action and that call hasn't returned yet).

    If the child method doesn't use any attributes of the child class, it's safe. If it accesses them, strange things can happen - the class could "see" a final attribute change its value, for example.

    (As far as I know, C++ "solves" this issue by calling the original, not overriden, method from constructor. Hard to say which solution is better.)
    2 years ago
    I believe that connection which is doing some work shouldn't time out, but I might be wrong.

    However, I've noticed this is a batch update exception. I've seen network errors to happen when using large batches, specifically with Oracle. It's natural to expect that the bigger the batch, the better - and faster, but unfortunately a batch which is too large (larger than, say, a hundred of records) isn't going to perform any better than moderately sized batches and can actually fail.

    How large are your batches, Jay?
    You'd probably need to post the relevant code for anyone to be able to help you.

    Given very little information available, my guess would be that your batches are too big. How many records are you deleting in one batch?
    When you need to find out what's going on in your code, a few strategically placed System.out.println() statements can go a long way.

    In other words, add some logging to your while loop and if statement to be able to tell what your program is doing when you run it. Ideally, output the details of each record as you process it. Then post the output of your program here, as well as your current code.

    Puspender Tanwar wrote:well i am amazed of this... why not that problem is occuring with the same code now ???


    My guess is that on the first successful run, all names in the database which were equal to "puspen" were changed to "puspender", and on subsequent runs your code never enters the body of the if statement and the update doesn't happen. Therefore, no error.