This week's giveaway is in the Android forum.
We're giving away four copies of Android Security Essentials Live Lessons and have Godfrey Nolan on-line!
See this thread for details.
The moose likes Developer Certification (SCJD/OCMJD) and the fly likes Solution to DuplicateKeyException Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Android Security Essentials Live Lessons this week in the Android forum!
JavaRanch » Java Forums » Certification » Developer Certification (SCJD/OCMJD)
Bookmark "Solution to DuplicateKeyException " Watch "Solution to DuplicateKeyException " New topic
Author

Solution to DuplicateKeyException

Jared Chapman
Ranch Hand

Joined: Feb 23, 2004
Posts: 81
Hello all,

Just wanted to run my proposed solution to the DuplicateKeyException problem for B&S Contractors by anyone interested.

In order to throw a DKException, there needs to be a primary key in the database. The specifications don't provide a primary key, and I am not comfortable picking one. Some have proposed using the record number, but since deleted records can be reused, I don't like this idea. Most people using a primary key are using name + location, but I don't want to use this solution, either. It is reasonable to assume that there could be more than one branch of Dogs With Tools in a city the size of Chicago, for example. Granted, in that situation you could specify the locations as "North Chicago" and "South Chicago", but none of the records in the supplied database use this format.

So here is my proposed solution. In my Data class, I have a boolean array called: When I initialize my database, I first read in the schema, and then initialize this array with the following:
Also in my Data class, I have an inner class called Record, which as the name implies, represents a record in the database. This class stores the int recNo and String[] data of a record. I have overridden the default equals method as follows:


Also, I have a Map used as a record cache, which stores (recNo, record) key-value pairs. When I enter the create method, I call recordCache.containsValue(record_to_be_created), and throw a DuplicateKeyException if the result is true. By default, this exception will never be thrown, because all values in primaryKeyFields are initialized to false.

If in the future B&S wanted to specify a primary key, such as name + location, then all I would have to do is call another method I created in Data called setPrimaryKeyFields(boolean[] primaryKeyFields).

For the name+location primary key, this call would look like:

What do y'all think?
[ December 08, 2004: Message edited by: Jared Chapman ]

B.S. University of Wisconsin<br />SCJP 1.4 (85%)<br />SCJD 1.4 (92%) B&S Contractors
Barend Garvelink
Ranch Hand

Joined: Dec 07, 2004
Posts: 64
In order to throw a DKException, there needs to be a primary key in the database. The specifications don't provide a primary key, and I am not comfortable picking one. Some have proposed using the record number, but since deleted records can be reused, I don't like this idea. Most people using a primary key are using name + location, but I don't want to use this solution, either. It is reasonable to assume that there could be more than one branch of Dogs With Tools in a city the size of Chicago, for example. Granted, in that situation you could specify the locations as "North Chicago" and "South Chicago", but none of the records in the supplied database use this format.


Given the reasoning above, which is sound & solid and can go straight into choices.txt; the most logical solution (in my opinion) is to simply not throw the declared exception at all. In urlybird I found one other convincing argument for that angle, but I'm not sure if it also applies to B&S, nor if I should post it here.


SCJP 1.4, SCJD 1.4, SCWCD 1.3, ICSD:Websphere 5.1
Jared Chapman
Ranch Hand

Joined: Feb 23, 2004
Posts: 81
Hi Barend,

I agree with you in that I wouldn't have to throw the exception at all for the required specifications. I decided to implement it this way for two reasons:

First, this way I can document the fact that I did implement a conscious solution to preventing duplicate records from being inserted into the database. I simply just use a really really relaxed definition of duplicate (i.e. none of the records will be duplicate, unless I decide to use all fields EXCEPT the owner field). By the way, since you don't have B&S, the fields are: Name, Location, Specialties, Size, Rate, and Owner, where owner is the ID# of the customer who has booked the contractor.

