lixj0571
发贴: 84
积分: 2
|
于 2003-03-27 18:36
A simple solution to the primary key generation problem is to use an entity bean that increments an internal counter. Since this primary key generator is an entity bean, it is distributed, transactional, and persistent. Simple!
The entity bean maintains a counter starting from 1, and has a string primary key. Clients can thus create primary key creators using any string and find them again using that same string. The UniqueIDGeneratorBean returns integers, incrementing them by one each time getNextID() is called.
Complete Code for the Primary Key Generator Bean (using EJB 1.0): /** * This Entity Bean generates unique id's for any client that needs one. * * @author Floyd Marinescu */ public class UniqueIDGeneratorBean implements EntityBean {
protected EntityContext ctx;
// Environment properties the bean was deployed with public Properties env;
private String idName; private long nextID;
/** * Create a PK generator. * * @param idName the name for this unique id tracker * @return The primary key (just a string) for this index */ public UniqueIDGeneratorPK ejbCreate( UniqueIDGeneratorPK key ) throws CreateException, RemoteException { this.idName = key.idName; this.nextID = 0;
...
//Build SQL query pstmt = conn.prepareStatement("insert into uniqueIDs (idName, nextID) values (?, ?)"); pstmt.setString( 1, this.idName); pstmt.setLong( 2, this.nextID); //insert row in databse pstmt.executeUpdate();
return key;
... }
public UniqueIDGeneratorPK ejbFindByPrimaryKey(UniqueIDGeneratorPK key) throws FinderException, ObjectNotFoundException, RemoteException { ...
// Find the Entity in the DB pstmt = conn.prepareStatement("select idName from uniqueIDs where idName = ?"); pstmt.setString( 1, key.idName ); rs = pstmt.executeQuery();
// iterate to the first row in the resultset if( ! rs.next() ) //if generator does not exist in database { throw new ObjectNotFoundException("ID Generator " + key + " does not exist in databse" ); }
// No errors occurred, so return the Primary Key return key; ... }
public void ejbLoad() throws RemoteException { // Query the Entity Context to get the current // Primary Key, so we know which instance to load. this.idName = ((UniqueIDGeneratorPK) ctx.getPrimaryKey()).idName;
...
pstmt = conn.prepareStatement("select nextID from uniqueIDs where idName = ?"); pstmt.setString(1, this.idName);
rs = pstmt.executeQuery();
// iterate to the first row in the results rs.next();
// populate with data from database this.nextID = rs.getLong("nextID");
... }
public void ejbRemove() throws RemoteException { // Query the Entity Context to get the current // Primary Key, so we know which instance to load. String pk = ((UniqueIDGeneratorPK)ctx.getPrimaryKey()).idName; ...
pstmt = conn.prepareStatement("delete from uniqueIDs where idName = ?"); pstmt.setString(1, pk);
//Throw a system-level exception if something bad happened. if (pstmt.executeUpdate() == 0) { //log errors here throw new RemoteException("UniqueIdGenerator " + pk + " failed to be removed from the database"); }
... }
public void ejbStore() throws RemoteException { ... // Store account in DB pstmt = conn.prepareStatement("update uniqueIDs set nextID = ? where idName = ?");
pstmt.setLong( 1, this.nextID); pstmt.setString(2, this.idName); pstmt.executeUpdate();
... }
public long generateUniqueId() throws EJBException {
this.nextID++; return this.nextID;
}
The bean is very versatile, and can be used in many different ways. The way I use it is that each entity bean "class" in my application uses a different instance of the UniqueIDGeneratorBean. In the create method of an entity bean class (for example, MessageBean), I would execute:
UniqueIDGeneratorHome.findByPrimaryKey("MessageBean");
Which will return an instance of the UniqueIDGeneratorBean that is maintaing count just for my MessageBean class.
If you want primary keys to be unique across all beans in your application, then simply use one instance of your UniqueIDGenerator across your entire application.
|