aspose file tools*
The moose likes Developer Certification (SCJD/OCMJD) and the fly likes Create method [B&S] Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Certification » Developer Certification (SCJD/OCMJD)
Bookmark "Create method [B&S]" Watch "Create method [B&S]" New topic
Author

Create method [B&S]

Jim Janssens
Ranch Hand

Joined: Sep 24, 2004
Posts: 210
The create method of my database facade is not business logic aware. This means that it does not know anyting about 'owner' fields or anything like that. It just creates the record I pass to it in the database.

There is no need to have syncrhonization in my database facade, since update & delete use lock cookies in my Data class, and physical locking is handled on the lowest level (database file read/write methods) .

Create() is also safe, since the lowest write is syncrhonized. Meaning that no more then one record can be created at the same time. The assignment of a record number occurs also in that synchronized write method, so I also do not need to worry that multiple creates are done on the same record number.

Now, the create method is supposed to throw a DuplicateKeyException. I know it is not a 'must' (I think..) but since the inteface defines it, it gives some indiciation that you should check if the record you are creating does not already exist.

http://www.coderanch.com/t/186531/java-developer-SCJD/certification/Solution-DuplicateKeyException discusses which fields you should use as primary key (pk) and which not. But besides that discussion: from the moment do not allow duplicates (based upon one or more fields) how are you going to prevent that no one updates ?

Scenario (assume record with 3 columns where the first 2 are part of the pk):

1. Thread A wants to create record with values: a,b,c
2. in the create() method we do a read to see if the record does not exist
3. The only record currently in the db is : t,b,c . So, the pk fields are different thus the record can be added.
3. In the mean time thread B updates record (t,b,c) to: a,b,d
4. Thread A creates the record: a,b,c

Result; we have 2 records in the db with same primary key (a,b)

So, to overcome this, I could syncrhonize the create() update() and delete() method of my database facade. But is this any good ? How do you guys solve this ? I feel some trouble:

1. Synchronization on the update() create() delete() method of the database facade
2. Syncrhonized locking system for the update() and deletes()
3. Synchronization on the lowest read/write method

The fact that I have 1) seems to make 2) totally useless. Because, the queue will never be used since the main methods are synchronized. You will never ever have 2 updates (or an update and delete) at the same time and there for do not actually use the queue. So I could just delete the queue system and place synchronized on my main entry methods (create,delete,update) this cannot be good ??

To sumarize my question:

If you do not allow duplicate records based upon one or more fields, you must lock the entire database between that 'duplicate record check' and the actual writing of the record. Is this assumption correct ?

If so, how can you manage that ? The only proper way I can think of is to synchronize the create() delete() and update() method. But, by doing this you make the entire lockcookie based locking superfluous. It will never be used because of the synchronization.

On the other hand, you could put the 'duplicate record check' in the lowest write method (that writes directly to the file) which is located in the Data class or some helper class used by Data. Since it is allready synchronized everything would be fine. However, this means that you must tell that class something about the business logic, you must tell it which field(s) to compare for duplicate key checking. There is no way you can pass additional information to it (you could pass the field numbers which act as pk), because the DB interface only has one parameter for create : String[] values

---------------------------------------Edit:---------------------------------

The only way to guarantee that no duplicate records will exist in my implementation is to delegate an array (which contains the field numbers that acts as primary key) of int's to the writeToDatabaseFile() method. This method will then read the database first to check if no duplicate exist. If not, it will write the record (comming from a creat or update operation). Because it is atomic, other write's (comming from updates in the queue or new create's) will do this check again and notice when there are duplicates.

Since the DB interface does not allow such array of primary keys to be passed to the implementation, I cannot do this check in the write method, but it should be done *before* the create/update method in Data (which implements DB) is called. But then we endup by synchronizing the update(),delete() and create() method of my database facade class (which uses Data) and this I don't want.

So ! For this reason I'm going to cancel the use of primary keys. You can create as much duplicates as you want using create() , the DuplicateKeyException is not thrown. As for the update, the same thing, no check is done for duplication (update does not even throw that exception).

In my choices.txt I'm going to write that there is currently no need for a primary key (well, besides the record number then ofcourse) because of the grouping of contractors:

Contractor X, amsterdam, painting, 8, 14, null
Contractor X, amsterdam, painting, 8, 14, null

In this example contractor X has 16 people all specialized in painting. However, the system does not allow to assign the number of workers. If you book a contractor you have all the workers. By dividing them over 2 or more records you have logical blocks of contractors. So, you could assign the first 8 to some client and if he really needs 16 workers, you assign them both. Otherwise you can assign the other 8 later to another client. So actually there is a valid explanation if you do allow duplication.

I will also write that If there is ever need for a primary key, the check should be implemented in the write() method.

How does this sounds to you guys ?
[ December 11, 2004: Message edited by: Koen Serneels ]
Andrew Monkhouse
author and jackaroo
Marshal Commander

Joined: Mar 28, 2003
Posts: 11462
    
  94

Hi Koen,

In my choices.txt I'm going to write that there is currently no need for a primary key (well, besides the record number then ofcourse) because of the grouping of contractors:

<cut>

I will also write that If there is ever need for a primary key, the check should be implemented in the write() method.


That's the way I would go.

Just a quick comment on an earlier issue though:

On the other hand, you could put the 'duplicate record check' in the lowest write method (that writes directly to the file) which is located in the Data class or some helper class used by Data. Since it is allready synchronized everything would be fine. However, this means that you must tell that class something about the business logic, you must tell it which field(s) to compare for duplicate key checking.


Data integrity is not normally considered business logic. It is quite normal when defining a database to specify which fields in the table are primary keys, and which are foreign keys. The database itself will check integrity.

So, if there was a clearly defined primary key for our assignments, I would not have a problem with storing all the primary keys in a Set within the Data class, and throwing the DuplicateRecordException if Set.contains(...) returns true.

Regards, Andrew


The Sun Certified Java Developer Exam with J2SE 5: paper version from Amazon, PDF from Apress, Online reference: Books 24x7 Personal blog
Jim Janssens
Ranch Hand

Joined: Sep 24, 2004
Posts: 210
Yeah Andrew, that is exactly my point. But I explained it a bit wrong I guess:

The implementation should be unaware of the pk fields. However, it need to know which field are primary key to perform the check. As I explained I must do this checks in the lowest layer. If I do them somewhere else I need to intensivly use synchronized to lock the whole database which would take a hit on the performance (well theoretically) because it also affects updates and deletes. Last but not least it will also make the locking system superfluous.

One solution to have both: passing the pk's and still having it business unawere, is to let the facade pass an array containing the pk's specific to Contractors. When you later invent another file "Employees" for example, you put the pk's of Employees in you business facade. The database implementation is then used as before, it just gets a array passed with the values and an array with the pk's. Only this time the array with pk's has other values then if we are creating contractors.

But, there is no such flexibility in the DB interface. You can only pass one array of Strings to the create method which are the values you want to create in a new record.

So, the only way to implement it, is to make the database classes business aware (to hard code the primary keys in there) . But this would go against every logic and will not make your database easy reuseable.

If you are respecting a layered design and you want to keep your database code reuseable, you cannot implement dynamic primary keys. Unless you want to violate the assignment constraints, put extra synchronization, or do some heavy overloading on the String array (you could for example pass the pk's in string format after the values...) but that is a bit dirty also.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Create method [B&S]