Second, I don't have any B&S specific code in my Data class. I use it as a class to perform basic database operations on ANY database file that follows the provided schema. And since records in a database file should have a primary key, I believe my Data class should provide functionality to utilize a primary key. This makes my Data class more reuseable. If a zoo wanted to use my Data class for performing operations on a database file to keep track of animal food inventory, it would work, provided their database file followed the schema. And if they defined a primary key, I wouldn't have to modify my create method at all - I would just create an instance of Data, and then call setPrimaryKeyFields(boolean[]); In the case of B&S contractors, where there is no concrete information pointing to a primary key, I would simply just not call setPrimaryKeyFields(boolean).
Barend Garvelink
Ranch Hand

Joined: Dec 07, 2004
Posts: 64
If your choices.txt is as thorough as your posts on this forum, you have nothing to worry about. Go for it!

Barend
Nicholas Cheung
Ranch Hand

Joined: Nov 07, 2003
Posts: 4982
Basically, according to the *user requirement*, you will have NO WAY to encounter with this exception under any circumstances.

Thus, no matter you declare it or not, it makes no difference.

Nick


SCJP 1.2, OCP 9i DBA, SCWCD 1.3, SCJP 1.4 (SAI), SCJD 1.4, SCWCD 1.4 (Beta), ICED (IBM 287, IBM 484, IBM 486), SCMAD 1.0 (Beta), SCBCD 1.3, ICSD (IBM 288), ICDBA (IBM 700, IBM 701), SCDJWS, ICSD (IBM 348), OCP 10g DBA (Beta), SCJP 5.0 (Beta), SCJA 1.0 (Beta), MCP(70-270), SCBCD 5.0 (Beta), SCJP 6.0, SCEA for JEE5 (in progress)
Jim Janssens
Ranch Hand

Joined: Sep 24, 2004
Posts: 210
Yes, I must admit that is very good way of thinking. This way you are basicly creating dynamic primary keys.

However, there could be problems when changing the primary keys after data is allready in the database. Supose you have these fields in the db:

A,B
B,B
C,G

First you put the primary key on the first field. After these records are inserted you change it to include both of the fields. This way searching the db on a primary key will return 2 values, which is impossible. But I'm sure this won't be an issue, I just want to mention it. Your solutions sounds very good !

Untill now I did by assigning all the fields as primary key minus the book field...
Daniel Simpson
Ranch Hand

Joined: Sep 02, 2004
Posts: 181
Hey Jared, a very good question. I used the DuplicateKeyException using the following implementation. I first grabbed the values from that specific record and did a comparison with those against the passed-in values. I did not compare the owner (customer id) field because I realized that if it was booked and I compared that field, a duplicate could be made, because theoretically it didn't have the same owner field. So if every field matches the same, I throw the DPKException. I think the one argument about multiple branches in a city is a good point, but past the scope of this assignment. I would note though in future implementations that, that would be a good idea to consider. Hope this helps.


SCJP 1.4<br />SCJD 1.4
Jim Janssens
Ranch Hand

Joined: Sep 24, 2004
Posts: 210
Daniel: so basicly you took every field as primary key except the owner field...
Jared Chapman
Ranch Hand

Joined: Feb 23, 2004
Posts: 81
This way you are basicly creating dynamic primary keys.
However, there could be problems when changing the primary keys after data is allready in the database


Good point. Perhaps I'll get rid of my setPrimaryKeyFields method, make my boolean array final, and include another constructor that takes a boolean array as an argument:

private final boolean[] primaryKeyFields;

public Data(String filePath){...}

public Data(String filePath, boolean[] primaryKeyFields){...}
Daniel Simpson
Ranch Hand

Joined: Sep 02, 2004
Posts: 181
Originally posted by Koen Serneels:
Daniel: so basicly you took every field as primary key except the owner field...

Hey Koen-
That is exactly what I did. I do not feel that any field in the database is sufficient enough to be considered a primary key. There are the same contractors but in different locations, so neither the name nor location can be primary. Also, the cost, etc. can not be used as a primary either. For this implementation, I decided to not use a specific primary key but to test the values of every field exluding owner as my primary key. Future implementations may decide to make a field that serves as a primary key.
 
 
subject: Solution to DuplicateKeyException
 
Similar Threads
B&S: DuplicateRecordException
The method public void lock(int recNo) throws RecordNotFoundException does not make sense to me
updating a primary key field
B&S:understanding of "search the data for all records" and create record
DuplicateKeyException - B&S