Sorry to be a party-pooper, but the database issue I keep referring to was
new code. The database was IBM's DB2 and I was using Hibernate JPA2 as the access mechanism. It's entirely possible - since multiple major versions of both have been released since then - that the constraints I was operating under at the time no longer apply, but one has to make due with what's available. It obviously wasn't a choice, since I had to go to the trouble to test for the pre-existence of my internally generated sequence and repeat until I found a viable slot, and normally an auto-generated sequence number would be less coding and much less overhead for both client and server.
A database doesn't "maintain" insertion order (well, outside primitive exceptions like MS-Access and FoxPro), but there's a reason why sequences are so popular that they frequently have built-in DBMS support these days. Accounting systems like them for generating invoice and order numbers, for example. Retrieving a list of unpaid invoices in sequence number order, for example, means that you can have the fastest access to the list in a manner that is most convenient to the accounting process - since First-In/First-Out is one of the most popular ways to manage things. Ordering by date is inferior because multiple invoices or orders are very frequently created on the same date, and timestamps in databases are particularly warty. Plus if you expect people to be able to sort through invoices based on microsecond-level timestamps, you haven't seen how few brain cells most people are willing to devote to such processes. A nice simple number with, say 5 digits, is a lot easier to dig through when you have a stack of papers in hand. Not only accounting systems do this. My nightly backup system numbers each backup job that runs, for example.
Regarding slicing, it's been my experience that database deletions are more the exception than the rule. For various reasons - including audit purposes - most of the production systems I've worked with did not allow deletions. Often the only part of a system that did
allow deletions was a staging area used, for example, to assemble transactions before they were either committed or rolled back (either of which caused the staging data to be deleted). So holes in the sequence are not an issue in general. On the other hand, if you have a sequence and use it for slicing, you can potentially free up entire disk drives by archiving to tape periodically. This is something more often seen in major IT shops, but then, they're the ones who employ more skilled DBA's and generally are using more sophisticated techniques for everything.
As I've said, GUIDs have a very definite set of uses. But they're not my identifier of choice because they have no semantic meaning. Their sole property is their uniqueness. If there are other properties in a table (including compound properties), that can be used to enforce uniqueness, then I prefer those, since such properties have additional and practical reasons for existence. As I said, storage space isn't as critical an issue as it used to be, but why waste it gratuitously? GUIDs take up a lot of space, relative to simple numeric and short-sequence character fields. And may Ganesha help you if you have read them out to someone over the phone. I have enough problems with things like MAC addresses. A touch of dyslexia isn't helping any, either.
Stephan van Hulst wrote:Can you explain what you mean by that POJOs are not supposed to have infrastructure-related property mandates? Does that mean that I can't simply pass a logger(-factory) in a constructor?
Yes, I can. POJO means "Plain Old Java Object". Once you cannot arbitrarily substitute one bean for another, you've locked yourself in. You now have coupling issues and code reuse limitations. That doesn't mean that you cannot
inject complex objects into a POJO, just that it means that you must not require
a class of POJO objects to accept a specific property or properties, since then it's by definition no longer a POJO.
Also, it is an essential requirement in both JavaServer Faces (JSF) and in Java Persistence Architecture (JPA) that every bean must
have a no-element constructor. For JPA, there is no way to define arguments for the constructor that JPA will use to auto-instantiate the bean. For JPA, JPA needs a no-element constructor for when it internally assembles entity objects. Because in many cases, JPA will not be populating those objects from application logic, it will be populating them from database value retrieval and that means that it simply won't have any knowledge of things like which logger you are using. Or what e-mailer, or any of a number of other such services that can be found via a static service locator without direct propagation from the calling framework.
Finally, I should mention that things like loggers, JDBC Connections, etc.
are not serializable. This is critical in JSF and JPA. In fact, Tomcat will flatly refuse to accept a session-scope object that doesn't at least claim to be serializable*. For one thing, when a serializable object is serialized out and back in again, any non-serializable properties do not get initialized, which can break things. A logger retrieved from a static method as part of the internal initializer code doesn't have this problem.
*Yes, I realize that forcing a POJO to to implement java.io.Serializable sounds like a violation of the definition. But it gets a pass since Serializable is a class characteristic, not a promise to implement any sort of logic or specific class or method properties. And because it's a core JVM feature and therefore guaranteed to always be there.