After reading this article, I believe you will have a deep understanding of what is ORM (image/link ing) and its advantages, let's start with a simple example to show its power.
Just as some traditional classical computer articles begin with a "Hello, world" example, we are no exception, we will also describe the development method of hibernate from a relatively simple example, but it is far from enough to simply print some characters on the screen if we want to really elaborate some important ideas of hibernate, in our example program, we will create some objects, store them in the database, and update and query them.
Read navigation |
"Hello World" |
The "Hello World" sample program gives you a simple understanding of hibernate.. |
Understand the hibernate Architecture |
This section describes the main functions of the hibernate interface. |
Core interface |
Hibernate has five core interfaces through which developers can store and obtain persistent objects and perform transaction control. |
An important term: Type |
Type is a term invented by the inventor of hibernate. It is a very basic and powerful element in the entire architecture, A type object can map a Java type to a table field in the database. |
Policy Interface |
Another difference between Hibernate and some other open-source software is its high scalability, which is achieved through its built-in policy mechanism. |
Basic Configuration |
Hibernate can be configured to run in any Java environment. Generally, it is used in 2-3 layer C/S mode projects and deployed on the server. |
Create a sessionfactory object |
To create a sessionfactory object, you must create an instance of the configuration class during hibernate initialization and submit the prepared ing file to it for processing. |
"Hello World"
The Hibernate application defines some persistent classes and the ing between these classes and database tables. The "Hello World" example contains a class and a ing file. Let's take a look at what this simple persistent class contains? How is a ing file defined? In addition, how can we use hibernate to operate this persistent class.
The purpose of this simple example program is to store some persistent classes in the database, extract them from the database, and display the information body to the user. Message is a simple persistent class, which contains the information to be displayed. The source code is as follows:
List 1 message. Java: A simple persistent 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; } } |
The message class has three attributes: Message ID, message body, and a pointer to the next message. The ID attribute allows our application to uniquely identify this message. Generally, it is equivalent to the primary key in the database. If multiple message class instance objects have the same ID, they represent the same record of a table in the database. Here we select a long integer as our ID value, but this is not required. Hibernate allows us to use any type as the id value of the object, which will be described in detail later.
You may notice that the message class code is similar to the Code style of JavaBean, and it has a constructor without parameters, in our future code, I will continue to use this style to write code for persistent classes.
Hibernate automatically manages message class instances and makes them persistent through internal mechanisms. However, the message object does not actually implement any hibernate classes or interfaces, therefore, we can use it as a common 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. However, this is not our final goal. In fact, Hibernate and an environment such as the EJB container differ greatly in the implementation method of the persistence layer. Our message class can be used in a container-independent environment. Unlike EJB, it must have an EJB container before execution. To better demonstrate this, the following code saves a new message 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 transaction interfaces (we will immediately mention the getsessionfactory () method ). It is equivalent to executing the following SQL statement:
Insert into messages (message_id, message_text, next_message_id) Values (1, 'Hello world', null) |
In the preceding SQL statement, what is the value of the message_id field initialized? Since we didn't assign an initial value to the ID attribute of the message object in the previous code, is it null? In fact, Hibernate makes special processing on the ID attribute: because it is the unique identifier of an object, when we call save, hibernate will automatically assign a unique value to it (We will explain in the following content how it generates this value ).
Let's assume that you have created a table named message in the database. Since the code above allows us to store the message object in the database, We need to extract them one by one. The following code Retrieves all the message objects in the database in alphabetical order and prints their message bodies 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 troubled by this parameter of the find () method: "From message as m order by M. text ASC "is actually a query language defined by hibernate. Its full name is Hibernate query language (hql ). Generally speaking, the relationship between hql and SQL is almost the relationship between dialect and Mandarin. At first glance, you will think it is a bit similar to SQL statements. In fact, in the find () call, Hibernate will translate 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 running result is as follows:
1 message (s) found: Hello World |
If you have no experience in developing ORM (Object-link ing), you may want to find this SQL statement somewhere in the code, but you may be disappointed in hibernate: it does not exist at all! All SQL statements are dynamically generated by hibernate.
Maybe you will find some disadvantages, right! By using the above Code hibernate, we cannot persist our message class. We need more information, which is the ing definition table! This table is embodied in hibernate in XML format. It defines how the attributes of the message class correspond one to one with the fields of the messages table in the database, list 2 is a list of ing configuration files for this sample program:
List 2: Object-link ing table of 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> <Hibernate-mapping> <Class name = "Hello. Message" table = "messages"> <ID name = "ID" column = "message_id"> <Generator class = "increment"/> </ID> <Property name = "text" column = "message_text"/> <Example-to-one name = "nextmessage" cascade = "all" column = "next_message_id"/> </Class> </Hibernate-mapping> |
This document tells hibernate how to map the message class to the messages table. The ID attribute of the message class corresponds to the message_id field of the table, and the text attribute corresponds to the message_text field of the table, the nextmessage attribute is a multi-to-one relationship that corresponds to next_message_id in the table.
Compared with some open-source projects, Hibernate configuration files are easy to understand. You can easily modify and maintain it. As long as you have defined the correspondence between the persistent class and the table fields in the database, Hibernate will automatically generate an SQL statement to insert, update, delete, and search the message object, you don't need to know the SQL language!
Now let's do a new experiment. First we get the first message object, then modify its message body, and finally we generate a new message object, and use it as the next message of the first message object. The Code is as follows:
List 3 Update a message
Session session = getsessionfactory (). opensession (); Transaction Tx = session. begintransaction (); // 1 is the generated ID of the first message 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 (); |
During the above Code call, Hibernate automatically generates the following SQL statement:
Select M. message_id, M. message_text, M. next_message_id From messages m Where M. message_id = 1Insert 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 attribute and nextmessage of the first message object are modified by the program, note how hibernate detects this change and automatically updates it in the database. This is actually a very valuable feature of hibernate. We call it "automatic dirty Data Detection". This feature of hibernate enables us to modify the attributes of a persistent object, you do not need to explicitly notify hibernate to update it in the database. Similarly, when the first message object calls the setnextmessage () method to reference the second message object as its next message, the second message does not need to call the SAVE () method, it can be automatically stored in the database. This feature is called "cascade storage", which saves us the trouble of explicitly calling the SAVE () method for the second message object.
If we run the previous code that prints all the message objects in the database, the running result is 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. Next we will go back and give a brief introduction to the main APIs of hibernate:
Understand the hibernate Architecture
When you want to use hibernate to develop your own persistence-layer-based applications, the first thing you should do is familiarize yourself with its programming interface. The Hibernate API is designed as concise and clear as possible to facilitate developers. However, in fact, due to the complexity of ORM, its APIs are generally not easy to design. But don't worry, you don't have to understand all the hibernate API interfaces at once. The following figure describes some important interfaces of hibernate at the application layer and persistence layer:
In, we place the application layer on the top of the persistent layer. In fact, in traditional projects, the application layer acts as a client role in the persistent layer. However, for some simple projects, the application layer and the persistent layer are not clearly distinguished. In this case, you can combine the application layer and the persistent layer into one layer.
In, Hibernate interfaces can be roughly divided into the following types:
· Interfaces called by your applications to complete basic creation, reading, update, deletion, and query operations. These interfaces are the main interfaces for hibernate to implement the business logic of user programs. They include Session, transaction, and query.
· Hibernate is used to read configuration files such as ing tables. A typical example is the configuration class.
· Callback interface. It allows applications to perform operations on events, such as interceptor, lifecycle, and validatable.
· Some interfaces that can be used to extend the hibernate ing mechanism, such as usertype, compositeusertype, and identifiergenerator. These interfaces can be implemented by user programs (if necessary ).
Hibernate uses the following technologies in the J2EE architecture: JDBC, JTA, and JNDI. Among them, JDBC is a base layer that supports relational database operations. It is combined with JNDI and JTA, so that hibernate can be easily integrated into the J2EE application server.
Here, we will not discuss in detail all the methods in the hibernate API interface. We will only briefly talk about the functions of each main interface. If you want to know more, you can use the net. SF. view the source code of these interfaces in the hibernate sub-package. Next we will talk about all the main interfaces in sequence:
Core interface
The following five core interfaces are used in almost any actual development. Through these interfaces, you can not only store and obtain persistent objects, but also control transactions.
Session Interface
The session interface is the most important interface for hibernate developers. However, in hibernate, the instantiated session is a lightweight class, and it does not occupy a lot of resources when it is created or destroyed. This is really important in the actual project, because in the client program, the session object may be constantly created and destroyed. If the session overhead is too large, it will bring adverse effects to the system. However, it is worth noting that the session object is non-thread-safe. Therefore, in your design, it is best to create only one session object for one thread.
In the minds of hibernate designers, they regard sessions as an intermediate interface between data connection and transaction management. We can think of a session as a buffer for persistent objects. hibernate can detect changes to these persistent objects and refresh the database in time. We sometimes call session a persistent layer manager because it contains some persistence layer-related operations, such as storing persistent objects to the database and obtaining 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 refer to the session in hibernate, And we will later call the httsemi sion object a user session.
Sessionfactory Interface
Here we use a design mode-factory mode. The user program obtains the session instance from the factory class sessionfactory.
What surprised you is that sessionfactory is not lightweight! In fact, its designer's intention is to allow it to be shared throughout the application. Typically, only one sessionfactory is required for a project, but when your project needs to operate on multiple databases, you must specify one sessionfactory for each database.
Sessionfactory actually plays a buffer role in hibernate. It buffers the SQL statements automatically generated by Hibernate and some other ing data, and buffered some data that may be reused in the future.
Configuration Interface
The configuration interface is used to configure and start hibernate. During hibernate startup, the configuration instance first locates the ing document, reads the configurations, and creates a sessionfactory object.
Although the configuration interface only plays a very small role in the entire hibernate project, it is every object you encounter when starting hibernate.
Transaction Interface
The transaction interface is an optional API. You can choose not to use this interface and replace it with the underlying transaction processing code written by the hibernate designer. The transaction interface is an abstraction of the actual transaction implementation. These implementations include JDBC transactions, usertransaction in JTA, and even CORBA transactions. This design allows developers to use a unified transaction operation interface so that their projects can be easily moved between different environments and containers.
Query and criteria Interfaces
The query interface allows you to easily query databases and persistent objects. It can be expressed in hql or SQL statements of local databases. Query is often used to bind query parameters, limit the number of query records, and finally perform query operations.
The criteria interface is very similar to the query interface. It 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 the session.
Callback Interface
When some useful events occur, such as loading, storing, and deleting persistent objects, the callback interface notifies hibernate to receive a notification message. Generally, the callback interface is not required in the user program, but you may use it when creating audit logs in your project.
An important term: Type
Hibernate designers invented the term "type", which is a very basic and powerful element in the entire architecture. A type object can map a Java type to fields in a table in the database (in fact, it can be mapped to multiple fields in the table ). All attributes of the persistent class correspond to a type. This design idea uses hibernate with high flexibility and scalability.
Hibernate has many built-in types, including almost all basic java types, such as Java. util. Currency, java. util. Calendar, byte [], and Java. Io. serializable.
In addition, Hibernate also supports user-defined types. You can add your own types by implementing the interface usertype and the interface compositeusertype. You can use this feature to make your project use custom types such as address and name, so that you can gain greater convenience and make your code more elegant. Custom type is a core feature in hibernate. Its designers encourage you to use it more to create a flexible and elegant project!
Policy Interface
Another difference between Hibernate and some other open-source software is its high scalability, which is achieved through its built-in policy mechanism. When you feel that some functions of Hibernate are insufficient or have some defects, you can develop a policy to replace it. All you have to do is inherit a policy interface of hibernate, then implement your new policy. The following is its policy interface:
· Primary key generation (identifiergenerator Interface)
· Local SQL language support (dialect abstract class)
· Buffer mechanism (Cache and cacheprovider interfaces)
· JDBC connection management (connectionprovider Interface)
· Transaction Management (transactionfactory, transaction, and transactionmanagerlookup interfaces)
· ORM Policy (classpersister Interface)
· Propertyaccessor Interface)
· Create a proxy object (proxyfactory Interface)
Hibernate creates a default implementation for the mechanisms listed above. Therefore, if you only want to enhance the functionality of a policy, simply inherit the class, there is no need to write code from the beginning.
These are some core interfaces of hibernate, but when we start to use it for development, you may always have a question in your mind: How do I use it, and where to obtain the session? We will answer this question below.
Basic Configuration
Now let's review our previous content: we have written a sample program and briefly explained some core classes of hibernate. But to really run your project, there is another thing you must do: configuration. Hibernate can be configured to run in any Java environment. Generally, it is used in 2-3 layer C/S mode projects and deployed on the server. In such projects, Web browsers, or Java GUI Programs Act as the client. Although our focus is mainly on multi-layer Web applications, Hibernate can also be used in some command line-based applications. In addition, the configuration of hibernate varies in different environments. hibernate runs in two environments: manageable and unmanageable.
· Manageable environment-this environment can manage the following resources: pool resource management, such as database connection pools and, as well as transaction management and security definitions. Some typical J2EE servers (JBoss, WebLogic, WebSphere) have implemented these.
· Unmanageable environment-it only provides some basic functions, such as the servlet container environment such as jetty or tomcat. A common Java Desktop Application or command line program can also be considered in this environment. Such environments cannot provide automatic transaction processing, resource management, or security management, which must be defined by the application itself.
Hibernate designers designed a unified abstract interface for these two environments, so there is only one environment for developers: manageable environment. If the actual project is built in an irmanageable environment such as Tomcat, Hibernate will use its own transaction processing code and JDBC connection pool to make it a manageable environment.
For a manageable environment, Hibernate will integrate itself into this environment. For developers, the work you need to do is very simple: you only need to create a sessionfactory class from a configuration class.
Create a sessionfactory object
To create a sessionfactory object, you must create an instance of the configuration class during hibernate initialization and submit the prepared ing file to it for processing. In this way, the configuration object can create a sessionfactory object. After the sessionfactory object is created successfully, 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, the location of the ing file message. HB. XML is special, and it is related to the current classpath. For example, if classpath contains the current directory, the message. HBM. xml ing file in the above Code can be saved in the hello directory under the current directory.
As a convention, the image file of hibernateuses .htm. XML as its extension. Another convention is to write a configuration file for each persistent class. If you write the ing of all persistent classes into a separate configuration file, the configuration file must be very large, not easy to maintain. However, there is another new problem: if you write a configuration file for each class, where should so many configuration files be stored?
Hibernate recommends that you save each ing file in the same directory as the persistent class and have the same name as the persistent class. For example, if the message persistence class in our first example program is placed in the hello directory, you must store the message ing file named message. HBM. XML in this directory. Such a persistent class has its own ing file, avoiding the case of "struts-config.xml hell" in struts projects. If you do not follow this rule, you must manually load the ing files by addresource (). However, if you follow this rule, you can easily use addclass () the method loads the persistent class and its ing file at the same time. The following is a sample code that demonstrates 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 in the hibernate ing file, such as database connection settings, or some settings that can change the runtime behavior of hibernate. All the settings may be complex enough to make you feel overwhelmed, but don't worry, because hibernate sets a reasonable default value for the vast majority of values, you only need to modify a very small part of these configuration files.
You can modify the system configuration parameters of hibernate in the following ways:
· Pass a java. util. properties instance as a parameter to the setproperties () method of the configuration class.
· Use Java-dproperty = value to set the value at hibernate startup.
· Create a configuration file named hibernate. properties in the classpath path.
· Create a file named hibernate. cfg. XML in the path that can be found in classpath, and define the property value in its <property> tag.
The above is a general introduction to hibernate. If you want to know more, this article is far from enough. I will introduce more information about hibernate. But there is no doubt: It is indeed a very good persistent layer solution!