Hibernate has conducted classification and integration and found that Hibernate is actually divided into three parts: core object, mapping, and HQL. These three parts are most commonly used in the development process. The previous articles discuss the conversion methods between core objects and objects. Next, discuss the mapping usage methods of Hibernate.
An important function of Hibernate is mapping, which can convert between object model and relational model. It is advocated by object-oriented programming ideas. Developers who use mapping programs only need to care about the writing of code in the object model. The mapping between an object and a relational database is usually defined by an XML document. This mapping document is designed to be readable and can be modified manually. I summarize this mapping relationship as shown in the following figure:
Mapping is defined through XML, managed using the session created by Hibernate, and finally the session uses JTA to submit the changes to the database. The session can be understood as a persistence manager, which manages objects in the persistence layer. It is created by the sessionFactory. When programming with Hibernate, you must first connect to the database, so you must first check the configuration of database connection in the XML, create a sessionFactory according to the configuration of the document (which can be understood as a database mirror), and then create a sessionFactory. Finally, the session will submit the changes to the database uniformly, which will complete all operations.
Process of use
1. Create a mapping file, and the mapping file is suffixed with .hbm.xml, indicating that it is a Hibernate mapping file;
2. Register the entity class in the mapping file and add the properties of the entity class to the mapping class. When adding properties, you must specify two values: id and property. The id indicates that it is the only identifier of an entity, and the property indicates that it is a field column of the table;
3. Submit modifications and synchronize data.
Note: Developers who have developed XML data to the database will soon understand that this mapping is actually a process of batch update and batch creation, and mapping is no exception. Hibernate stipulates a set of mapping standards that can be converted according to the standards. Its internal implementation is still dead, so it is only relatively flexible and easy to use.
A simple entity class mapping process:
1. Property code of entity class User1:
package com.hibernate; import java.util.Date; public class User1 { private String id; private String name; private String password; private Date createTime; private Date expireTime; public String getId() { return id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public Date getExpireTime() { return expireTime; } public void setExpireTime(Date expireTime) { this.expireTime = expireTime; } }
2. The internal code implementation of User1.hbm.xml of the mapping file User1.java:
The settings that can be set in the basic database are also provided in Hibernate. You can use label attributes to set specific mapping relationships.
Class->Tables use class tags, commonly used properties:
(1) name: Map entity class, its value needs to be set to the name of the entity class that needs to be converted into a table. During synchronization, the corresponding entity class will be found based on this attribute.
(2) table: map the name of the database table. If the name of the table to be mapped is different from the entity class name, use this property to specify the mapped table. If it does not exist, a table will be created based on the value of the property.
Check the table structure generated by the configuration in the figure above, as shown below:
The table name is changed to t_user1; the id field is changed to user_id, and the field length is 32 bits; the createTime property is mapped to the database field create_time, and is modified to date type.
Property --> fields use id or property tags, commonly used properties:
(1) name: The function is similar to the name of the class tag, and the value determines the mapping attribute name of the entity class;
(2) column: Similar to the table of the entity class tag, specifying the column name of the mapping table, and will be created if it does not exist;
(3) type: Specify the data type mapped to fields in the database and view the document as needed;
(4) Generator, which is optional, is used to generate a unique identifier for a persistent class.
<id name="id" type="long" column="cat_id"> <generator> <param name="table">uid_table</param> <param name="column">next_hi_value_column</param> </generator> </id>
All generators implement the org.hibernate.id.IdentifierGenerator interface. This is a very simple interface; some applications can choose to provide their own specific implementation. Of course, Hibernate provides a lot of built-in implementations. Here are some commonly used types:
(1) identity: The returned identifier is of type long, short or int. Similar to the database's self-increment field.
(2) sequence: Use sequences in DB2, PostgreSQL, Oracle, SAP DB, McKoi, and generators in Interbase. The returned identifier is of type long, short, or int. In the entire database, instead of self-increasing in a single table, you need to specify that self-increasing in a single table needs to be added.
(3) uuid: Use a 128-bit UUID algorithm to generate a string type identifier, which is unique in a network (using an IP address). The UUID is encoded as a string of 32-bit hexadecimal numbers. Similar to the serial number generated by .NET.
(4) native: Choose one of identity, sequence or hilo based on the capabilities of the underlying database. In a flexible way, the identity type used will be determined based on the database used. MySQL will select identity and Oracle will select sequence.
(5) assigned: manually create an identification id for the entity class. This is the default generation policy when the <generator> element is not specified.
(6) foreign: Use another associated object identifier. Usually used in combination with <one-to-one>.
Developers are often used to the manual configuration method to write configuration properties according to the documentation instructions. This is very primitive. Beginners recommend using the manual configuration method to help thinking. There are also many third-party tools that use visual methods to configure and generate XML configuration documents, which improves development efficiency. Similar tools such as XDoclet, Middlegen and AndorMDA.
Associative mappings are many to one
The basic mapping of Hibernate is discussed above. An entity class corresponds to a table and uses the <class> tag mapping in the corresponding Hibernate Mapping file. And the normal properties in the entity class correspond to the table field and are mapped using the <property> tag. In addition, when constructing entity classes, you should pay attention to: the default constructor without parameters should be implemented in entity classes, and a label should be provided. It is recommended not to use final to modify the entity class and generate getter and setter methods for the entity class. Finally, several main primary key generation strategies are introduced, and the next step is to discuss many-to-one mapping.
This many-to-one correlation mapping is reflected in the object model. It is an aggregation relationship. User is part of the group. There are Users in the group. Their life cycles are different and can be reflected in the following figure:
So how is this many-to-one relationship mapping set in Hibernate? The following will introduce two methods: use the <many-to-one> tag to map directly, or use the <many-to-one> cascade to modify the table.
1. Many-to-one direct mapping <br />It can be understood from the literal meaning that it refers to a many-to-one relationship. Many refers to the more end, and one refers to the less end. When using it, the tag is often used in the hbm of the more end, and the name attribute of <many-to-one> is set to the attribute of one end of one in the corresponding class of the mapping file, such as: <many-to-one name="group" column="groupid"></many-to-one>. This tag is added to User.hbm.xml, which corresponds to many; the name value in the tag is group to map one, and there will be an attribute called group in User.java. Next, let’s take a look at the specific code class that implements the implementation.
(1) User.java class code, which has a property called group, which will be used as the name value of the one end of <many-to-one>.
public class User { private String name; public String GetName(){ return name; } public void SetName(String name){ this.name=name; } private Group group; public Group GetGroup(){ return group; } public void SetGroup(Group group){ this.group=group; } }(2) The value of the name of <many-to-one> in User.hbm.xml is the property value of the one-side in User.java. It will generate a new column in the database, which can be understood as a foreign key of the User table.
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Generated 2014-5-14 23:39:25 by Hibernate Tools 3.4.0.CR1 --> <hibernate-mapping> <class name="com.hibernate.User" table="USER"> <id name="id" type="java.lang.Long"> <column name="ID" /> <generator /> </id> <!-- The value of name is a property in a corresponding one in User.java. It will automatically generate a column in the table, so the column is renamed using column--> <many-to-one name="group" column="groupid"></many-to-one> </class> </hibernate-mapping>
(3) Test the above mapping relationship, write two User objects into the table, name it user1 and user2, name it Zhang San and Li Si, use session to save the object, write data to the database, the code is as follows:
public void testSave1(){ Session session=null; try{ session=GetSession.getSession(); session.beginTransaction(); Group group=new Group(); group.SetName("power node"); User user1=new User(); user1.SetName("Zhang San"); user1.SetGroup(group); User user2=new User(); user2.SetName("Li Si"); user2.SetGroup(group); session.save(user1); session.save(user2); //The TransientObjectException error will be reported //The error occurs when cleaning the cache TransientObjectException //Because Group is Transient state, it is not Sessioned, and there is no matching data in the database //When User is Persistent state, Hibernate cannot find the Group object in the cache //Revealed: Objects in Persistent state cannot refer to objects in Transient state //This problem is changed in the testSave2 method session.getTransaction().commit(); }catch(Exception e){ e.printStackTrace(); session.getTransaction().rollback(); } finally{ GetSession.CloseSession(session); } }However, when using the above code, a TransientObjectException will be reported when executing writes. This is because when saving the User object, it will search for group objects in memory according to the group added in <many-to-one>. However, in the above code, the group object has always been in the Transient state and is not managed by the session, which means that the session object cannot be found, and the User object enters the Persistent state, so this error will be reported. The correct code is as follows:
public void testSave2(){ Session session=null; try{ session=GetSession.getSession(); session.beginTransaction(); Group group=new Group(); group.SetName("power node"); session.save(group); //Set the group object here to the Persistent object User user1=new User(); user1.SetName("Zhang San"); user1.SetGroup(group); User user2=new User(); user2.SetName("Li Si"); user2.SetGroup(group); session.save(user1); session.save(user2); //The data can be saved correctly//Because Group and User are objects in Persistent state//The associated object can be found in the session when Hibernate cleans the cache session.getTransaction().commit(); }catch(Exception e){ e.printStackTrace(); session.getTransaction().rollback(); } finally{ GetSession.CloseSession(session); } } 2. Cascading mapping
In addition to converting both the group object and the user object to the Persistent object mentioned above, you can also use the cascade cascade mapping attributes, add the cascade attribute in the <many-to-one> attribute, and copy it to save-update. You can write to the database when the group object is not in the Persistent state. In this way, you only need to set the Group attributes of the two user objects to the same group object to achieve a many-to-one mapping relationship. At this time, the corresponding content in User.hbm.xml is the following code:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Generated 2014-5-14 23:39:25 by Hibernate Tools 3.4.0.CR1 --> <hibernate-mapping> <class name="com.hibernate.User" table="USER"> <id name="id" type="java.lang.Long"> <column name="ID" /> <generator /> </id> <!-- Cascade modification table--> <many-to-one name="group" column="groupid" cascade="save-update"></many-to-one> </class> </hibernate-mapping>
Note: After cascade is set to save-update, it can be cascaded modification, addition and deletion to the database, but the specific cascade query operation cannot be done.
The corresponding test configuration file method is as follows:
//Cascade cascade public void testSave3(){ Session session=null; try{ session=GetSession.getSession(); session.beginTransaction(); Group group=new Group(); group.SetName("power node"); User user1=new User(); user1.SetName("Zhang San"); user1.SetGroup(group); User user2=new User(); user2.SetName("Li Si"); user2.SetGroup(group); session.save(user1); session.save(user2); //The TransientObjectException was not thrown//Because cascade is used//Hibernate will first save the User's associated object Group //Group and User are both objects in Persistent state session.getTransaction().commit(); }catch(Exception e){ e.printStackTrace(); session.getTransaction().rollback(); } finally{ GetSession.CloseSession(session); } } 3. Comparative sublimation
The two methods also implement a many-to-one mapping method, and the results are the same, but they are very different in implementation. Whether the first or second type uses <many-to-one> to add the tag to the mapping file on many end, and assign the name attribute of the tag to the attribute value of the one end of the class registered by the mapping file, thus completing the many-to-one basic mapping, which is the same. The difference is that the direct mapping relationship does not use the attributes of the Hibernate field, which is more flexible in implementation. It not only supports addition, deletion and modification, but also allows querying; the second cascade cascade modification adopts the method provided by Hibernate. This method only supports addition, deletion and modification, and does not support querying.