A detailed explanation of interceptor and Collection_java in Java's hibernate framework

Source: Internet
Author: User
Tags commit generator set set java util

Interceptor
Speaking of Interceptor, I believe that familiar with Struts2 's children's shoes will not be unfamiliar, struts2 can customize the interceptor to carry out their own desired series of related work. And the interceptor we're talking about here are pretty much the same function.
Nonsense not to say, directly to the code:
The following is the Myinterceptor class, which implements the Interceptor interface:

public string Onpreparestatement (string arg0) {return 
  arg0; 
} 
 
public boolean OnSave (Object arg0, Serializable arg1, object[] arg2, 
    string[] arg3, type[] arg4) throws Callbackexcept Ion { 
  if (arg0 instanceof user) { 
    System.out.println ("User to be Saved=>" + ((user) arg0). GetName ()); 
  return false; 
} 

Other methods do not read, by default implementation on the line, we only need to change the two methods, we need to change the return value in the Onpreparestatement, to return to the current SQL statement, the parameter is the incoming execution of the SQL statement, we can directly return to print out the statement.
In OnSave, the name can be known to be invoked at the time of the save. We can do a series of work before saving.
I believe you can see the name of the parameter to understand it.
Serializable refers to the parameter of the serial number, which is the property that maps to the database ID.
Object[] This is a series of states that are not used for the time being, and are later used for further research, but the API explains that the OnSave method must return true, regardless of the manner in which the values in the array are modified.
String[] refers to the name of the property
and type[] is the type of the corresponding property.

1 This interceptor can do some operations before and after the database is saved. For example, if you want to modify the data, add a prefix or suffix, you can use it to achieve, let's take a look at.

public boolean OnSave (Object arg0, Serializable arg1, object[] arg2, 
    string[] arg3, type[] arg4) throws Callbackexcept Ion { 
  if (arg0 instanceof user) { 
    System.out.println ("User to be Saved=>" + ((user) arg0). GetName ()); 
  We add 123 here as the prefix of the name 
  user user = (user) arg0; 
  User.setname ("123" +user.getname ()); 
  return false; 
} 

Let's take a look at the test methods:

public static void Main (string[] args) { 
 
  Configuration cfg = new Configuration (). Configure (); 
  Sessionfactory sessionfactory = Cfg.buildsessionfactory (); 
  Interceptor Interceptor = new Myinteceptor (); 
  Session session = Sessionfactory.opensession (Interceptor); 
     
  User user = new user (); 
  User.setname ("Shun"); 
     
  Transaction tx = Session.begintransaction (); 
  Session.save (user); 
     
  Tx.commit (); 
  Session.close (); 
     
} 

It's simple, we just keep it simple. The mapping file and entity classes are not given here, and you can just try it out.
Run it and we can see:

User to is Saved=>shun 
Hibernate:insert into User (user_name, age) VALUES (?,?) 
Hibernate:update USER set user_name=?, age=? where user_id=? 

It will be the last to update the name and age of the operation, mainly because we have been modified in the OnSave method.
We see that the values in the database have been modified to have 123 prefixes.

2 in the same way, we can modify the value of the property at load time:
public boolean onLoad (Object arg0, Serializable arg1, object[] arg2, 
    string[] arg3, type[] Arg4 throws Ion { 
     
  if (arg0 instanceof user) { 
    System.out.println ("User to be loaded=>" + (arg2[0]+ ":" +arg2[1]); 
  } 
  User user = (user) arg0; 
  Determine which property is name for 
  (int i = 0; i < arg3.length i + +) { 
    if (arg3[i].equals ("name")) { 
      User.setname (((String) Arg2[i]). Replace ("123", "")); 
      Arg2[i] = ((String) arg2[i]). Replace ("123", ""); 
    } 
  return false; 
} 

The value of modifying the property at load time is written in the OnLoad method.
The arg0 here is our user object, which has no value, and this method is invoked after the Load method, so we're not going to be working on the user at this point, and our user.setname is useless. Mainly in:

Arg2[i] = ((String) arg2[i]). Replace ("123", "");


This code changes the value of the returned property, so the value in the user object we get in the program changes, and we run the test method to see:

public static void Main (string[] args) { 
 
  Configuration cfg = new Configuration (). Configure (); 
  Sessionfactory sessionfactory = Cfg.buildsessionfactory (); 
  Interceptor Interceptor = new Myinteceptor (); 
  Session session = Sessionfactory.opensession (Interceptor); 
     
  User user = (user) session.load (user.class,new Long); 
     
  System.out.println ("User Name:" +user.getname ()); 
  Session.close (); 
     
} 

Looking at the results, we got:

Hibernate:select user0_. user_id as user1_0_0_, user0_. User_name as user2_0_0_, user0_.age as age0_0_ from USER user0_ where user0_. User_id=? 
User to is loaded=>123shun:0 
user Name:shun 

We have removed the original 123, in the real load after the relevant treatment, but this is not really loaded before the deal, a bit speculative suspicion. But it is also a plan to consider. Interceptor may be the most used or in the log related processing, such as we need to do every operation of the corresponding log records, then Interceptor is a good choice.

Collection
remember what we used in the previous example of a pair of set, still have the impression, if not quickly to check the data, review. Today we are going to study around these collection.
No more nonsense, let's go straight to the point.
1 First, let's learn about set. We all know that the Java Util package also has a set, then hibernate inside the set and Java set and what difference and connection? We open the Hibernate API and find the set, which we can see.

What we see is the parent class of a Hibernate collection, which is an abstract class, with a series of concrete implementation classes, and we continue to see the following method, and we find that the class implementation encapsulates the Java collection so that we understand that The so-called hibernate set actually encapsulates only the Java set.
So is the feature of the set that does not allow repeating elements to be hibernate? The answer is certainly yes.
We don't see this here, we used to relate attributes directly to the associated classes when we were learning maps, but today we don't, we use another method, we just correlate a string and see what the problem is.
But before we look at the problem, let's take a look at the string comparison in Java.
What we see is the parent class of a Hibernate collection, which is an abstract class, with a series of concrete implementation classes, and we continue to see the following method, and we find that the class implementation encapsulates the Java collection so that we understand that The so-called hibernate set actually encapsulates only the Java set.
So is the feature of the set that does not allow repeating elements to be hibernate? The answer is certainly yes.
We don't see this here, we used to relate attributes directly to the associated classes when we were learning maps, but today we don't, we use another method, we just correlate a string and see what the problem is.
But before we look at the problem, let's take a look at the string comparison in Java.

public static void Main (string[] args) { 
 
  String S1 = "shun1"; 
  String s2 = "shun1"; 
  System.out.println ("S1==S2:" + (S1==S2)); 
     
} 

I believe many children's shoes know the answer is true.
Before we take a look at our mapping files, the mapping classes are not written:
This is the Tuser mapping file:

<class name= "TUser" table= "T_user" dynamic-insert= "true" dynamic-update= "true" > 
  <id name= "id" column= " ID "> 
    <generator class=" native "/> 
  </id> 
  <property name=" name "type=" java.lang.String ' column= ' name '/> 
  <property name= ' age ' type= ' Java.lang.Integer ' column= ' age '/> <set name= ' 
  Addresses "cascade=" All "table=" t_address "> 
    <key column=" user_id "/> 
    <!--<one-to-many class= "Address"/>--> 
    <element column= "Address" type= "string"/> 
  </set> 
   
</class> 

Next is the map file for address:

<class name= "Address" table= "T_address" dynamic-insert= "false" Dynamic-update= "false" > 
  <id name= "id" column= "id" type= "java.lang.Integer" > 
    <generator class= "native"/> 
  </id> 
  <property Name= "Address" column= "Address" type= "java.lang.String"/> <many-to-one name= " 
  user" class= "TUser  
    " Column= "user_id" not-null= "true" ></many-to-one> 
 
</class> 

Children's shoes See Clearly, I tuser in the set inside the one-to-many annotation and use element, here first regardless of what it has the problem, we first look at the database:
This is the T_address table:

Here is the T_user table:

We can see that the user ID 4 corresponds to three addresses, and next, let's take a look at the test method:

public static void Main (string[] args) { 
     
  Configuration cfg = new Configuration (). Configure (); 
  Sessionfactory sessionfactory = Cfg.buildsessionfactory (); 
  Session session = Sessionfactory.opensession (); 
     
  TUser user = (TUser) session.load (tuser.class,new Integer (4)); 
  Set set = User.getaddresses (); 
  Session.close ();   
  SYSTEM.OUT.PRINTLN ("Address Size:" +set.size ()); 
} 

A very simple query class, just take out the result, we see a strange phenomenon:

Address Size:1 

This is the result!
You will say, surely wrong, is the hibernate bug. Here must be happy, finally can submit a bug, before job-hopping can loudly say I have submitted a bug for hibernate. Haha, but unfortunately, this is not a bug.
Just now said that we are in front of the string comparison is for here to pave the way, then how to shop it?
We use set in the config file, and is associated with a string character, it first determines whether the value of the associated character is equal when it is fetched into the set in the database, because our values are equal (we do not delve into how it is compared here for the moment). All we need to know is that when we compare strings, we're stuck in a string trap in Java. Found only one, then delete it, delete the time is more trouble, it will be all the same record deleted.
So let's take a look at the deletion:

TUser user = (TUser) session.load (tuser.class,new Integer (4)); 
     
Transaction tx = Session.begintransaction (); 
Object obj = user.getaddresses (). iterator (). Next (); 
     
User.getaddresses (). Remove (obj); 
     
Tx.commit (); 
Session.close (); 

Here the Hibernate output statement is:

Hibernate:delete from t_address where user_id=? 

Believe when everyone knows, is to delete all the addresses under the user. There is no choice but to delete all.
So you need to be aware of it in real development.

2 above we talked about set, it seems to use is not cool Ah, there is a trap, but there is no way, set is we use the most, and generally no one directly to the association string bar. But many people still will be unhappy, then hibernate also should ask everybody to get a bag (perhaps not on request, perhaps they also have some dissatisfaction, haha).
Let's take a look at its basic usage:
First we need to modify the set tag in the previous Tuser mapping file to:

<bag name= "Addresses" lazy= "true" table= "t_address" > 
  <key column= "user_id"/> <element type= 
  " String "column="/> 
</bag> 

and the corresponding entity class needs to modify the addresses type to the list type.
Here we re adding three additional addresses:

We run the test code:

public static void Main (string[] args) { 
   
  Configuration cfg = new Configuration (). Configure (); 
  Sessionfactory sessionfactory = Cfg.buildsessionfactory (); 
  Session session = Sessionfactory.opensession (); 
     
  TUser user = (TUser) session.load (tuser.class,new Integer (4)); 
     
  SYSTEM.OUT.PRINTLN ("Address Size:" +user.getaddresses (). Size ()); 
  Session.close (); 


Here we see:

Address Size:3 

This time we have all been able to see, whether or not to repeat.

But we have just seen a deletion of the problem, bag here is still unresolved, the need to use Idbag. We see a configuration file that requires the following modifications:

Idbag name= "Addresses" table= "t_address" lazy= "true" > 
  <collection-id type= "int" column= "id" > 
    < Generator class= "Identity"/> 
  </collection-id> 
  <key column= "user_id"/> <element 
  type = "string" column= "Address"/> 
</idbag> 

We see it's only a bag more than a collection-id. Indicates the record number to be deleted.
When we rerun the deleted code:

TUser user = (TUser) session.load (tuser.class,new Integer (4)); 
   
Transaction tx = Session.begintransaction (); 
Object obj = user.getaddresses (). iterator (). Next (); 
User.getaddresses (). Remove (obj); 
     
Tx.commit (); 

We see the output statement as:

Hibernate:delete from t_address where id=? 

This is not done by user_id to delete, but based on the t_address ID to delete, which means that it really deletes the record we need to delete.
We see the database, and now the record is:

We have deleted the first record, and we are right.

3 look at the above two methods, we take a look at the map, which with the top two of the biggest difference is the key value of the corresponding. Look directly at the code, straight point:
First, we need to modify the configuration file:

<map name= "Addresses" table= "t_address" lazy= "true" > 
  <key column= "user_id"/> <index "type=" 
  String "column=" type "/> 
  <element type=" string "column=" Address "/> 
</map> 

The biggest difference between it and the previous two is that there is a index, which is equivalent to the key of our map in Java, through which we take out the corresponding records. Remember, after you change the corresponding entity class, you need to change the type of addresses attribute to map.
Look at the data in the database:

Here we see two office and one home, so which office do you take?
Don't worry, we'll run through the test code and we'll know:

TUser user = (TUser) session.load (tuser.class,new Integer (4)); 
   
System.out.println (User.getaddresses (). Get ("Home"); 
System.out.println (User.getaddresses (). Get ("office"); 
Shanwei 
Shanghai 

Yes, as it turns out, we're getting the back one, which, like the map principle, will overwrite the previous values (if they are the same key).
Map is relatively simple, quite the first two.

4 The last one let's take a look at the list. The list is different from the previous several and is different in that it can be sorted.
Let's take a look at how it is implemented:
First, we'll revise the mapping file:

<list name= "Addresses" table= "t_address" lazy= "true" > 
  <key column= "user_id"/> <index "type=" 
  String "column=" idx "/> 
  <element type=" string "column=" Address "/> 
</list> 

It is similar to the configuration of the map, but the properties of the index are not the same, the index in the map is the key to get the value, and the list index is sorted.
We look at the database:

We set three values in the order of 0,1,2.
Here we run the code to change the value of the 0,2:

TUser user = (TUser) session.load (tuser.class,new Integer (4)); 
   
Transaction tx = Session.begintransaction (); 
Object obj1 = user.getaddresses (). get (0); 
Object obj2 = user.getaddresses (). get (2); 
     
User.getaddresses (). Set (0,OBJ2); 
User.getaddresses (). Set (2,OBJ1); 
     
Tx.commit (); 

We see the results:

We see that the 0,2 has been switched, of course, this is only the replacement of the IDX value. But this has basically achieved the function of sorting.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.