How to Change Hibernate Collection Mapping from Set to List - java

I am using eclipse Tools to generate my Annotated Domain Code Classes.
For the One to Many & Many to Many Relationships, the code generated
used Set type for collections.
I want to change it to List or ArrayList. What should be my configuration
in reveng.xml
Also, what are the standard conversion types between MySQL and Java.
I mean like varchar is converted to string, int to int etc.
Can anyone share a pretty much standard reveng.xml file for type conversions...???

You shouldn't use List by default instead of Set. But if you need it punctually, that can help you:
public <T> List<T> fromSetToList(Set<T> set) {
return new ArrayList<T>(set);
}

Also, what are the standard conversion types between MySQL and Java. I mean like varchar is converted to string, int to int etc.
For reference on Hibernate mappings, I found the following link helpful for basic scenarios. For more complex mappings, refer to the full hibernate documentation.
Hibernate Mapping Cheat Sheet
As for The List vs. Set, Set should actually be the Collection type you should use. The only difference between List and Set is that List implies order of the elements and Set does not allow duplicates. A simple DB record set does not have a specified order and it does not have duplicates, so a Set is appropriate. A List would be useful only if your query did specify order and/or you wanted some kind of UNION which may produce duplicates.
I don't know how to turn your Sets into Lists but I would encourage you to question if you actually want to do so.

Related

List vs Set on JPA 2 - Pros / Cons / Convenience

I have tried searching on Stack Overflow and at other websites the pros, cons and conveniences about using Sets vs Lists but I really couldn't find a DEFINITE answer for when to use this or that.
From Hibernate's documentation, they state that non-duplicate records should go into Sets and, from there, you should implement your hashCode() and equals() for every single entity that could be wrapped into a Set. But then it comes to the price of convenience and ease of use as there are some articles that recommend the use of business-keys as every entity's id and, from there, hashCode() and equals() could then be perfectly implemented for every situation regardless of the object's state (managed, detached, etc).
It's all fine, all fine... until I come across on lots of situations where the use of Sets are just not doable, such as Ordering (though Hibernate gives you the idea of SortedSet), convenience of collectionObj.get(index), collectionObj.remove(int location || Object obj), Android's architecture of ListView/ExpandableListView (GroupIds, ChildIds) and on... My point is: Sets are just really bad (imho) to manipulate and make it work 100%.
I am tempted to change every single collection of my project to List as they work very well. The IDs for all my entities are generated through MYSQL's auto-generated sequence (#GeneratedValue(strategy = GenerationType.IDENTITY)).
Is there anyone out the who could in a definite way clear up my mind in all these little details mentioned above?
Also, is it doable to use Eclipse's auto-generated hashCode() and equals() for the ID field for every entity? Will it be effective in every situation?
Thank you very much,
Renato
List versus Set
Duplicates allowed
Lists allow duplicates and Sets do not allow duplicates. For some this will be the main reason for them choosing List or Set.
Multiple Bag's Exception - Multiple Eager fetching in same query
One notable difference in the handling of Hibernate is that you can't fetch two different lists in a single query.
It will throw an exception "cannot fetch multiple bags". But with sets, no such issues.
A list, if there is no index column specified, will just be handled as a bag by Hibernate (no specific ordering).
#OneToMany
#OrderBy("lastname ASC")
public List<Rating> ratings;
One notable difference in the handling of Hibernate is that you can't fetch two different lists in a single query. For example, if you have a Person entity having a list of contacts and a list of addresses, you won't be able to use a single query to load persons with all their contacts and all their addresses. The solution in this case is to make two queries (which avoids the cartesian product), or to use a Set instead of a List for at least one of the collections.
It's often hard to use Sets with Hibernate when you have to define equals and hashCode on the entities and don't have an immutable functional key in the entity.
furthermore i suggest you this link.

Converting an Integer[] to List<integer> automatically in JOOQ

I'm using PostgreSQL. One of my table fields is an array:
"day_of_month" int[] DEFAULT NULL
But my domain object for this table is List<Integer>. I want to annotate my domain object with #Column(name = "day_of_month") so I can use fetchOneInto(MyDomainType.class). The problem is JOOQ converts int[] field as Integer[] so I have to fetch result, convert Integer[] to List<Integer> and fill my domain object manually. Is there any automatic way to do this?
Unfortunately, the type rewriting system of jOOQ-codegen is not very sophisticated, meaning that "special" data types like arrays or user-defined types are a bit hard to rewrite.
There is a pending feature request #3310 to rectify this, but it won't be before jOOQ 3.5. In the mean time, I'm afraid that you:
Either convert these types yourself:
Post-process the generated jOOQ meta data to patch such Field definitions
Apply Taeir's solution and implement a RecordMapperProvider. This will not modify the array values in jOOQ records, but at least you will be able to map arrays to List when mapping to your MyDomainType.
Update: As a matter of fact, I suspect that #3062 might sufficiently cover your use-case. Maybe, we give this a higher priority for jOOQ 3.4
I'm not sure what you mean with "Automatic", but you can convert an Integer Array into a List of Integers with List<Integer> list = Arrays.asList(array);, where array is your Integer array.
The other way is also possible: Integer[] array = list.toArray(new Integer[0]);.
EDIT:
It might be possible to have JOOQ do this for you. I haven't worked with it myself, but by looking at the documentation, it seems that it is possible to add a RecordMapper to a RecordMapperProvider. With one of these mappers, you can define how certain db types should be converted to java types (I think at least). This is, however, probably a lot more work than just having a small call to Arrays.asList().

