Win a copy of Re-engineering Legacy Software this week in the Refactoring forum
or Docker in Action in the Cloud/Virtualization forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Solution to DuplicateKeyException

 
Jared Chapman
Ranch Hand
Posts: 81
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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 ]
 
Barend Garvelink
Ranch Hand
Posts: 64
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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.
 
Jared Chapman
Ranch Hand
Posts: 81
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 64
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 4982
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
 
Jim Janssens
Ranch Hand
Posts: 210
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 181
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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.
 
Jim Janssens
Ranch Hand
Posts: 210
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Daniel: so basicly you took every field as primary key except the owner field...
 
Jared Chapman
Ranch Hand
Posts: 81
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 181
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic