Discover hibernate bugs and gain an in-depth understanding of Properties

Source: Internet
Author: User

In the afternoon, check the Jobs completed by Wang zeyou. Wang zeyou uses drivermanagerconnectionprovider in hibernate to obtain database connections. Because drivermanagerconnectionprovider does not provide the constructor or setter method to receive configuration information, instead, you can only call the configure (properties) method to set its configuration information. In order to be able to use spring, he uses the properties object of the parameter accepted by the confiure method as a bean object of spring (this is a bit of excessive use of spring, and their reasons are fun and deepen the application of spring ), I did not expect this use to have a very strange problem:
The following is the spring configuration file:
<? XML version = "1.0" encoding = "UTF-8"?>
<! Doctype beans public "-// spring // DTD bean // en" "http://www.springframework.org/dtd/spring-beans.dtd">

<Beans>
<Bean id = "providerprops" class = "Java. util. properties">
<Constructor-Arg>
<Props>
<Prop key = "hibernate. Connection. driver_class"> com. MySQL. JDBC. Driver </prop>
<Prop key = "hibernate. Connection. url"> JDBC: mysql: // itcast </prop>
<Prop key = "hibernate. Connection. username"> root </prop>
<Prop key = "hibernate. Connection. Password"> 1234 </prop>
</Props>
</Constructor-Arg>
</Bean>
</Beans>
The above configuration is equivalent to the following source code:
Properties providerprops = new properties ();
Providerprops. setproperty ("hibernate. Connection. driver_class", "com. MySQL. JDBC. Driver ");
Providerprops. setproperty ("hibernate. Connection. url", "JDBC: mysql: // itcast ");
Providerprops. setproperty ("hibernate. Connection. username", "root ");
Providerprops. setproperty ("hibernate. Connection. Password", "1234 ");
Properties props = new properties (providerprops );
Create a properties object first, and then use the properties object as the parameter of the constructor of another properties object to test the other properties object.
The call code snippets in the source program are as follows:
Drivermanagerconnectionprovider DMCP = new drivermanagerconnectionprovider ();
Applicationcontext context = new classpathxmlapplicationcontext ("/applicationcontext. xml ");
Props = (properties) Context. getbean ("providerprops ");
DMCP. Configure (props );
Connection Cn = DMCP. getconnection ();
....
When the program is running, it always reports a connection failure to the database. The cause of the failure reported by MySQL is that the login account password is empty. They changed the above program code to the following form:
Drivermanagerconnectionprovider DMCP = new drivermanagerconnectionprovider ();
Applicationcontext context = new classpathxmlapplicationcontext ("/applicationcontext. xml ");
Props = (properties) Context. getbean ("providerprops ");
DMCP. Configure (props );
// Added the following statement.
Props. setproperty ("hibernate. Connection. Password", props. getproperty ("hibernate. Connection. Password "));
Connection Cn = DMCP. getconnection ();
....
Run again and the result will be normal. The modified code only sets the Password attribute again, and the setting value is extracted from the original props object. It seems that there is no difference if this statement is not added? The content in the props object is printed before and after the new statement, and the results are the same.
Drivermanagerconnectionprovider DMCP = new drivermanagerconnectionprovider ();
Applicationcontext context = new classpathxmlapplicationcontext ("/applicationcontext. xml ");
Props = (properties) Context. getbean ("providerprops ");
DMCP. Configure (props );
Props. List (system. Out); // The result is exactly the same as that shown in the following list.
// Added the following statement.
Props. setproperty ("hibernate. Connection. Password", props. getproperty ("hibernate. Connection. Password "));
Props. List (system. Out); // The result is exactly the same as that shown in the list above.
Connection Cn = DMCP. getconnection ();
....
This is really weird !!! Why can't I understand it!
So I opened the JDK help document and carefully read the help information of the properties class. I noticed the following section:
A property list can contain in another property list as its "defaults"; this second property list is searched if the property key is not found in the original property list.
This probably means that a properties object can contain another properties object as its default properties object. When we retrieve an attribute from the properties object, first, search for the properties object itself. If it cannot be found, search for it from another default properties object contained in it. This is a detail that I did not pay attention to before, and our above application seems to have something to do with this detail. We also constructed a properties object first, then it is set to the internal default properties object of another properties object, although the internal default properties object contains a "hibernate. connection. password, but it is not the property of the properties object. We call setproperty ("hibernate. connection. password ",...) method, so that the external properties object and its internal default properties object have a "hibernate. connection. password "attribute. Obviously, after we call the setproperty method, the internal data of the properties object is indeed changed, instead of It seems that the problem may occur in this detail. Therefore, I started to track and debug this program under eclipse and tracked the connectionproviderfacatory. getconnectionproperties method. The code for this method is as follows:
Public static properties getconnectionproperties (properties Properties ){

Iterator iter = properties. keyset (). iterator ();
Properties result = new properties ();
While (ITER. hasnext ()){
String prop = (string) ITER. Next ();
If (prop. indexof (environment. connection_prefix)>-1 &&! Special_properties.contains (PROP )){
Result. setproperty (
Prop. substring (environment. connection_prefix.length () + 1 ),
Properties. getproperty (PROP)
);
}
}
String username = properties. getproperty (environment. User );
If (username! = NULL) result. setproperty ("user", username );
Return result;
}
This method extracts database connection information-related attributes from a properties object and generates a new properties object, the newly generated properties object does not contain the "password" attribute, and the problem occurs in this method. Based on the recognition of the previous properties object, the above Code is analyzed, and the conjecture is properties. the keyword set returned by the keyset () method only contains its own keywords, but does not contain the keywords of its internal default properties object. Therefore, I wrote the following code to prove my conjecture:
Properties props1 = new properties ();
Props1.setproperty ("hibernate. Connection. username", "root ");
Props1.setproperty ("hibernate. Connection. Password", "1234 ");
Properties props = new properties (props1 );
Props. setproperty ("hibernate. Connection. username", "root ");
Enumeration E = props. Keys ();
While (E. hasmoreelements ())
{
System. Out. println (string) E. nextelement ());
}
Only the keywords set by the props. setproperty method are printed, but the keywords contained in props1 are not printed. So far, I have completely determined the cause of the problem. It seems that hibernate developers may not pay attention to the details of the properties class, thus leaving such a bug for hibernate.

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.