Best practice design pattern for defining "types" in a database with potential multi language requirement?

My question more specificity is this:
I want users on multiple front ends to see the "Type" of a database row. Let's say for ease that I have a person table and the types can be Student, Teacher, Parent etc.
The specific program would be java with hibernate, however I doubt that's important for the question, but let's say my data is modelled in to Entity beans and a Person "type" field is an enum that contains my 3 options, ideally I want my Person object to have a getType() method that my front end can use to display the type, and also I need a way for my front end to know the potential types.
With the enum method I have this functionality but what I don't have is the ability to easily add new types without re-compiling.
So next thought is that I put my types in to a config file and simply story them in the database as strings. my getType() method works, but now my front end has to load a config file to get the potential types AND now there's nothing to keep them in sync, I could remove a type from my config file and the type in the database would point to nothing. I don't like this either.
Final thought is that I create a PersonTypes database table, this table has a number for type_id and a string defining the type. This is OK, and if the foreign key is set up I can't delete types that I'm using, my front end will need to get sight of potential types, I guess the best way is to provide a service that will use the hibernate layer to do this.
The problem with this method is that my types are all in English in the database, and I want my application to support multiple languages (eventually) so I need some sort of properties file to store the labels for the types. so do I have a PersonType table the purely contains integers and then a properties file that describes the label per integer? That seems backwards?
Is there a common design pattern to achieve this kind of behaviour? Or can anyone suggest a good way to do this?
Regards,
Glen x
I would go with the last approach that you have described. Having the type information in separate table should be good enought and it will let you use all the benefits of SQL for managing additional constraints (types will be probably Unique and foreign keys checks will assure you that you won't introduce any misbehaviour while you delete some records).
When each type will have i18n value defined in property files, then you are safe. If the type is removed - this value will not be used. If you want, you can change properties files as runtime.
The last approach I can think of would be to store i18n strings along with type information in PersonType. This is acceptable for small amount of languages, altough might be concidered an antipattern. But it would allow you having such method:
public String getName(PersonType type, Locale loc) {
if (loc.equals(Locale.EN)) {
return type.getEnglishName();
} else if (loc.equals(Locale.DE)){
return type.getGermanName();
} else {
return type.getDefaultName();
}
}
Internationalizing dynamic values is always difficult. Your last method for storing the types is the right one.
If you want to be able to i18n them, you can use resource bundles as properties files in your app. This forces you to modify the properties files and redeploy and restart the app each time a new type is added. You can also fall back to the English string stored in database if the type is not found in the resource bundle.
Or you can implement a custom ResourceBundle class that fetches its keys and values from the database directly, and have an additional PersonTypeI18n table which contains the translations for all the locales you want to support.
You can use following practices:
Use singleton design pattern
Use cashing framework such as EhCashe for cashe type of person and reload when need.

How to map standard Java types to SQL types?

I want to write a program, which creates RDBMS-tables through JDBC automatically. To add columns to a table, I need to know the name of the column and the column's RDBMS datatype. I already have the names of the columns. I don't have the RDBMS types for the columns, but I have Java types for those column. So I need to map those Java types to RDBMS datatypes. The Java type can be one of the following:
primitve types
wrapper types of primitive types
String
So my question is: How to map those java types to RDBMS types?
Is there a part of JDBC or library that already handles this mapping?
Are there any classes which can help me partially?
Especially I am working with PostgreSQL. So if there is no genenic way to do it, it would be important for the moment to get it running with PG.
Thanks in advance
Well, there there's always the java.sql.Types class which contains the generic SQL type mappings, but you'd be better served using something like Hibernate to do all of this for you.
getTypeInfo() is intended to get the driver's view on which (native) DBMS type should be mapped to which JDBC type. But these mappings aren't always precise so you will need to find some way of detecting the "best match"
Sun/Oracle's JDBC Guide proposes some mappings:
Mapping SQL and Java Types
I don't think there is any generic way to do it. The devil is in the details : do you want to impose any precision or scale? What's the maximum number of chars in your strings?
The mapping, in its simplest form could be
Java char --> varchar(1)
Java String --> varchar
Java number --> numeric
Java boolean --> boolean

Persisting data suited for enums

Most projects have some sort of data that are essentially static between releases and well-suited for use as an enum, like statuses, transaction types, error codes, etc. For example's sake, I'll just use a common status enum:
public enum Status {
ACTIVE(10, "Active");
EXPIRED(11, "Expired");
/* other statuses... */
/* constructors, getters, etc. */
}
I'd like to know what others do in terms of persistence regarding data like these. I see a few options, each of which have some obvious advantages and disadvantages:
Persist the possible statuses in a status table and keep all of the possible status domain objects cached for use throughout the application
Only use an enum and don't persist the list of available statuses, creating a data consistency holy war between me and my DBA
Persist the statuses and maintain an enum in the code, but don't tie them together, creating duplicated data
My preference is the second option, although my DBA claims that our end users might want to access the raw data to generate reports, and not persisting the statuses would lead to an incomplete data model (counter-argument: this could be solved with documentation).
Is there a convention that most people use here? What are peoples' experiences with each and are there other alternatives?
Edit:
After thinking about it for a while, my real persistence struggle comes with handling the id values that are tied to the statuses in the database. These values would be inserted as default data when installing the application. At this point they'd have ids that are usable as foreign keys in other tables. I feel like my code needs to know about these ids so that I can easily retrieve the status objects and assign them to other objects. What do I do about this? I could add another field, like "code", to look stuff up by, or just look up statuses by name, which is icky.
We store enum values using some explicit string or character value in the database. Then to go from database value back to enum we write a static method on the enum class to iterate and find the right one.
If you expect a lot of enum values, you could create a static mapping HashMap<String,MyEnum> to translate quickly.
Don't store the actual enum name (i.e. "ACTIVE" in your example) because that's easily refactored by developers.
I'm using a blend of the three approaches you have documented...
Use the database as the authoritative source for the Enum values. Store the values in a 'code' table of some sort. Each time you build, generate a class file for the Enum to be included in your project.
This way, if the enum changes value in the database, your code will be properly invalidated and you will receive appropriate compile errors from your Continuous Integration server. You have a strongly typed binding to your enumerated values in the database, and you don't have to worry about manually syncing the values between code and the data.
Joshua Bloch gives an excellent explanation of enums and how to use them in his book "Effective Java, Second Edition" (p.147)
There you can find all sorts of tricks how to define your enums, persist them and how to quickly map them between the database and your code (p.154).
During a talk at the Jazoon 2007, Bloch gave the following reasons to use an extra attribute to map enums to DB fields and back: An enum is a constant but code isn't. To make sure that a developer editing the source can't accidentally break the DB mapping by reordering the enums or renaming then, you should add a specific attribute (like "dbName") to the enum and use that to map it.
Enums have an intrinsic id (which is used in the switch() statement) but this id changes when you change the order of elements (for example by sorting them or by adding elements in the middle).
So the best solution is to add a toDB() and fromDB() method and an additional field. I suggest to use short, readable strings for this new field, so you can decode a database dump without having to look up the enums.
While I am not familiar with the idea of "attributes" in Java (and I don't know what language you're using), I've generally used the idea of a code table (or domain specific tables) and I've attributed my enum values with more specific data, such as human readable strings (for instance, if my enum value is NewStudent, I would attribute it with "New Student" as a display value). I then use Reflection to examine the data in the database and insert or update records in order to bring them in line with my code, using the actual enum value as the key ID.
What I used in several occations is to define the enum in the code and a storage representation in the persistence layer (DB, file, etc.) and then have conversion methods to map them to each other. These conversion methods need only be used when reading from or writing to the persistent store and the application can use the type safe enums everywhere. In the conversion methods I used switch statements to do the mapping. This allows also to throw an exception if a new or unknown state is to be converted (usually because either the app or the data is newer than the other and new or additional states had been declared).
If there's at least a minor chance that list of values will need to be updated than it's 1. Otherwise, it's 3.
Well we don't have a DBA to answer to, so our preference is for option 2).
We simply save the Enum value into the database, and when we are loading data out of the database and into our Domain Objects, we just cast the integer value to the enum type.
This avoids any of the synchronisation headaches with options 1) and 3). The list is defined once - in the code.
However, we have a policy that nobody else accesses the database directly; they must come through our web services to access any data. So this is why it works well for us.
In your database, the primary key of this "domain" table does't have to be a number. Just use a varchar pk and a description column (for the purposes your dba is concerned). If you need to guarantee the ordering of your values without relying on the alphabetical sor, just add a numeric column named "order or "sequence".
In your code, create a static class with constants whose name (camel-cased or not) maps to the description and value maps to the pk. If you need more than this, create a class with the necessary structure and comparison operators and use instances of it as the value of the constants.
If you do this too much, build a script to generate the instatiation / declaration code.

Categories