1. Collection mapping
1. Collection introduction
Collection mapping is also a basic mapping, but it will not be used frequently during the development process, so there is no need to have a deep understanding. You only need to understand the basic usage methods. Just be able to query the solution when you encounter such a problem during the development process. Corresponding set mapping In fact, it refers to mapping the set in java to the corresponding table. It is a mapping of collection objects. There are four types of sets in java, namely Set, Map, List and ordinary arrays. There are big differences between them:
(1) Set, there should be no duplicate objects, the objects are disordered;
(2) List can be ordered with repeated objects;
(3) Map, it appears in pairs of key values;
(4) Arrays can be repeated, and there is an order between objects.
The difference between them determines which collection is used during development. Usually, Set is used during development. The objects inside it are unnecessary and the internal objects can be obtained using an iterator. If these sets want to map to the corresponding relational model, you must use the mapping tags provided by Hibernate, <set>, <list>, <map>, and <array>.
2. Mapping introduction
Continue to discuss the relationship model of set mapping. Set mapping refers to an object corresponding to another object collection. When saving, Hibernate will save the data set to the corresponding table and save the data to the data table according to the id it allocates. If a new table is assigned to the set separately, the id will be assigned to the id of the set table, and the corresponding relationship table is as follows:
3. Class files
How set mapping is implemented through code, and we will analyze it in detail next. Here we seal all the collections into a class. We call this class CollectionMapping.java, so its corresponding internal code is as follows:
package com.hibernate; import java.util.List; import java.util.Map; import java.util.Set; @SuppressWarnings("rawtypes") public class CollectionMapping { //id private int id; public int getId() { return id; } public void setId(int id) { this.id = id; } //name private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } //Set collection private Set setValues; public Set getSetValues() { return setValues; } public void setSetValues(Set setValues) { this.setValues = setValues; } //List collection private List listValues; public List getListValues() { return listValues; } public void setListValues(List listValues) { this.listValues = listValues; } //Array collection private String[] arrayValues; public String[] getArrayValues() { return arrayValues; } public void setArrayValues(String[] arrayValues) { this.arrayValues = arrayValues; } //Map collection private Map mapValues; public Map getMapValues() { return mapValues; } public void setMapValues(Map mapValues) { this.mapValues = mapValues; } }This class encapsulates several commonly used sets. If you want to convert them into a relational model, you must look at the mapping below.
4. Collection Mapping
The mapping of a collection is actually quite simple. You only need to add the corresponding collection tags. Hibernate provides the collection tags <set>, <map>, <list>, and <array> respectively. The collection is mapped into the corresponding relationship table by using the centralized tag. In addition, the association of foreign keys is achieved by adding the <key> tag, and other attributes are added by using <element>.
CollectionMapping.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.hibernate.CollectionMapping" table="t_collection_mapping"> <id name="id"> <generator//id> <property name="name"/> <set name="setValues" table="t_set_values"> <key column="set_id"></key> <element type="string" column="set_value"></element> </set> <list name="listValues" table="t_list_values"> <key column="list_id"/> <list-index column="list_index"/> <element type="string" column="list_value"/> </list> <map name="mapValues" table="t_map_values"> <key column="map_id"/> <map-key type="string" column="map_key"/> <element type="string" column="map_value"/> </map> <array name="arrayValues" table="t_array_value"> <key column="array_id"/> <index column="array_index" type="integer"></index> <element type="string" column="array_value"/> </array> </class> </hibernate-mapping>
It should be noted that the list tag and array tag. The objects in these two sets are in order. Therefore, when adding mapping tags, you need to use list-index or index tags to indicate the order of the objects. Moreover, when adding sub-tags, you must add them in order. That is to say, first add the <key> tag, then add the <list-index> tag, and finally add the <element> tag, otherwise the following error will appear:
The content of element type "list" must match "(meta*,subselect?,cache?,synchronize*,comment?,key,(index|list-index),(element|one-to-many|many-to-many|composite-element|many-to-any),loader?,sql-insert?,sql-update?,sql-delete?,sql-delete-all?,filter*)".
5. Relational model
The configured object model is converted into the corresponding relational model, and the generated SQL statement is as follows:
alter table t_array_value drop foreign key FK2E0DD0C067676B68 alter table t_list_values drop foreign key FKE01EC98BF4FCB03 alter table t_map_values drop foreign key FKD169BA107402B585 alter table t_set_values drop foreign key FK7BB8D04A7E79F8BF drop table if exists t_array_value drop table if exists t_collection_mapping drop table if exists t_list_values drop table if exists t_map_values drop table if exists t_set_values create table t_array_value (array_id integer not null, array_value varchar(255), array_index integer not null, primary key (array_id, array_index)) create table t_collection_mapping (id integer not null auto_increment, name varchar(255), primary key (id)) create table t_list_value varchar(255), list_index integer not null, primary key (list_id, list_index)) create table t_map_values (map_id integer not null, map_value varchar(255), map_key varchar(255) not null, primary key (map_id, map_key)) create table t_set_values (set_id integer not null, set_value varchar(255)) alter table t_array_value add index FK2E0DD0C067676B68 (array_id), add constraint FK2E0DD0C067676B68 foreign key (array_id) references t_collection_mapping (id) alter table t_list_values add index FKE01EC98BF4FCB03 (list_id), add constraint FKE01EC98BF4FCB03 foreign key (list_id) references t_collection_mapping (id) alter table t_map_values add index FKD169BA107402B585 (map_id), add constraint FKD169BA107402B585 foreign key (map_id) references t_collection_mapping (id) alter table t_set_values add index FK7BB8D04A7E79F8BF (set_id), add constraint FK7BB8D04A7E79F8BF foreign key (set_id) references t_collection_mapping (id)
The corresponding database view generated is as follows:
2. Data operation
1. Data writing
When writing data operations, you need to pay attention to creating data objects when writing data. List, Set, and Map need to create data objects and write data objects to the database. Because all three of them are object interfaces, you need to create an object and write the object to the database. The specific code is as follows:
@SuppressWarnings({ "unchecked", "rawtypes" }) public void testsave(){ Session session=null; try{ session=HibernateUtils.getSession(); session.beginTransaction(); CollectionMapping cm=new CollectionMapping(); cm.setName("zhangsan"); Set set=new HashSet(); set.add("a"); set.add("b"); cm.setSetValues(set); List list=new ArrayList(); list.add("list1"); list.add("list2"); cm.setListValues(list); String[] str=new String[]{"array1","array2"}; cm.setArrayValues(str); Map map=new HashMap(); map.put("k1","v1"); map.put("k2", "v2"); cm.setMapValues(map); session.save(cm); session.getTransaction().commit(); }catch(Exception e){ e.printStackTrace(); session.getTransaction().rollback(); } finally{ HibernateUtils.closeSession(session); } }The generated SQL statement is as follows:
Hibernate: insert into t_collection_mapping (name) values (?) Hibernate: insert into t_set_values (set_id, set_value) values (?, ?) Hibernate: insert into t_set_values (set_id, set_value) values (?, ?) Hibernate: insert into t_list_values (list_id, list_index, list_value) values (?, ?, ?) Hibernate: insert into t_list_values (list_id, list_index, list_value) values (?, ?, ?) Hibernate: insert into t_list_values (list_id, list_index, list_value) values (?, ?, ?) Hibernate: insert into t_list_values (list_id, list_index, list_value) values (?, ?, ?) Hibernate: insert into t_map_values (map_id, map_key, map_value) values (?, ?, ?) Hibernate: insert into t_map_values (map_id, map_key, map_value) values (?, ?, ?) Hibernate: insert into t_array_value (array_id, array_index, array_value) values (?, ?, ?) Hibernate: insert into t_array_value (array_id, array_index, array_value) values (?, ?, ?)
2. Loading data
The method of loading data is very simple. It will load the data in the table into the object according to the set, and then you only need to get the corresponding object collection.
public void testload(){ Session session=null; try{ session=HibernateUtils.getSession(); session.beginTransaction(); CollectionMapping cm=(CollectionMapping)session.load(CollectionMapping.class, 1); System.out.println("cm.name= "+cm.getName()); System.out.println("cm.list= "+cm.getListValues()); System.out.println("cm.map= "+cm.getMapValues()); System.out.println("cm.array= "+cm.getArrayValues()); System.out.println("cm.set= "+cm.getSetValues()); session.getTransaction().commit(); }catch(Exception e){ e.printStackTrace(); session.getTransaction().rollback(); } finally{ HibernateUtils.closeSession(session); } }The result generated:
Hibernate: select collection0_.id as id0_0_, collection0_.name as name0_0_ from t_collection_mapping collection0_ where collection0_.id=? Hibernate: select arrayvalue0_.array_id as array1_0_, arrayvalue0_.array_value as array2_0_, arrayvalue0_.array_index as array3_0_ from t_array_value arrayvalue0_ where arrayvalue0_.array_id=? cm.name= zhangsan Hibernate: select listvalues0_.list_id as list1_0_, listvalues0_.list_value as list2_0_, listvalues0_.list_index as list3_0_ from t_list_values listvalues0_ where listvalues0_.list_id=? cm.list= [list1, list2] Hibernate: select mapvalues0_.map_id as map1_0_, mapvalues0_.map_value as map2_0_, mapvalues0_.map_key as map3_0_ from t_map_values mapvalues0_ where mapvalues0_.map_id=? cm.map= {k1=v1, k2=v2} cm.array= [Ljava.lang.String;@758d8478 Hibernate: select setvalues0_.set_id as set1_0_, setvalues0_.set_value as set2_0_ from t_set_values setvalues0_ where setvalues0_.set_id=? cm.set= [b, a] 3. Summary
Hibernate can persist instances of the following java collections, including java.util.Map, java.util.Set, java.util.SortedMap, java.util.SortedSet, java.util.List, and arrays of any persistent entities or values (using Set collection types is the best choice). Properties of type java.util.Collection or java.util.List can also be persisted using the "bag" semantics. Collections used for persistence cannot retain the semantics attached to any classes that implement these interfaces except for the collection interface (for example: iterative order brought by LinkedHashSet). All persistent collections actually work directly according to the semantics of HashMap, HashSet, TreeMap, TreeSet and ArrayList. To put it more deeply, for a property that contains a collection, the Java type must be defined as an interface (that is, Map, Set, or List, etc.), and must not be HashMap, TreeSet or ArrayList. The reason for this limitation is that when you don't know, Hibernate secretly replaces your Map, Set and List instances with its own implementation of Map, Set or List. (So in your program, use the == operator with caution.) (Note: For performance and other reasons, almost all Java collection interfaces are implemented in Hibernate (to implement some features of lazy loading).) All ordered collection classes (maps, lists, arrays) have a primary key composed of <key> and <index>. In this case, the update of the collection class is very efficient - the primary key has been indexed effectively, so when Hibernate tries to update or delete a row, the data of that row can be found quickly. The primary key of a set (sets) consists of <key> and other element fields. This is inefficient for some element types, especially combination elements or large text or large binary fields; the database may not be able to effectively index complex primary keys. On the other hand, for one-to-many, many-to-many associations, especially synthetic identifiers, sets can achieve the same efficient performance. (Part 1: If you want SchemaExport to create a primary key for your <set>, you must declare all fields as not-null="true".) The <idbag> map defines the proxy key, so it can always be updated efficiently. In fact, <idbag> has the best performance. Bag is the worst. Because bag allows duplicate element values and does not have index fields, it is impossible to define primary keys. Hibernate cannot determine duplicate lines. When such a collection is changed, Hibernate will first completely remove the entire collection (through a single DELETE) and then recreate the entire collection. Therefore Bag is very inefficient.