Butterfly Persistence Auto Object Mapping
The easiest way to create object mappings in Butterfly Persistence is to use automatic mapping. Automatic mapping can take care of most trivial object relational mappings, thus freeing your precious development time for other tasks, such as walks to and from the coffee machine, surfing the internet, looking out the window etc.
Object Mappings and Object Mapping Keys
Automatic mapping is performed by the ObjectMapper. You don't have to interact with the ObjectMapper to create automatic mappings. Whenever you use any of the read, insert, update or delete methods of the IObjectDao, you provide an object mapping key, telling what type of object to read, insert, update or delete. For example:
dao.readByPrimaryKey(Employee.class, new Long(23));
In this example the
Employee.class object is the object mapping key.
The object mapping key points to the object mapping to use for the read or write action. The object mappings are kept internally in a cache, in the corresponding IPersistenceConfiguration instance. If no object mapping is found in the cache by the given object mapping key, Butterfly Persistence will attempt to generate a new object mapping and cache it for later use.
In principle an object mapping key can be any object you desire. However, if you want Butterfly Persistence to be able to auto-map the target class to the database, the object mapping key should be either a Class object, or an IObjectMappingKey instance. The IObjectMappingKey instance can contain more information about the class to be mapped, than a Class object can. The IObjectMappingKey instance can also be used to do programmatic or mixed object mapping, as described in the text "Programmatic Mapping".
No matter whether you use a Class object or an IObjectMappingKey instance, a Class object is needed for Butterfly Persistence to do automatic object mapping. An IObjectMappingKey instance has a getObjectClass() method that returns the Class object of the class to map, so automatic mapping is possible in either case.
Name Guessing Based on Name Similarity
Once Butterfly Persistence has obtained a Class object, it will try to map it to the database. Mapping a Class object to the database is done in three steps:
- Guessing the Table Name
- Guessing the Column Names
- Determining the Primary Key
Table and column names are guessed based on name similarity. The name similarity rules are based on common Java and database naming conventions.
Table Name Guessing
When checking for tables with similar names to the class to map only the class name itself is used.
The package part of the class name is cut off. For instance, for the class
com.jenkov.db.test.object.PersistentObject only the PersistentObject part is used.
The ObjectMapper generates various textual combinations based on the class name and checks the database meta data to see if any of these match. The ObjectMapper mapper breaks the class name into words, based on the uppercase letters and numbers in the class name. Then it tries to look for table names that contains these words, in the following combinations:
- Java Class Naming Convention (exact case)
- Java Variable Naming Convention
- All of the above, with the words underscore delimited. Based on the database naming convention
to separate words with underscore.
(Persistent_Object, persistent_Object, persistent_object, PERSISTENT_OBJECT)
- All of the above, with a plural s appended. Uppercase names have the
s added in both uppercase and lowercase. Based on the database naming convention to name tables
(Persistent_Objects, persistent_Objects, persistent_objects, PERSISTENT_OBJECTS, PERSISTENT_OBJECTs)
Based on these combinations the PersistentObject class name would
be similar to the table names
As you can see there is a reasonable chance that the table name will be guessed if it is similar to the class name.
Column Name Guessing
Guessing column names is done the ways way as guessing table names, except no plural combinations of the column name is generated. The Object Mapper uses reflection to iterate the methods of the class to be mapped, and filters out all other methods than getters and setters. Getters and setters are recognized like this:
- Getter: Starts with “get”, takes no parameters and returns a value.
- Setter: Starts with “set”, and takes one parameter.
Thus, the getter method name "getEmployeeId" will be similar to the column names:
Note, that some databases might return the names of the tables and column via the JDBC database meta data in a different case than you defined it in, in your database script. For instance, HSQLDB returns all table and column names in uppercase regardless of the case you defined them in, when you created the tables. Thus, the method “setEmployeeId” will not be mapped to the column employee_id, even though that is what you called it when you created the table, but to EMPLOYEE_ID. This is relevant to know if you need to modify the object mappings later on. When reading and writing objects this shouldn't have any noticable effect on your code.