Ask a question
Saturday, 12 September 2009 14:23
Agile - Using Hibernate
-
font size
decrease font size
increase font size
An Overview of Object-Relational Mapping (ORM)
It is no secret that relational databases are the most common type of databases in a majority of organizations today when compared to other formats (for example, object-oriented, hierarchical, network). Product names such as Oracle,
Microsoft SQL Server, MySQL, IBM DB2, and Sybase are common terms used by developers in our line of work.
On the computer languages side of things, object-oriented (OO) programming has become the norm. Languages such as Java, C#, C++, and even OO scripting languages are common discussion topics among developers.
A majority of the software applications that use relational database and OO languages end up writing code to map the relational model to the OO model. This can involve anywhere from cumbersome mapping code
(because of the use of embedded SQL or stored procedure calls) to heavy-handed technology, such as EJB's entity beans.
(because of the use of embedded SQL or stored procedure calls) to heavy-handed technology, such as EJB's entity beans.
Because most of us seem to like both relational databases and OO, Object-Relational Mapping (ORM) has become a natural choice for working with POJOs (plain old Java objects), especially if you don't need the distributed a
nd secure execution of EJB's entity beans (which also map object attributes to relational database fields).
nd secure execution of EJB's entity beans (which also map object attributes to relational database fields).
Although you still need to map the relational model to the OO model, the mapping is typically done outside of the programming language, such as in XML files. Also, once this mapping is done for a given class, you can use instances
of this class throughout your applications as POJOs. For example, you can use a save method for a given object and the underlying ORM framework will persist the data for you instead of you having to write tedious INSERT or UPDATE statements using JDBC, for example.
of this class throughout your applications as POJOs. For example, you can use a save method for a given object and the underlying ORM framework will persist the data for you instead of you having to write tedious INSERT or UPDATE statements using JDBC, for example.
Hibernate is one such ORM framework and given its popularity in the world of Java today, we will use it for Time Expression. A few others, such as JDO, iBATIS, Java, and Apache ObJectRelationalBridge, are listed at the end of this
chapter under "Recommended Resources."
chapter under "Recommended Resources."
Hibernate also supports the EJB 3.0 standard, so should you need to move to EJB 3.0, it'll be an easy transition (in fact, EJB 3.0 is based on many of the concepts and techniques found in Hibernate). EJB 3.0, as you might already know, aims to simplify working with EJB technology prior to this release; for example, EJB 3.0 provides a lighter-weight persistent API similar to the one provided by Hibernate.
However, if you do not need the many services provided by EJB technology, you can use the Hibernate core technology by itself (without needing a big EJB container product such as an application server).
Before delving into Hibernate, let's review some basic concepts common across ORM technologies. Later we will look at lots of Hibernate Java code and XML file examples. After you have the hang of coding using an ORM framework, you will almost certainly not turn back to the old ways of working with relational databases.
Relationships and Cardinality
Database relationships are typically defined in terms of direction and cardinality (multiplicity in OO terminology). From an OO perspective, relationships are defined as association, inheritance, or aggregation. Many software development projects use ORM either with existing databases or are required to conform to standards established by a database group within the organization; hence, I will approach our relations discussion from a database perspective.
Note
Relationships can be viewed as unidirectional or bidirectional for objects. On the other hand, relations in a relational database are bidirectional by definition because related tables know of each other. However, if we were designing objects that map to the database, we would factor in both types of relations because object relationships have to be made bidirectional explicitly. So for the sake of our discussion on relationships and cardinality, we will pretend that the database can have bothunidirectional and bidirectionalrelations.
Unidirectional is when one table knows of another, but not vice versa. For example, you might have a record that uses a unique primary key; this same primary key can be used as a foreign key by records in a child table, thereby establishing a unidirectional relationship. In a bidirectional relationship, records in both tables would know about each other. For example, assume we have two tables named Employee and Project to store information about which employees worked on which project. In the Project record, we might have an EmployeeId foreign key. On the flip side, we might have a ProjectId key in the Employee table.
Cardinality can be defined as one-to-one, one-to-many (or many-to-one depending on which direction you look at the relationship), and many-to-many. We look at each briefly:
- A one-to-one relationship is when a record in table 1 can have exactly one associated record in table 2. For example, a record in a Person table might have exactly one related record in a JobTitle table.
- A one-to-many relationship is typically seen in parent-child relationships where a parent record can have several related records in a child table (for example, related via the parent's primary key).
- A many-to-many relationship is where a record in table 1 can have several related records in table 2 and vice versa. For example, an Employee table might have more than one record in a Project table (because an employee can be involved in multiple projects). On the flip side, a record in the Project table might have several related records in the Employee table because a project can have multiple employees assigned to it. Also, this type of relationship is typically achieved by using an (extra) association table (for example, a ProjectEmployee table that contains foreign keys pointing to the two main tables).
Object Identity
An object identity (or simply, object id) is something that uniquely defines a persisted object (that is, a record in the database). It is commonly mapped to the primary key of a database table.
Cascade
Cascading can be defined as an action on a given entity flowing down to related entities. For example, if we wanted to maintain referential integrity between related parent-child tables in a database, we would delete records from a child table whenever its related parent is deleted, so that no orphan records are left lingering in the database. Similarly, when you read a parent record in, you may also want to read in all its children records. Cascading can be defined for each of the four CRUD operationsthat is, create, read, update, and delete. Also, cascading is often handled via the use of database triggers.
Mapping
Before we can begin working with objects that store and retrieve data from a relational database, we must create mappings (usually in an XML file) between the database tables and Java classes. The mapping file typically contains properties, which essentially map an attribute (variable) in a class to a column in database. If you are new to some of these concepts, don't worry; after you see some examples later in this chapter, it'll start to become a bit clearer.
There are various mapping strategies we can employ, such as horizontal mapping, vertical mapping, and union mapping. In vertical mapping, each class in a hierarchy (abstract or concrete) is mapped to a different table. For example, if we have concrete classes named Dog and Cat, both inheriting from an abstract class named Animal, we would end up having three tables in the databaseone for each class. In horizontal mapping, each concrete class is mapped to a table. In union mapping, many classes (presumably part of the same hierarchy) map to a single table.
Although vertical mapping is more flexible, it is also more complex because it requires multiple tables to extract all the data. Hence, we will use horizontal mapping because it is a simpler design and can provide faster performance, especially for simple to reasonably complex applications. To be more specific, our approach will involve one table per class mapping strategy.
In-Memory Versus Persisted Objects
When we are working with ORM technologies, there is a distinction between database objects we have in memory versus persisted ones. If the object does not exist in the database, or its attribute values do match the corresponding column values in the database, it is considered an in-memory object. For example, Hibernate distinguishes object states as persistent, detached, or transient (each is explained later in this chapter).
Another way to look at this distinction is that if we remove an object from memory (for example, by removing it from a Java collection), it does not necessarily mean the record has been physically deleted from the database (unless, of course, we mapped the collection in Hibernate to have automatic cascading during parent deletes).
Design our Sample Database
Now that we have covered some OR concepts, it is time to set up our database so that we can move one step closer to building an application's user interface with the help of the Spring Web MVC Framework.
As I mentioned in earlier chapters, the focus of this book is more on development and less on infrastructure. Given Java's vendor product portability (for example, operating system, web/application server, databases), in theory, it should be relatively easy to develop your application using one product but deploy to another application. In light of this, I chose the easiest (and consequently lightest-weight) products to set up. HSQLDB, a relational database, is one such product (discussed later in this chapter), and we will use it for Time Expression.
Denormalization
"XP and AMDD-Based Architecture and Design Modeling," shown in Figure 5.1.
Given the simplicity of our sample application, Time Expression, and its domain model, we could create a physical database model (PDM), also known as an Entity-Relationship (ER) diagram, which contains entities identical to ones in our domain model, with the addition of columns and data types and other database constraints. However, let's denormalize it just a bit for performance and ease of development purposes.
Figure 5.2 shows a PDM, denormalized a bit from our Domain Model and with data types (for example, varchar) added to it. The denormalization is related only to the Timesheet and Time tables.
Naming Convention
You will notice we are using Java-like naming conventions for the table and column names. This makes our job easier because we can use the same names across all artifacts related to Time Expression while also gaining consistency across them. In other words, we have matching names from User Story tag/name to controller classes to model (domain) objects to the Hibernate persistent bean Java code and finally, to the database tables and columns (shown in Figure 5.2).
This naming approach makes our job easier in two ways. First, we don't need to think about the naming convention for each layer, and second, it reduces the amount of mapping details we need to specify in our Hibernate class mapping files because we do not have to specify a corresponding column name for each property being mapped (as we will see later in this chapter).
However, in the real world, you might not have control over the database table/column naming because a database group might have their own set of naming standards. In this case, it is easy to use Hibernate's column attribute to specify the database column name. I would also encourage following your organization's naming standards for consistency sake.
Note that for database objects (such as tables and sequences), I tend to use names starting with an uppercase letter, whereas column names start with a lowercase letter.
Database Design Disclaimers
The following are some disclaimers and/or explanations for the PDM we looked at in Figure 5.2.
Unused Columns
By combining the Timesheet and Time entities into one physical table, there is the possibility of wasted database space by unused columns. For example, there is a good chance that MinutesSat and MinutesSun will be less frequently used (unless employees in this company work most or all weekends). However, the advantages of the simpler design and performance arguably outweigh the disadvantages of a bit of wasted space.
Int Versus Float
We have used Minutes
Password
We have a Password column in the Employee table. Typically, in larger organizations, you might end up using something like a central Lightweight Directory Access Protocol (LDAP) authentication service. However, this works well for our small (and sample) application, Time Expression.
DDL Script
Now that we have a PDM (see Figure 5.2), we can move to the next level down, which is to write a DDL script that can be used to create the actual databse. Our DDL script is embedded inside one of our Ant scripts, named timexhsqldb.xml. The table names, column names, and data types in our DDL script closely match the PDM in Figure 5.2, as they should.
Our DDL file primarily contains CREATE TABLE statements. However, I would like to point out a couple of additional notable items.
First, the primary key column of the Timesheet table is of data type identity, as shown in this code excerpt:
CREATE TABLE Timesheet
( timesheetId IDENTITY NOT NULL,
As you might already know, an identity is an auto increment database column (and is directly supported by Hibernate). For databases that do not support identity types, we can use a sequence type instead.
Second, we have seen some test data being inserted; this is for use by our JUnit test cases covered later in this chapter. For the sake of simplicity, I have not created any primary or foreign key constraints, as we typically should in a real-world application. Also, the focus of this chapter is to demonstrate features of Hibernate and not necessarily database design.
Where HSQLDB and Hibernate Fit into Our Architecture
Before we get too far along with HSQLDB and Hibernate, it is a good idea to revisit our architecture diagram that we developed earlier in this book. Figure 5.3 shows the diagram; notice where HSQLDB and Hibernate fit into the big picture (top-right).
HSQLDB
HSQLDB is a lightweight Java database engine that has been around since 2001. However, because it is a continuation of Thomas Mueller's closed Hypersonic SQL Project, it has actually been around longer than 2001. In short, the product is fairly mature.
HSQLDB provides a good amount of ANSI-92 SQL-compliant features (and many enhancements from more recent SQL standards)more than we will need in this book. Furthermore, most of the features defined by JDBC 2, and some from JDBC 3, are also supported. HSQLDB's popularity has grown significantly since its inception a few years ago, and it is commonly found bundled with open source and commercial Java-related products such as JBoss, OpenOffice.org, Atlassian's JIRA, and many more.
At the time of this writing, the HSQLDB project was one of the top 50 ranking in more than 100,000 SourceForge.net projects.
HSQLDB can be found at http://hsqldb.org. There are ample setup instructions on this site to download, install, and configure it. I'm using version 1.8.x in this book.
HSQLDB Server and Convenient Ant Tasks
Now we need to start the HSQLDB server and create the database using our DDL file. However, first, let's copy the hsqldb.jar file from the HSQLDB install directory to our lib/ directory; for example, on my Microsoft Windows XP-based system, I typed the following:
copy \hsqldb\lib\hsqldb.jar \anil\rapidjava\timex\lib\
We will use our Ant script, timexhsqldb.xml, to start the server and also to create the database. This file is placed in the top-level directory of our sample application (in my case, this is
C:\anil\rapidjava\timex).
C:\anil\rapidjava\timex).
Assuming our HSQLDB configuration is set up correctly, we can now type the ant -f timexhsqldb.xml starthsql command to start the HSQLDB server, as demonstrated here:
C:\anil\rapidjava\timex>ant -f timexhsqldb.xml starthsql
From another command window, we can type the ant -f timexhsqldb.xml execddl command to execute our DDL script for creating our database within HSQLDB, as demonstrated here:
C:\anil\rapidjava\timex>ant -f timexhsqldb.xml execddl
Before we move on, let's review parts of timexhsqldb.xml.
The following properties are related to HSQLDB; that is, the hfile property points to a local set of files under the timex/data/ directory, the halias is the alias we will use in our client applications to connect to the HSQLDB server, and the hport is the port number the HSQLDB server will listen to:
Next, the starthsql Ant target starts the HSQLDB server using the built-in Ant java task, as shown here:
classname="${hclass}" classpath="${hjar}" args="${hfile} -dbname.0 ${halias} -port ${hport}"/>
The execddl Ant target uses the built-in sql task to execute our SQL DDL script, as shown here:
driver="org.hsqldb.jdbcDriver" url="jdbc:hsqldb:hsql://localhost:${hport}/${halias}" userid="sa" password="" print="yes">
HSQLDB Database Manager and SqlTool
HSQLDB is bundled with two tools you should read about in the HSQLDB documentation: HSQL Database Manager (GUI) and SqlTool (command-line based). These are nice tools for working with our database. Meanwhile, you will find two convenient ant tasks in our timexhsqldb.xml file, hsqldm and sqltool, which can be used to start these two tools. For example, to start HSQL Database Manager, type the following on the command line:
ant -f timexhsqldb.xml hsqldm
After the Database Manager comes up, we can change the following parameters on the screen and work with our database in a GUI fashion, instantly (assuming the HSQLDB server is running in another window):
Type: HSQL Database Engine Server
URL: jdbc:hsqldb:hsql://localhost:9005/timex
HSQLDB Persistent and In-Memory Modes
Be sure to read about the various modes HSQLDB can run in (such as local versus server and in-memory versus persistent); we will use the server and persistent mode. For example, we could also use the very same HSQLDB database files (found under our timex/data/ directory) as follows:
jdbc:hsqldb:file:${catalina.base}/webapps/timex/WEB-INF/data/timexdb
Incidentally, this is a feature that ties in nicely with the next section on bundling HSQLDB in an archive file.
Bundling HSQLDB in a Deployable Archive File
As an added benefit, HSQLDB has a small enough footprint to run entirely in memory. For example, we could deploy our sample application with HSQLDB, bundled in the same web archive (WAR) file, essentially making the WAR file a fully self-contained system with no need for an external database!
Working with Hibernate
Hibernate has recently gained a lot of momentum in the world of Java database application development. Although products such as Toplink and others have been around for many years, Hibernate is open source (hence, free), stable, mature, well documented, and relatively easy to learn; these are probably just a few reasons why it is as popular as it is. Hibernate has been around for several years but was recently acquired by the JBoss group. (However, it continues to operate autonomously as an open source project.)
The Hibernate persistence framework can make working with relational databases using Java a pleasant experience. This is especially true if you have been developing using JDBC or using heavy-handed type entity beans. Defining the mappings can seem like a slight pain initially, but as you will see in later in this book, there are tools to generate these mapping files.
No Need for DAOs or DTOs
The extra work of defining mappings is well worth it because our persistence code will be cleaner and we will have automatically eliminated the need for Data Access Objects (DAOs), which typically are objects that know how to persist themselves. We also won't need Data Transfer Objects (DTOs), which are objects used to encapsulate business data and get transferred between layers of an application.
Supported Databases
As of the writing of this book, Hibernate supported the following databases (other databases are supported via community efforts):
· DB2
· HSQLDB
· Microsoft SQL Server
· MySQL
· Oracle
· PostgreSQL
· SAP DB
· Sybase
· TimesTen
Hibernate and EJB 3.x
One thing worth mentioning here is that members of the Hibernate/JBoss team are part of the EJB 3.0 expert group, a group that helped simplify the EJB specifications. It should come as no surprise, then, that the latest version of Hibernate supports the EJB 3.0 specification. However, we will not cover the EJB 3.0 here because it is outside the scope of this book. The focus of this book is on lighter-weight (and open source) frameworks, not heavy-handed specifications that require commercial application servers to use these features.
Simple Test for Hibernate Setup
Before diving into Hibernate concepts and terminology, let's look at a simple hibernate program and the setup involved. The following sections outline the steps required to get our first test program, SimpleTest, working. But first, let's take another look at the development directory structure we established in Chapter 3.
Figure 5.4 shows the development directory structure for Time Expression. It is important to review this again because we will create several files in this chapter and refer to them using their relative path namesfor example, model/Department.java means file Department.java in the timex/src/java/com/visualpatterns/timex/model/ directory.
Hibernate XML Files and Related Java Files
We will place the three types of Hibernate files (discussed next), a Hibernate configuration file, related Java classes, and table mapping files, in the same directory. This is the practice recommended in Hibernate documentation and examples.
The naming convention for the Hibernate mapping files is typically the name of the Java class name with a suffix of .hbm.xmlfor example, Timesheet.hbm.xml.
Hibernate Configuration File (hibernate.cfg.xml)
First we will create a file named hibernate.cfg.xml in the timex/src/java/com/visualpatterns/timex/model/ directory. This file will contain a SessionFactory definition (discussed later in this chapter) and reference to our first mapping file, Department.hbm.xml. Let's review some of the interesting lines from this file:
The following lines show the HSQLDB-related configuration (as we saw in timexhsqldb.xml, previously):
org.hsqldb.jdbcDriver
jdbc:hsqldb:hsql://localhost:9005/timex
sa
The following lines from our hibernate.cfg.xml show the reference to the mapping files we will create in this chapter:
Using the complete hibernate.cfg.xml file, we will be able to create a Hibernate SessionFactory (discussed later in this chapter).
Mapping File (Department.hbm.xml)
We will create our first mapping file, Department.hbm.xml, in the timex/src/java/com/visualpatterns/timex/model/ directory.
To keep things simple, I chose to start with the Department table because it is one of the simpler tables, and we will also use it in our slightly more complex example later in this chapter. Let's review the Department.hbm.xml file a bit closer.
The following line maps our Java class to the database table:
The following line establishes departmentCode as the object id (as we discussed earlier) and the database primary key, and also maps the two:
The generator class="assigned" value shown next tells Hibernate that we will be responsible for setting the value of this object id in our Java class, and Hibernate does not need to do anything special, such as get the next sequence from an auto-increment type column (for example, HSQLDB's identity data type):
This line maps the remainder of the Department tablethat is, the name column to a name property in the Department.java class file (discussed next):
Java Code
We will write two Java classes, one called com.visualpatterns.timex.model. Department and another called com.visualpatterns.timex.test. HibernateTest.
Department.java
The Department.java (under src/java/com/visualpatterns/timex/model) contains a simple JavaBean class, which provides accessors (get methods or getters) and mutators (set methods or setters) for these two variables:
String departmentCode; String name;
HibernateTest.java
Now we will write some simple code to accomplish two things: test the Hibernate setup and also look at a basic example of how to use Hibernate. Let's review our HibernateTest.java file (under src/java/com/visualpatterns/timex/test) step-by-step.
The first few lines show how we obtain a Hibernate SessionFactory class and get a single Department record back for the departmentCode "IT":
SessionFactory sessionFactory = new Configuration().configure()
.buildSessionFactory();
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.beginTransaction(); Department department; department = (Department) session.get(Department.class, "IT"); System.out.println("Name for IT = " + department.getName());
The following lines shows how to get and process a java.util. List of Department objects.
List departmentList = session.createQuery("from Department").list();
for (int i = 0; i < departmentList.size(); i++) {
department = (Department) departmentList.get(i);
System.out.println("Row " + (i + 1) + "> " + department.getName()
+ " (" + department.getDepartmentCode() + ")"); }
The remaining notable line closes out theSessionFactory.
sessionFactory.close();
Note the HibernateTest.java file provides a simple example of using Hibernate by bunching all the code in a single (main) method. Later in this chapter, we will look at a better way of building a SessionFactory and subsequently obtaining Session objects from it.
Now we are going to try running our test using our Ant build.xml file, introduced in Chapter 4, "Environment Setup: JDK, Ant, and JUnit." Our Ant target, hibernatetest, is as follows:
classname="com.visualpatterns.timex.test. HibernateTest"/>
To run our test, we need to:
· Change (cd) to the timex/ (top-level) directory.
Notice that there are errors on the screen, such as package org.hibernate does not exist. This means it is time to download and set up Hibernate in our environment!
Installing Hibernate
Hibernate can be found at http://hibernate.org. At this point, we will follow the setup instructions provided on this site to download and install it to the recommended (or default) directory.
After we have the Hibernate installed, we will copy all the recommended libraries (for example, hibernate3.jar and antlr.jar) in the Hibernate documentation to the rapidjava/lib directory.
Note that I also needed to copy ehcache-1.1.jar and antlr-2.7.6rc1.jar (which was not mentioned in the Hibernate reference documentation at the time of this writing). Here is what I ended up with, in my timex/lib/ directory:
· antlr-2.7.6rc1.jar
· asm-attrs.jar
· asm.jar
· cglib-2.1.3.jar
· commons-collections-2.1.1.jar
· commons-logging-1.0.4.jar
· dom4j-1.6.1.jar
· ehcache-1.1.jar
· hibernate3.jar
· jta.jar
· log4j-1.2.11.jar
Before rerunning our test, we need to temporarily alter the hibernate.cfg.xml file. Because we have only Department.hbm.xml implemented, we need to temporarily remove the following lines (to conduct this test) from our hibernate.cfg.xml file:
Finally, we can rerun the ant hibernatetest command. If we run the ant as shown earlier in Figure 5.5, this time our command is successful, as shown in Figure 5.6!
At this point, we can reinsert the following two lines into the hibernate.cfg.xml file:
Notice the log4j warning messages in Figure 5.6. We could ignore these because they are harmless. However, we'll go ahead and create a minimal log4j.properties file (available in this book's code zip file) in our timex/src/conf directory. Logging will be discussed in more detail in Chapter 9, "Logging, Debugging, Monitoring, and Profiling."
Hibernate Basics
Now that we have looked at a small preview of Hibernate-related Java code and XML files, let's get a high-level understanding of some basic Hibernate concepts before we look at slightly more complex Hibernate code for the Time Expression application.
Dialect
Hibernate provides dialect classes for the various supported databases mentioned earlier. This is essentially to ensure that the correct and most optimized SQL is used for the database product being used. For example, we are using the org.hibernate.dialect. HSQLDialect class for HSQLDB.
SessionFactory, Session, and Transaction
SessionFactory, as you might guess, manages a collection of Session objects. Each SessionFactory is mapped to a single database. The Session object essentially is a wrapper for a JDBC connection and is also a factory for Transaction objects. A Transaction is a wrapper for the underlying transaction, typically a JDBC transaction.
Built-In Connection Pooling
A side but important benefit of using Hibernate is that it provides built-in database connection poolinghence, one less thing for us to worry about. Connection pooling, as you might be aware, is used to create a specified pool of open database connections (see connection.pool_size property in our hibernate.cfg.xml). By using a pool of connections, we can achieve more efficiency in our use of the database because existing open connections are reused. Furthermore, we get performance gains because we reuse open connections, thereby avoiding any delays in opening and closing database connections.
Working with Database Records (as Java Objects)
Several methods available in Hibernate's org.hibernate. Session interface enable us to work with database records as objects. The most notable methods are save, load, get, update, merge, saveOrUpdate, delete, and createQuery (several of these are demonstrated later in this chapter).
Another noteworthy interface to mention is org.hibernate. Query, which is returned by calling the Session.createQuery Hibernate method in our HibernateTest.java file. The Query class can be used to obtain a group of records in the form of a java.util. Collection object (for example, Hibernate provides mapping elements such as an array, set, bag, and others).
One last interface worth mentioning here is org.hibernate. Criteria, which can be used for database queries in an OO fashion, as an alternative to the Query class (which is HQL based).
We will look at examples of most of these interfaces and methods in this chapter.
Object States
Hibernate defines three states for object instances: persistent, detached, and transient. Persistent objects are ones that are currently associated with a Hibernate session; as soon as the session is closed (or the object is evicted), the objects become detached. Hibernate ensures that Java objects in a persistent state for an active session match the corresponding record(s) in the database. Transient objects are ones that are not (and most likely, never were) associated with Hibernate session and also do not have an object identity.
Data Types
Hibernate supports a large number of Java, SQL, and Hibernate typesmore than you will probably need for a typical application. Also, you can have Hibernate automatically convert from one type to another by using a different type for a given property in a entity/class mapping file.
The following is a partial list of types supported: integer, long, short, float, double, character, byte, boolean, yes_no, true_false, string, date, time, timestamp, calendar, calendar_date, big_decimal, big_integer, locale, timezone, currency, class, binary, text, serializable, clob, and blob.
Hibernate Query Language (HQL)
HQL is Hibernate's robust SQL-like query language, which is not case sensitive. HQL has many of the features defined in ANSI SQL and beyond, because it is fully object-oriented and supports OO concepts such as inheritance, polymorphism, and more. The following are some basic clauses and features supported in HQL. You wil
Read 373 times
Published in
Java