Basically, I want a way to access sequence values in a database-neutral way.
The use case is that I have a field on an entity that I want to set based on an incrementing value (other than the id).
For instance, say I have a Shipment entity. At some point after the shipment gets created, it gets shipped. Once it gets shipped, a manifest number is generated for it and assigned. The manifest number looks something like M000009 (Where the stuff after the 'M' is a left-padded value from a sequence).
Something similar was asked here at SO , but I'm not a fan of the solution since it requires another table to maintain and seems like a weird relationship to have.
Does anyone know if it is possible to use something like hibernate's MultipleHiLoPerTableGenerator as something other than an ID generator?
If that's not possible, does anyone know of any libraries that handle this (either using hibernate or even just pure JDBC). I'd prefer not to have to write this myself (and have to deal with prefetching values, locking and synchronization).
Thanks.
I think the complexity of your task depends on whether or not you manifest number needs to be sequential:
If you don't need sequential manifest numbers then it's happy days and can use a sequence.
If you do need sequential manifest numbers (or your database doesn't support sequences) then use an id table with the appropriate locking so that each transaction gets a unique sequential value.
Then you've got 2 options that I can think of:
write the necessary JDBC code on your client, ensuring (if the manifest number is sequential) that the transaction being used is the same as that for the database update.
use a trigger to create the manifest number when the appropriate update occurs.
I think my preference would be the trigger because the transaction side of things would be taken care of although it would mean the object would need refreshing on the client.
I didn't read over the linked similar solution, but sounds like something I wound up doing. I created a table just for sequences. I added a row to the table for each sequence type I needed.
I then had a sequence generator class that would do the necessary sql query to fetch and update the sequence value for a particular named sequence.
I used hibernate's Dialect class to do it in a db neutral way.
I also would 'cache' the sequences. I would bump the stored sequence value by a large number, and then dole those out those allocated sequences from my generator class. If the class was destroyed (ie. app shutdown), a new instance of the sequence generator would start up at the stored value. (having a gap in my sequence numbers did not matter)
Here is a code samnple. I would like to caveat this with - I have not comiled this and it reuires spring code. Having said this it should still provide the bones of what you want to do.
public Long getManifestNumber() {
final Object result = getHibernateTemplate().execute(new HibernateCallback() {
public Object doInHibernate(Session sess) throws HibernateException, SQLException {
SQLQuery sqlQuery = sess.createSQLQuery("select MY_SEQUENCE.NEXTVAL from dual");
sqlQuery.uniqueResult();
}
});
Long toReturn;
if (result instanceof BigDecimal) {
toReturn = ((BigDecimal)result).longValue();
}
return toReturn;
}
Related
I'm getting the "No data type for node" error when I run this query:
session.createQuery("select nextval( 'next_num_seq' )")
which I know means that I need to make it a property of a class, but I haven't been able to find a way to add a sequence to a class, only how to make a sequence generate IDs for a class.
Is there a way to include a sequence in a Hibernate mapping that isn't an ID generator?
As such, this question is valid, yet the path to the solution is headed in the wrong direction. Mapping a Sequence into a managed domain entity is not a "good" idea, as these are two separate concepts.
Sequences, such as the one you are trying to query from a PostgreSQL backend, are a central concept for the generation of unique IDs for primary key values of tuples or - from an ORM application perspective - Java objects. Thus, it is not clever to map their current state to a domain entity. Instead, one sets a single, particular value drawn from such a sequence - e.g. next_num_seq - into one particular object to be persisted in a relational database. Therefore, the related class of such an domain object is linked to this sequence by, for instance, dedicated ORM annotations (or via similar approaches).
In the JavaDoc of the Session interface we find the method createNativeQuery(String sql) which is inherited from the EntityManager interface, see also here.
It is described as follows:
Query createNativeQuery(java.lang.String sqlString)
Create an instance of Query for executing a native SQL statement, e.g., for update or delete.
Parameters:
sqlString - a native SQL query string
Returns:
the new query instance
Thus, you could modify your code to execute the native query against your PostgreSQL database as follows:
Query q = session.createNativeQuery("select nextval( 'next_num_seq' )");
This gives you the option to read the next valid sequence value as a long or Number instance for your programming purposes.
Note well: Be careful not to reuse this value multiple times (for several objects), as this might cause consistency trouble in your backend when used, for instance, in the context of separate threads.
Hope this helps.
For possibly no other good reason at this point in time other that 'we've always done it like this', how are new systems being architected to use reference data used to represent state codes?
For example, a Case may have 2 valid states, 'Open' or 'Closed'. Historically I've seen many systems where these valid values would be stored in a database table containing this reference data, and referred to as a code type ('CaseStatus'), and each valid value has a 'code' value (eg 'OPN') and a decode or display value that is used when the value is needed to be displayed to a user (in this case 'Open').
If developing a Java based system today, from a code point of view with type safety, we would define an Enum like this:
public enum CaseStatus{
Open("OPN"),
Closed("CLS");
private String codeValue;
private CaseStatus(String codeValue){
this.codeValue = codeValue;
}
}
This is great solely from the view of the source code, the Enum enforces type-safety with a restricted list of valid values, but by itself there is no representation of this code type or it's valid values in the database. If there are users of the data who run adhoc reports directly against the database, they need a way to look up decoded values for 'OPN', 'CLS'. Historically this would have been done using a reference table containing the codetype, the codes and their decode values.
It seems odd that we continue to use these state code values as '3 letter codes', where the motivation at this point is no longer because we need to save space in the database ('OPN' vs 'Open' is hardly a great optimization anyway).
What other approaches have people used or seen on recent systems they have worked on? Do you maintain the reference data only in the database, only in code, or in both places, and if you maintain it in both, what approaches do you use to keep the two in sync?
First, if there are only two possible values, and it is not possible to expect them to develop into a larger number (as in your example of open/closed), I would probably define a status_open column as BOOLEAN or SMALLINT (0/1) or CHAR (Y/N).
When the universe of status is bigger (or may increase to more than two values), I would use a surrogate key. While saving a few bytes is hardly an optimization, indexing and joining CHAR valued columns is more expensive than indexing and joining INTEGER columns. While I don't have a metric on the issue of INTEGER vs CHAR(3), I would suppose that for this case the difference would not be as big as in the case of INTEGER vs CHAR(50).
However, an disadventage that I find in small CHAR abbreviations is that sometimes it is difficult to find meaningful values. Suppose that you have an status of "broken - replacement has been ordered", does it help if I call it "BRO"? Is it better than calling it 3?
On the other hand, even when it is not required by the model, I found convenient adding a short VARCHAR column on status, for describing what each mnemonic or surrogate key means. (After the model grows, it becomes quite difficult to remember all of them!)
My implementation (with due exceptions in particular cases) would likely be:
On the Java side, the enum, as you defined it. (Even for boolean-like values, sometimes it helps having different enums for each value, particularly if there are methods taking several of those values as parameter. Methods with a long list of parameters of the same type are a recipe for disaster).
On the SQL side:
CREATE TABLE status (
id INTEGER PRIMARY KEY,
description VARCHAR(40)
)
CREATE TABLE entity (
...
status_id INTEGER REFERENCES status(id)
)
INSERT INTO status VALUES (0,'Closed');
INSERT INTO status VALUES (1,'Open');
INSERT INTO status VALUES (2,'Broken - replacement has been ordered');
One solution I've encountered is to use a materialized view in the database to dynamically recalculate the denormalized relation. In a document based database you would probably store the CaseStatus as a String. Finally, you might use an ORM tool to store CaseStatus as an Object but in the cases I'm familiar with the reference data is stored in the database (if you store it in code then it requires a build and deployment to production, along with additional testing for the release).
Suppose we have an entity "Something" and this something has one to many (factor of millions) relationship to some "Data".
Something 1 -> * Data
Data 1 -> 1 Something
Now if we want to add some data objects we should do this:
Something.getDataList().add(Data)
This will actually pull all data objects from database which is not optimal imho.
However if i remove relationship from Something, and leave it in Data I'll be able to add and retrieve exactly those objects that I ask for using DAO:
Something
Data 1 -> 1 Something
Now the data access interface will look like this:
Something.addData(Data) // will use DataDAO to save object
or
Something.addData(List<Data>) // will use same DataDAO batch insert
I need some guidance on this, maybe I lack some knowledge in JPA, and there is no need for this? Also I'm not sure as entities are not natural this way as data is provided by their methods but its not actually contained in entity, (if this is right then I should remove every one to many relationship if there is a performance critical operation dealing with that particular entity, which is also unnatural).
In my particular case I have lot of REST consumers that periodically gonna update database. I'm using ObjectDB, JPA... But question is more abstract here.
I believe that having the something.getDataList() around is a clicking bomb if there are milions of Data records related to Something. Just as you said, calling something.getDataList().add(data) would fetch the whole data set from DB in order to perform a single insert. Also, anyone could be tempted to use something.getDataList().size to get the number of records, resulting in the same overhead.
My suggestion is that you use the DataDAO for such operations (i.e. adding or counting) like:
void addData(Something something, Data data){
//Something similar can be used for batch insert
data.setSomething(something);
em.persist(data);
}
List<Data> findData(Something something, MyFilter filter){
// use a NamedQuery with parameters populated by something and your filters
return em.getResultList();
}
Long countData(Something something){
// use a 'SELECT COUNT(*) FROM Data d WHERE d.something = :something' NamedQuery
return em.getSingleResult;
}
I'm working on a desktop application in Java6 using H2 as the db and Hibernate 3.6.
Because of a construct with a third-party library involving JNI and some interesting decisions made a priori, I am unable to pass around long identifiers in their index code, and can only pass int. These indexes are generated quickly and repeatedly(not my choice), and get handed around via callbacks. However, I can split my expected dataset along the lines of a string value, and keep my id size at int without blowing out my id's. To this end, I'm keeping a long value as pk on the core object, and then using that as a one-to-one into another table, where it maps the int id back to the core entity, which when combined with the string, is unique.
So I've considered embedded compound keys and such in hibernate, but what I REALLY want is to just have this "extra" id that is unique within the context of the extra string key, but not necessarily universally unique.
So something like(not adding extraneous code/annotations):
#Entity
public class Foo{
...
#Id
public Long getId(){...}
...
#OneToOne
#PrimaryKeyJoinColumn
public ExtraKey getExtra(){...}
}
#Entity
public class ExtraKey{
...
#Id
public Long getFooId(){...}
...
public Integer getExtraId(){...}
...
public String getMagicString(){...}
}
In that case, I could really even remove the magicString, and just have the fooId -> extraId mapping in the table, and then have the extraId + magicString be in another where magicString is unique. However, I want hibernate to allow the creation of new magicString's at whim(app requirement), ideally one per row in a table, and then have hibernate just update the extraId associated to that magicString via incrementation/other strategy.
Perusing all of the hibernate manuals and trying a few tests on my own in a separate environment has not quite yielded what I want(dynamically created named and sequential id's basically), so I was hoping for SO's input. It's entirely possible I'll have to hand-code all of it myself in the db with sequences or splitting a long and doing logic on the upper and lower, but I'd really rather not, as I might have to maintain this code someday(really likely).
Edit/Addendum
As a sneaky way of getting around this, I'm just adding the extraId to the Foo object(ditching the extraKey class), and generating it from another object singleton, that at load time, does a group by select over the backing Foo table, returning magicKey, and the max(extraId). When I create a new Foo, I ask that object(multithread safe) to hand me the next extraId for the given magicKey and push that into Foo, and store it, thus updating my effective extraId for each magicKey on next app reload without an extra table. It costs me one group by query on the first request for a new extraId, which is suboptimal, but it's fast enough for what I need, simple enough to maintain in the future, and all contained in an external class, so I COULD replace it in one place if I ever come up with something more clever. I do dislike having the extra "special query" in my dao for this purpose, but it's easy enough to remove in the future, and well-documented.
Maybe I still didn't understand your problem properly, but I think you can consider using Hibernate's hilo algorithm. It will generate unique identifier for the whole database, based on a table that Hibernate creates and manages. More details here:
http://docs.jboss.org/hibernate/core/3.5/reference/en/html/mapping.html#mapping-declaration-id
This is a problem about historical data handling.
Suppose you have a class MyClass like the following one:
class MyClass {
String field1;
Integer field2;
Long field3;
getField1() {...}
setField1(String ...) {...}
...
}
Now, suppose I need to make MyClass able to store and retrieve old data, what's the best way to do this?
The requirements are to persist the classes through Hibernate, too. And to have at most two tables per "entity": only one table or one table for the "continuity" class (the one which represents the entity which evolves over the time) and another table for the historical data (as it's suggested here)
Please note that I have to be able to assign an arbitrary valid time to the values of the fields.
The class should have an interface like:
class MyClass {
// how to store the fields????
getField1At(Instant i) {...}
setField1At(Instant i, String ...) {...}
...
}
I'm currently using the JTemporal library, and it has a TemporalAttribute<T> class, which is like a map: you can do things like T myAttr.get(Instant i) to get the version of myAttr at Instant i. I know how to persist a TemporalAttribute in a table with Hibernate (it's simple: I persist the SortedMap used by the TemporalAttribute and you get a table with start and end valid time and the value of the attribute).
The real problem is that here we have multiple attributes.
I have a solution in mind but it's not clear, and I'd like to hear your ideas.
Your project reminds me of Hibernate Envers.
The Envers project aims to enable easy
auditing of persistent classes. All
that you have to do is annotate your
persistent class or some of its
properties, that you want to audit,
with #Audited. For each audited
entity, a table will be created, which
will hold the history of changes made
to the entity. You can then retrieve
and query historical data without much
effort.
choose what you want to audit (on a per attribute basis)
make your own Revision Entity (that stores informations such as revision number, author, timestamp...)
Using Hibernate Envers for this decouples entities and revision data (in database and in your code).
You can do something like this simply by adding a version number to your domain class. I did something like this where the Id was a composite between an db assigned number and the version number, but I would advise against that. Use a normal surrogate key, and if you really want, make the [id, version] tuple a natural key.
You can actually version entire object graphs that way, just by ensuring that the version number is the same for all elements on the graph. You can then easily go back to any previous version.
You should write a lot of service tests to insure the integrity of the code that manages the version.