Perhaps you have heard of Hibernate's name, but may have been not understand it, perhaps you have been eager to use it for development, then this article is what you need! In this article, I will highlight Hibernate's core API call library and explain its basic configuration.
After reading this article, I believe you have a deep understanding of what an ORM (image/relationship mapping) and its advantages will be, and let's start by using a simple example to show its power.
As some traditional classical computer articles will be explained by a "hello,world" example, we are no exception, we will also explain the development method of hibernate from a relatively simple example, but if we want to really expound some important ideas of hibernate, It's not enough to just print some characters on the screen, and in our sample program we'll create objects, save them in the database, and then update and query them.
Reading Navigation
The Hello World sample program gives you a simple understanding of hibernate.
Understanding the Hibernate architecture describes the main features of the Hibernate interface.
Core interface Hibernate has 5 core interfaces through which developers can store and acquire persistent objects and be able to control transactions
An important term: Typetype is a term invented by hibernate inventors, which is a very basic and powerful element in the entire architecture, and a type object can map a Java type to a field in a table in a database.
The policy interface hibernate, unlike some other open source software, has a high degree of scalability, which is achieved through its built-in policy mechanisms.
The underlying configuration hibernate can be configured to run in any Java environment, generally, it is typically used in 2-3-tier C/S mode projects and deployed on the server side.
Create a Sessionfactory object to create a Sessionfactory object, you must create an instance of the configuration class when the hibernate is initialized and leave the written mapping file to it for processing.
"Hello World"
The hibernate application defines some persistence classes and defines the mapping relationship between these classes and the database tables. A class and a mapping file are included in our Hello World sample program. Let's see what this simple persistence class contains. How is the mapping file defined? In addition, how do we use hibernate to manipulate this persistent class.
The purpose of our simple example program is to store some persistent classes in a database and then take them out of the database and display their body of information to the user. Where message is just a simple persistence class: It contains the information we want to display, with the following source code:
Listing 1 Message.java a simple persistence class
Package Hello;
public class Message {
Private Long ID;
private String text;
Private message nextmessage;
Private message () {}
Public message (String text) {
This.text = text;
}
Public Long getId () {
return ID;
}
private void SetId (Long id) {
This.id = ID;
}
Public String GetText () {
return text;
}
public void SetText (String text) {
This.text = text;
}
Public message Getnextmessage () {
return nextmessage;
}
public void Setnextmessage (message nextmessage) {
This.nextmessage = Nextmessage;
}
}
A message class has three properties: the ID of the message, its body, and a pointer to the next one. Where the id attribute gives our application the ability to uniquely identify the message, it is usually equivalent to a primary key in the database, and if the instance object of multiple message classes has the same ID, they represent the same record for a table in the database. Here we chose the long integer as our ID value, but this is not required. Hibernate allows us to use any type as an object's ID value, which we will describe in detail later.
You may notice that the code for the message class resembles the JavaBean code style, and that it has a constructor with no parameters, and I will continue to use this style to write the code for the persistent class in our future code.
Hibernate automatically manages instances of the message class and makes it persistent through internal mechanisms, but in reality the message object does not implement any class or interface about hibernate, so we can also use it as a normal Java class:
Message message = new Message ("Hello World");
System.out.println (Message.gettext ());
The above code is exactly what we expected: it prints "Hello World" to the screen. But this is not our ultimate goal; in fact, Hibernate is very different from the way the persistence layer is implemented with an environment such as an EJB container. Our Persistence class (message Class) can be used in a container-independent environment, unlike an EJB must have an EJB container to execute. To show this more clearly, the following code saves one of our new messages to the database:
Session session = Getsessionfactory (). Opensession ();
Transaction tx = Session.begintransaction ();
Message message = new Message ("Hello World");
Session.save (message);
Tx.commit ();
Session.close ();
The above code calls the hibernate session and the transaction interface (about the Getsessionfactory () method we'll immediately mention). It's equivalent to executing the following SQL statement:
Insert into MESSAGES (message_id, Message_text, next_message_id)
VALUES (1, ' Hello world ', null)
In the above SQL statement, what is the value of the message_id field being initialized? Is it null because we did not assign the original value to the id attribute of the Message object in the previous code? In fact, hibernate the id attribute: since it is the unique identifier of an object, when we make a save () call, Hibernate automatically assigns it a unique value (we'll tell you later about how it generates this value).
Let's say you've created a table named message in the database, so now that we've got the message object in the database, we're going to take one by one of them out. The following code takes out all the message objects in the database in alphabetical order and prints the text of their messages to the screen:
Session newsession = Getsessionfactory (). Opensession ();
Transaction newtransaction = Newsession.begintransaction ();
List Messages =newsession.find ("from message as M order by m.text ASC");
System.out.println (messages.size () + "message (s) found:");
for (Iterator iter = Messages.iterator (); Iter.hasnext ();) {
Message message = (message) iter.next ();
System.out.println (Message.gettext ());
}
Newtransaction.commit ();
Newsession.close ();
In the above code, you may be bothered by this parameter of the Find () method: "From message as M order by m.text ASC", in fact it is hibernate its own definition of the query language, full name hibernate query Language (HQL). In layman's terms, the relationship between HQL and SQL is almost the same as the relationship between dialect and Mandarin, and at first glance you'll find it a bit like a SQL statement. In fact, when the find () call is made, Hibernate translates the HQL language into the following SQL statement:
Select m.message_id, M.message_text, m.next_message_id
From MESSAGES m
ORDER BY M.message_text ASC
The following are the results of the operation:
1 message (s) found:
Hello World
If you've never developed an ORM (object-relational mapping) experience, you might want to find this SQL statement somewhere in the code, but in hibernate you might be disappointed: it doesn't exist! All of the SQL statements are hibernate dynamically generated.
Maybe you're going to feel something else. It is not possible to persist our message class with the above code hibernate. We also need some more information, which is the mapping definition table! This table is embodied in XML in Hibernate, which defines how the attributes of the message class are one by one corresponding to the fields of the messages table in the database, and listing 2 is the mapping profile list for this sample program:
Listing 2: The object-relational mapping table for the sample program
<?xml version= "1.0"? > >
! DOCTYPE hibernate-mapping Public
"-//hibernate/hibernate Mapping dtd//en"
"Http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
<class name= "Hello. Message "table=" "MESSAGES" >
<ID name= "id" column= "message_id"
<generator class= "Increment"/>
</id>
<property name= "text" column= "Message_text"/>
<many-to-one name= "Nextmessage" cascade= "All" column= "next_message_id"/>
</class>
The above document tells hibernate how to map the message class to the messages table, where the id attribute of the message class corresponds to the message_id field of the table, and the Text property corresponds to the Message_text field of the table. The Nextmessage property is a many-to-many relationship that corresponds to the next_message_id in the table.
Hibernate's configuration files are easy to understand compared to some open source projects. You can easily modify and maintain it. As long as you define the persistence class corresponds to the table field in the database, hibernate will automatically help you generate SQL statements to insert, UPDATE, Delete, find work on the Message object, you can not write a SQL statement, even do not need to understand the SQL language!
Now let's do a new experiment, we first take out the first message object, and then modify its text, and finally we regenerate it as a new message object, with the following code:
Listing 3 Updates a message
Session session = Getsessionfactory (). Opensession ();
Transaction tx = Session.begintransaction ();
1 is the generated ID of the the
Message message = (message) session.load (Message.class, New Long (1));
Message.settext ("Greetings earthling");
Message Nextmessage = new Message ("Take me to Your leader (please)");
Message.setnextmessage (Nextmessage);
Tx.commit ();
Session.close ();
When the above code is invoked, Hibernate automatically generates the following SQL statement internally:
Select m.message_id, M.message_text, m.next_message_id
From MESSAGES m
where m.message_id = 1
Insert into MESSAGES (message_id, Message_text, next_message_id)
VALUES (2, ' Take me to your leader (please) ', NULL)
Update MESSAGES
Set message_text = ' Greetings earthling ', next_message_id = 2
where message_id = 1
When the Text property and Nextmessage of the first message object are modified by the program, notice how the hibernate detects the change and how it is updated automatically in the database. This is actually a very valuable feature of Hibernate, which we call "automatic dirty Data Detection," which hibernate that when we modify the properties of a persistent object, we do not have to explicitly notify hibernate to update it in the database. Similarly, when the first message object calls the Setnextmessage () method to refer the second message object as the next one of its messages, it can be automatically saved in the database without invoking the Save () method. This feature, known as cascading save, also eliminates the pain of explicitly invoking the Save () method on the second message object.
If we run the previous section of the code that prints all the message objects in the database, the results are as follows:
2 message (s) found:
Greetings Earthling
Take me to your leader (please)
The "Hello World" sample program is now complete. We finally have a simple understanding of hibernate, and we'll go back to the main API for hibernate as a brief introduction:
understand the architecture of hibernate
When you want to use Hibernate to develop your own application based on persistence layer, the first thing you should do is familiarize yourself with its programming interface. The API interface of Hibernate is designed to be as concise as possible to facilitate developers. In reality, however, because of the complexity of ORM, its APIs are generally not designed to be simple. But don't worry, you don't need to know all the Hibernate API interfaces at once.
We put the application layer at the top of the persistence layer, and in fact, in traditional projects, the application layer acts as a client role for the persistence layer. But for some simple projects, the application and persistence layers are not as clear as they are, and that's fine, in which case you can combine the application layer and the persistence layer into a single layer.
Hibernate interfaces can be roughly divided into the following types:
· An interface that is invoked by a user's application to complete basic creation, read, update, delete operations, and query operations. These interfaces are the main interfaces for hibernate to implement the business logic of user programs, including session, transaction, and query.
· Hibernate is used to read interfaces for configuration files such as mapping tables, typically representing configuration classes.
· Callback (Callback) interface. It allows an application to do something about the occurrence of events, such as Interceptor, lifecycle, and validatable are interfaces of this kind.
· Some interfaces that can be used to extend hibernate mapping mechanisms, such as usertype, Compositeusertype, and Identifiergenerator. These interfaces can be implemented by user programs, if necessary.
Hibernate uses the following techniques in the Java EE architecture: JDBC, JTA, JNDI. JDBC is a base layer that supports relational database operations, and it is combined with jndi and JTA to make the hibernate easily integrated into the Java application Server.
Here, we won't go into detail about all the methods in the Hibernate API interface, we'll just briefly talk about the functionality of each major interface, if you want to learn more, You can view the source code of these interfaces in the hibernate package in the net.sf.hibernate. Let's talk about all the main interfaces in turn:
Core interface
The following 5 core interfaces will be used in almost any actual development. Through these interfaces, you can not only store and acquire persistent objects, but also enable transaction control.
Session interface
The session interface is one of the most important interfaces for hibernate developers. In hibernate, however, the instantiated session is a lightweight class that does not consume a lot of resources to create and destroy. This is really important in the actual project, because in the client program, the session object may be constantly created and destroyed, and if the session is too expensive, it will have a negative impact on the system. However, it is worth noting that the session object is not thread safe, so in your design it is best to have a thread create only one session object.
In the minds of hibernate designers, they view the session as an intermediate interface between data connections and transaction management. We can think of the session as a buffer of persistent objects, hibernate can detect changes to these persistent objects and refresh the database in a timely manner. We sometimes call the session a persistent Layer manager because it contains some of the persistence-related operations, such as storing persisted objects to the database, and getting them from the database. Note that the Hibernate session is different from the httpsession in the JSP application. When we use the term session, we are referring to the hibernate, and we will later call the Httpsesion object the user sessions.
Sessionfactory interface
Here we use a design pattern-factory mode, where the user program obtains the session instance from the factory class Sessionfactory.
To your surprise, sessionfactory is not lightweight! In fact its designer's intention is to allow it to be shared throughout the application. Typically, a project usually requires only one sessionfactory, but when your project is working on multiple databases, you must specify a sessionfactory for each database.
Sessionfactory actually acts as a buffer in hibernate, buffering the SQL statements that hibernate automatically generates and some other mapping data, and buffering some of the data that might be reused in the future.
Configuration interface
The function of the configuration interface is to configure the Hibernate and to start it. During hibernate startup, instances of the configuration class first locate the mapping document, read the configuration, and then create a Sessionfactory object.
Although the configuration interface plays only a small role in the entire Hibernate project, it is every object you encounter when you start hibernate.
Transaction interface
Transaction interface is an optional API, you can choose not to use this interface, replaced by the Hibernate's designer to write the underlying transaction code. The transaction interface is an abstraction of the implementation of real transactions, including JDBC transactions, usertransaction in JTA, or even CORBA transactions. This design is designed to enable developers to use a unified transaction interface, so that their own projects can be in different environments and containers easily moved between the value.
Query and Criteria Interface
The query interface gives you easy access to databases and persistent objects, and it can be expressed in two ways: the HQL language or the SQL statement for the local database. Queries are often used to bind query parameters, limit the number of query records, and ultimately perform query operations.
The criteria interface is very similar to the query interface, which allows you to create and execute object-oriented, standardized queries.
It is worth noting that the query interface is also lightweight and cannot be used outside of the session.
Callback interface
When useful events occur-such as loading, storing, and deleting a persistent object-the callback interface notifies hibernate to receive a notification message. Generally speaking, the callback interface is not necessary in a user program, but you may want to use it when you create an audit log in your project.
an important term: Type
Hibernate's designers invented a term: Type, which is a very basic, powerful element throughout the architecture. A type object can map a Java type to a field in a table in a database (in fact, it can be mapped to multiple fields in a table). All properties of the persisted class correspond to a type. This design idea uses hibernate to have a high degree of flexibility and scalability.
Hibernate has many type types built into it, and includes almost all Java basic types, such as Java.util.Currency, Java.util.calendar, byte[, and Java.io.Serializable.
Not only that, Hibernate also supports user-defined type, and by implementing interface Usertype and Interface Compositeusertype, you can add your own type. You can use this feature to make your project use custom type such as address and name, so you can get greater convenience and make your code more elegant. Custom type is a core feature in Hibernate, and its designers encourage you to use it to create a flexible, elegant project!
Policy interface
Hibernate is also different from some other open source software--a high degree of scalability, which is achieved through its built-in policy mechanisms. When you feel that some of the features of the hibernate, or some defects, you can develop a strategy to replace it, and all you have to do is to inherit one of its policy interface, and then implement your new strategy can be, the following is its policy interface:
· Primary key generation (Identifiergenerator interface)
· Native SQL language Support (dialect abstract class)
· Buffering mechanism (cache and Cacheprovider interface)
· JDBC Connection Management (ConnectionProvider interface)
· Transaction management (Transactionfactory, Transaction, and Transactionmanagerlookup interfaces)
· ORM policy (Classpersister interface)
· Property access Policy (PropertyAccessor interface)
· Proxy object Creation (Proxyfactory interface)
Hibernate creates a default implementation for the mechanisms listed above, so if you just want to enhance the functionality of one of its policies, simply inherit the class and there's no need to write code from scratch.
These are some of the core interfaces of hibernate, but when we really start developing with it, there's always a question in your mind: how do I get the session from? Let's answer the question below.
Base configuration
Now look back at what we did earlier: we wrote a sample program and briefly explained some of the core classes of hibernate. But to really get your project running, there's one more thing you have to do: configure it. Hibernate can be configured to run in any Java environment, which is generally used in 2-3-tier C/S mode projects and deployed on the server side. In this project, a Web browser, or a Java GUI program, serves as the client. While our focus is primarily on multi-tier Web applications, hibernate can actually be used in some command-line based applications. Also, the configuration of hibernate is different in different environments, and hibernate runs in two environments: a manageable environment and an environment that is not manageable
· Manageable environments-This environment manages resources such as pooling resource management, such as database connection pooling and, and transaction management, security definitions. Some of the typical Java EE servers (JBoss, Weblogic, WebSphere) have been implemented.
· An environment that is not manageable-just provides some basic functionality, such as a servlet container environment like jetty or Tomcat. A common Java desktop application or command-line program can also be considered to be in this environment. This environment does not provide automatic transaction processing, resource management, or security management, which must be defined by the application itself.
Hibernate designers have designed a unified abstract interface for both environments, so there is only one environment for developers: manageable environments. If the actual project is built in an hibernate environment such as Tomcat, it will use its own transaction processing code and the JDBC connection pool to make it a manageable environment.
For a manageable environment, hibernate integrates itself into this environment. For developers, the job you have to do is simple: just create a sessionfactory class from a configuration class.
Create a Sessionfactory object
In order to create a Sessionfactory object, you must create an instance of the configuration class when the hibernate is initialized and leave the written mapping file with it. This way, the configuration object can create a Sessionfactory object, and when the Sessionfactory object is created, the configuration object is useless, and you can simply discard it. The following is the sample code:
Configuration cfg = new Configuration ();
Cfg.addresource ("Hello/message.hbm.xml");
Cfg.setproperties (System.getproperties ());
Sessionfactory sessions = Cfg.buildsessionfactory ();
In the above code, Message.hb.xml the location of this mapping file is very special, it is related to the current classpath. For example, the classpath contains the current directory, and the Message.hbm.xml mapping file in the above code can be saved in the Hello directory in the current directory.
As a convention, the hibernate mapping file defaults to. htm.xml as its extension. Another convention is to persist in writing a configuration file for each persistent class, and consider that if you write the mappings of all persistent classes to a single configuration file, this profile must be very large and difficult to maintain. But here's a new question: If you write a configuration file for each class, where should so many profiles be stored?
Hibernate recommends that you save each mapping file in the same directory as the persistent class and have the same name as the persistent class. For example, the message persistence class in our first example program is placed in the Hello directory, and you must have a mapping file named Message.hbm.xml in this directory. Such a persistent class has its own mapping file, avoiding the appearance of "Struts-config.xml hell" in a struts project. If you don't follow this rule, then you must manually load each mapping file with the AddResource () method, but if you follow this rule, you can easily load the persistence class and its mapping file with the AddClass () method, and here is the sample code that shows this convenience:
Sessionfactory sessions = new Configuration ()
. addclass (Org.hibernate.auction.model.Item.class)
. addclass (Org.hibernate.auction.model.Category.class)
. addclass (Org.hibernate.auction.model.Bid.class)
. SetProperties (System.getproperties ())
. Buildsessionfactory ();
Of course, there are many other configuration options for the hibernate mapping file, such as database connection settings, or some settings that can change the behavior of the Hibernate runtime. All the settings can be very complex enough to make you breathless, but don't worry, because hibernate sets a reasonable default value for most of the values, you just need to modify the minimum part of those profiles.
You can modify the hibernate system configuration parameters in the following ways:
· Passes a Java.util.Properties instance as an argument to the SetProperties () method of the configuration class.
· Set the value in a java–dproperty=value manner when Hibernate is started.
· Create a configuration file named Hibernate.properties under the path that classpath can find.
· Create a file named Hibernate.cfg.xml under the path that classpath can find, and define the property value in its <property> label.
The above is a general introduction to hibernate, if you want to know more, that this article is not enough, I will launch more information on hibernate. But there is no doubt about it: it is indeed a very good persistence layer solution!