How to inject code at runtime in Java?

javassist example


Its been never easy for me to believe that you can inject code into existing method without changing its original code but this can also happens using library javassist.

javassist
Javassist (Java Programming Assistant) allows you to manipulate bytecode. It enables Java programs to define a new class at runtime and to modify a class file when the JVM loads it. Read more about plug-in on http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/.

Shigeru Chiba originally created this library now its sub project of Jboss organization. You can read more about author on his blog http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/site/.

Source code background
We created two class files 1. SampleCodeJavassist and 2. CommonUtil under package javaQuery.javassist. You can have your own package name.

Source Code
package javaQuery.javassist;

public class CommonUtil {
    public void printToConsole() {
        System.out.println("javaQuery");
    }
}
/**
 * @author javaQuery
 */
package javaQuery.javassist;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;

public class SampleCodeJavassist {
    public static void main(String[] args) throws Exception {
        /* Create object of ClassPool */
        ClassPool objClassPool = ClassPool.getDefault();
        /**
         * Create an object of CtClass.
         * Get the instance of class you want to inject the code.
         * Be careful while accessing the class. You have to specify whole the package name.
         */
        CtClass objCtClass = objClassPool.get("javaQuery.javassist.CommonUtil");
        /**
         * Create an object of CtMethod.
         * Get the method where you want to inject the code.
         */
        CtMethod objCtMethod = objCtClass.getDeclaredMethod("printToConsole");
        /* Inject the code at the begging of the method */
        objCtMethod.insertBefore("{ System.out.println(\"Hello World! at the beggining of method [Runtime from Test class]\"); }");
        /* Inject the code at the end of the method */
        objCtMethod.insertAfter("{ System.out.println(\"Hello World! at the end of method [Runtime from Test class]\"); }");
        /* Create an object of Class */
        Class objClass = objCtClass.toClass();
        /* Create an instance of CommonUtil class using objClass */
        CommonUtil objCommonUtil = (CommonUtil)objClass.newInstance();
        /* Execute method printToConsole */
        objCommonUtil.printToConsole();
    }
}

//output
Hello World! at the beggining of method [Runtime from Test class]
javaQuery
Hello World! at the end of method [Runtime from Test class]
This article is just to give you basic information of plug-in. Read more about plug-in on official website http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/.

What is the difference between str.equals(''Vicky'') and ''Vicky''.equals(str) in Java?

javaQuery


String Comparison
Comparing one string value against another string value either matching same case or ignoring its case. Its much important that How you're comparing Strings.

Source Code
Lets consider following code...
public class CompareString {
    private String Firstname;
    public static void main(String[] args) {
        /* Create an Object of CompareString */
        CompareString objCompareString = new CompareString();
        /* Set null value for Firstname */
        objCompareString.setFirstname(null);
        /* Get value in local variable */
        String name = objCompareString.getFirstname();
        /**
         * Compare string
         * java.lang.NullPointerException will occur in this case
         */
        if (name.equals("Vicky")) {
            System.out.println("Fail");
        }

        /**
         * Compreare string
         * It will handle java.lang.NullPointerException without checking null
         */
        if ("Vicky".equals(name)) {
            System.out.println("Passed");
        }
    }

    /**
     * Getter of Firstname
     * @return 
     */
    public String getFirstname() {
        return Firstname;
    }

    /**
     * Setter of Firstname
     * @param Firstname 
     */
    public void setFirstname(String Firstname) {
        this.Firstname = Firstname;
    }
}

Case 1: name.equals("Vicky") Compare unknown value with known value.
We are comparing name(unknown) value with another string Vicky(known) value. name will be decided based on some database call, calling another method, etc... It may possible you get null value of name and possible chances of java.lang.NullPointerException or you have to check explicitly for null value of name.

Case 2: "Vicky".equals(name) Compare known value with unknown value.
We are comparing Vicky(known) value with another string name(unknown) value. Same way name will be decided based on some database call, calling another method, etc... But equals and equalsIgnoreCase method of String will handle the null value and you don't have to check explicitly for null value of name.


Why "Vicky".equals(name) Compare known value with unknown value handles null.
To understand the core logic I extracted code of equals and equalsIgnoreCase method from String class.
/* Original source code form String class */
public boolean equals(Object anObject) {
 if (this == anObject) {
     return true;
 }
 /* This condition handles null value */
 if (anObject instanceof String) {
     String anotherString = (String)anObject;
     int n = count;
     if (n == anotherString.count) {
  char v1[] = value;
  char v2[] = anotherString.value;
  int i = offset;
  int j = anotherString.offset;
  while (n-- != 0) {
      if (v1[i++] != v2[j++])
   return false;
  }
  return true;
     }
 }
 return false;
}
anObject instanceof String implemented as null instanceof String and because null is not instance of String so It'll return false.
/* Original source code form String class */
public boolean equalsIgnoreCase(String anotherString) {
 return (this == anotherString) ? true : (anotherString != null) && (anotherString.count == count) && regionMatches(true, 0, anotherString, 0, count);
}
(anotherString != null) handles null value.

Interview Question
This is one of the popular question asked in Interviews. Those who knows answer says...

Ordinary Answer: Comparing known value with unknown value handles null.
ExtraOrdinary Answer: Comparing known value with unknown value handles null because null is not instance of String in case of equals and in case of equalsIgnoreCase, it checks the null before comparison.

Conclusion:
Always compare known value with unknown value to handle the null and to avoid the java.lang.NullPointerException.

How to forward current Session in HttpURLConnection?

Server Room


HttpURLConnection
HttpURLConnection is helps to use HTTP-specific features. Each HttpURLConnection instance is used to make a single request however it can be shared by other instances at the server. The most common use of HttpURLConnection is to make HTTP connection with Cookies, CustomHeader, Set GET/POST Methods, etc...

I used HttpURLConnection to make HTTP call from Servlet, I also required current session to be forwarded to called Servlet. You may have your different scenario.

Source Code
try {
 /* ID of Session you want to forward */
 String sessionId = "";
 /* Reading response data */
 String inputLine = "";

 URL data = new URL("http://www.your-domain.com/your-page.jsp");
 /* comment below line in case of Proxy */
 HttpURLConnection con = (HttpURLConnection) data.openConnection();
 /* Forward current session in request */
 con.setRequestProperty("Cookie", "JSESSIONID=" + URLEncoder.encode(sessionId, "UTF-8"));
 /* Read webpage coontent */
 BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
 /* Read line by line */
 while ((inputLine = in.readLine()) != null) {
  System.out.println(inputLine);
 }
 /* close BufferedReader */
 in.close();
 /* close HttpURLConnection */
 con.disconnect();
} catch (Exception e) {
 e.printStackTrace();
}

How Session forwarded/passed in HttpURLConnection request?
Server access Cookies to get Session ID value. JSESSIONID cookie used by server to identify session. If Session ID is valid then server allows you to access that session. This is how it works.

I tested code with Apache Tomcat and JBoss and its working fine. I don't know about other web server but It should work because all web server uses common standards.

Java Documentation: http://docs.oracle.com/javase/7/docs/api/java/net/HttpURLConnection.html

How Hibernate interpret Order of JOIN on a Table?

Hibernate Logo


Hibernate is one of the greatest framework to interact with database but every framework has its own advantages and disadvantages. Haphazard use of Hibernate may slower your application and you'll face major performance issues.

"Hibernate ain't important than database, you should care How Hibernate execute queries against database"

I've prepared sample mapping file to join two table "vehicle_master" and "profile_master" (It may not make sense but this is just an example so just ignore it).
/* user.hbm.xml */
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
  <class name="javaQuery.hibernate.User" table="user_master">
    <id name="id" type="int">
      <column name="id"/>
      <generator class="assigned"/>
    </id>
    <property name="Username" type="java.lang.String">
      <column name="user_name"/>
    </property>
    <property name="Email" type="java.lang.String">
      <column name="email"/>
    </property>
    <list cascade="refresh" name="listVehicle" table="user_vehicle_map">
      <key column="user_id"/>
      <index column="idx" type="integer"/>
      <many-to-many class="javaQuery.hibernate.Vehicle" column="vehicle_id"/>
    </list>
    <many-to-one name="Profile" class="javaQuery.hibernate.Profile" column="profile_id" unique="true" not-null="true" />
  </class>
</hibernate-mapping>

Execute following criteria to get SQL query and lets see "In which order Hibernate interpret your join".
/* Simple Criteria to load user with its vehicles and profile */
Criteria criteria = session.createCriteria(User.class);
criteria.setFetchMode("listVehicle", FetchMode.JOIN);
criteria.setFetchMode("Profile", FetchMode.JOIN);
criteria.list();

Above criteria will generate following SQL as we know it.
SELECT *
FROM   user_master this_
LEFT OUTER JOIN user_vehicle_map listvehicl2_
            ON this_.id = listvehicl2_.user_id
LEFT OUTER JOIN vehicle_master vehicle3_
            ON listvehicl2_.vehicle_id = vehicle3_.id
INNER JOIN profile_master profile4_
       ON this_.profile_id = profile4_.id

Myth
Developer thinks that JOIN on vehicle table took first place in SQL query because we have vehicle table at the first position in Criteria but have you ever tried changing position in Criteria? Lets see what happen if we change position in Criteria. After executing following code you'll get the same SQL query generated by first code.
/* Position of JOIN changed in criteria */
Criteria criteria = session.createCriteria(User.class);
criteria.setFetchMode("Profile", FetchMode.JOIN);
criteria.setFetchMode("listVehicle", FetchMode.JOIN);        
criteria.list();

Why didn't Hibernate change order of JOIN?
Well so far you are living with wrong assumption about How order of JOIN take place in hibernate. Its not the Criteria used by Hibernate to interpret order of JOIN on table. Its the Hibernate Mapping (hbm.xml) file. So if you want to change order of JOIN on table, you'll have to change order in your Hibernate Mapping (hbm.xml) file.

Order changed in Hibernate Mapping file. Compare first and second user.hbm.xml file for Vehicle and Profile.
/* user.hbm.xml */
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
  <class name="javaQuery.hibernate.User" table="user_master">
    <id name="id" type="int">
      <column name="id"/>
      <generator class="assigned"/>
    </id>
    <property name="Username" type="java.lang.String">
      <column name="user_name"/>
    </property>
    <property name="Email" type="java.lang.String">
      <column name="email"/>
    </property>
    <many-to-one name="Profile" class="javaQuery.hibernate.Profile" column="profile_id" unique="true" not-null="true" />
    <list cascade="refresh" name="listVehicle" table="user_vehicle_map">
      <key column="user_id"/>
      <index column="idx" type="integer"/>
      <many-to-many class="javaQuery.hibernate.Vehicle" column="vehicle_id"/>
    </list>
  </class>
</hibernate-mapping>

Now this hibernate mapping file will generate following SQL query not matter what order you've in your Criteria.
SELECT *
FROM   user_master this_
INNER JOIN profile_master profile2_
       ON this_.profile_id = profile2_.id
LEFT OUTER JOIN user_vehicle_map listvehicl3_
            ON this_.id = listvehicl3_.user_id
LEFT OUTER JOIN vehicle_master vehicle4_
            ON listvehicl3_.vehicle_id = vehicle4_.id 

Why ORDER of JOIN is so important?
You'll get same result in both the queries. However JOIN on table in wrong order may cause performance issue at Database. After all Database have to filter your data based on your joins. This is sample query and will not create major impact because of order of JOIN but in real time application we have lots of joins on table and at that time ORDDER of JOIN does matter. Contact your Database Administrator to understand this performance issue for JOINs.

When Hibernate uses INNER JOIN?

Hibernate Logo

After years of experience working around Hibernate there are very few people actually knows "When Hibernate Uses INNER JOIN". I'm one of 'em till today. Today I drilled further and found 3 cases where Hibernate uses INNER JOIN.

1. not-null attribute
When you specify attribute not-null = "true" in hbm.xml for particular column which used for table joining, It will use INNER JOIN no matter you specified FetchMode.JOIN in criteria.
/* Having not-null = "true" in hbm file, It'll override following FetchMode.JOIN */
criteria.setFetchMode("user", FetchMode.JOIN);

2. createAlias
When you create an alias of table, Hibernate will automatically uses INNER JOIN. Its default setting of hibernate.
criteria.createAlias("user", "user");

3. CriteriaSpecification.INNER_JOIN
Well you can ignore CriteriaSpecification.INNER_JOIN, as it can be used with createAlias. And when you use createAlias hibernate will automatically use INNER JOIN but this is just for the sake of your knowledge.
criteria.createAlias("user", "user", CriteriaSpecification.INNER_JOIN);

Note: If I'm missing any other way let's all know about it. Use comment box below.

How to change collation_database value in MySQL?

collation_database

A collation is a set of rules for comparing characters in a character set.
Read more about Character Sets and Collations in General.

How to check database collation character set in MySQL?
Execute following query to know the collation character set of current database.Currently its 'utf8_general_ci'.
SHOW VARIABLES LIKE '%collation_database%';
Variable_name value Value
collation_database utf8_general_ci


How to change database collation character set in MySQL?
We need to alter the database with new collation character set. We will change it to 'utf8_unicode_ci', change character set as per your requirement.
ALTER DATABASE inventory COLLATE utf8_unicode_ci;
Now lets check the collation character set again by executing same query.
SHOW VARIABLES LIKE '%collation_database%';
Variable_name value Value
collation_database utf8_unicode_ci


How to change character_set_database value in MySQL?

character_set_database + MySQL

MySQL is highly configurable database. It support different character set at Database level, Table level and Column level as well. Sometime it gets worse when you provide so many options.

We were facing an issue because of mixed character set at different level in MySQL. I've tried to change configuration [my.cnf in Linux and my.ini in Windows] file of MySQL but didn't work. I've searched to change value of 'character_set_database' but no one explained to the point. After many try and error I figured out solution.

How to check database character set in MySQL?
Execute following query to know the character set of current database. Currently its 'latin1'.
SHOW VARIABLES LIKE '%character_set_database%';
Variable_name value Value
character_set_database latin1


How to change database character set in MySQL?
We need to alter the database with new character set. We will change it to 'utf8', change character set as per your requirement.
ALTER DATABASE inventory CHARACTER SET utf8;
Now lets check the character set again by executing same query.
SHOW VARIABLES LIKE '%character_set_database%';
Variable_name value Value
character_set_database utf8

Reorganize or Rebuild Indexes to remove fragmentation on database table

Fragmentation
Fragmentation occurs when you perform any INSERTION, UPDATION or DELETION operation against table. Over the time this operation cause to data become scattered in database. Heavily fragmented indexes can degrade query performance and cause your application to respond very slowly.

Note: I'm using sample database(AdventureWorks2008R2) from Microsoft. Change database name and table name where required.

Finding Fragmentation On Table-Index
Execute following query to determine fragmentation on particular table of database.
SELECT ind.name, phy.avg_fragmentation_in_percent, phy.fragment_count, phy.avg_fragment_size_in_pages
FROM sys.dm_db_index_physical_stats(DB_ID(N'AdventureWorks2008R2'), OBJECT_ID(N'HumanResources.Employee'), NULL, NULL, NULL) AS phy
JOIN sys.indexes AS ind
ON phy.object_id = ind.object_id
AND phy.index_id = ind.index_id
Index + REBUILD + REORGANIZE + Detecting Fragmentation + Microsoft SQL Server

As you can see in Image that index 'AK_Employee_LoginID' is Heavily fragmented. It will lead to lower performance of your database.

Column Description
avg_fragmentation_in_percent The percent of logical fragmentation (out-of-order pages in the index).
fragment_count The number of fragments (physically consecutive leaf pages) in the index.
avg_fragment_size_in_pages Average number of pages in one fragment in an index.
Source: http://technet.microsoft.com/

REORGANIZE Index or REBUILD Index?

avg_fragmentation_in_percent value Operation
> 5% and < = 30% ALTER INDEX REORGANIZE
> 30% ALTER INDEX REBUILD WITH (ONLINE = ON)*

What is Index Reorganize?
Database will Reorganize data pages on an index. Reorganizing an index is always executed with online. It means when you perform Reorganize operation on an Index, Database will keep the old index value to serve the incoming queries. When its completed, it'll drop the old index data.

What is Index Rebuild?
Database will drop the current index and create an index from scratch. It comes with two option online and offline. As I said online option will keep the data of old index to serve incoming queries until it completes the rebuild operation. Offline option will drop the old index data right away and create index again, index won't be available until it completes the rebuild operation.

To reorganize an index
ALTER INDEX IX_Employee_OrganizationalLevel_OrganizationalNode ON HumanResources.Employee
REORGANIZE;
To reorganize all indexes in a table
ALTER INDEX ALL ON HumanResources.Employee
REORGANIZE;
To rebuild an index
ALTER INDEX AK_Employee_LoginID ON HumanResources.Employee
REBUILD;
To rebuild all indexes in a table
ALTER INDEX ALL ON HumanResources.Employee
REBUILD WITH (FILLFACTOR = 80, SORT_IN_TEMPDB = ON,
              STATISTICS_NORECOMPUTE = ON);
Warning: This is part of database maintenance so please be carefully while you are dealing with live database server. I'd suggest perform this task under maintenance hours.

Microsoft SQL Server Index: Warning! The maximum key length is 900 bytes.

Today I was creating an Index on columns and got warning from SQL server. I never know that Microsoft SQL Server has put Maximum size limitation on Index key column. I prefer to write SQL script rather design mode of SQL Server Studio. I got warning message in console as follow...

Warning! The maximum key length is 900 bytes. The index 'IndxNc_index_master__MultiCol01' has maximum length of 1000 bytes. For some combination of large values, the insert/update operation will fail.

I did Google for more information and read few articles and also SQL Server library articles. Lets understand warning message with example.

Step 1: First create table. Lets assume below table for the sake of example.
CREATE TABLE [dbo].[index_master](
 [id] [bigint] IDENTITY(1,1) NOT NULL,
 [indexCol1] [nvarchar](450) NULL,
 [indexCol2] [bigint] NULL,
 [indexCol3] [int] NULL,
 [indexCol4] [varchar](442) NULL,
 [indexCol5] [varchar](450) NULL
) ON [PRIMARY]

Step 2: Find out individual column size in bytes.
SELECT name, max_length as size_in_bytes
FROM sys.columns
WHERE OBJECT_NAME(object_id) = 'index_master'

Warning! The maximum key length is 900 bytes


Step 3: Create an index on indexCol2 [8] + indexCol3 [4] + indexCol4 [442] + indexCol5 [450] = 904 bytes.
CREATE NONCLUSTERED INDEX [IndxNc_index_master__MultiCol01] ON [dbo].[index_master] 
(
 [indexCol3] ASC,
 [indexCol4] ASC,
 [indexCol5] ASC,
 [indexCol2] ASC
)WITH (PAD_INDEX  = ON, FILLFACTOR = 80)

/* If you create an index using above script, it'll gives you warning as follow */
/* Warning! The maximum key length is 900 bytes. The index 'IndxNc_index_master__MultiCol01' has maximum length of 904 bytes. For some combination of large values, the insert/update operation will fail.*/

/* If you create an index using SQL Studio design mode, it'll gives you warning as follow */
/* Adding the selected columns will result in an index key with a maximum length of 904 bytes.  The maximum permissible index length is 900 bytes. INSERT and UPDATE operations fail if the combined value of the key columns exceeds 900 bytes. */

Step 4: Lets try to insert record with random data to check what happens if you try cross the limit of 900 bytes.
INSERT INTO index_master values(
'indexCol1',
1234567891012312312,
12345,
'12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218',
'123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186');

It'll throw an error as follow...
Operation failed. The index entry of length 902 bytes for the index 'IndxNc_index_master__MultiCol01' exceeds the maximum length of 900 bytes.

Notes
- If a table column is a Unicode data type such as nchar or nvarchar, then column size in bytes is two times the number of characters specified in the CREATE TABLE statement. Check indexCol1.
- If you have index that exceed the 900 bytes, It'll allow insert/update until unless total sum of key columns not more than 900 bytes. In above insert query cut down long string into small and you'll be able to insert the record without any error.
- You can add big columns in index using INCLUDE clause [except text, ntext, and image datatype columns], SQL Server will not consider included columns for 900 bytes.

Hibernate and Database (Microsoft SQL Server) Indexes

Hibernate logo

Hibernate
Hibernate is an Object Relational Mapping (ORM) library used in java. This framework used to map relational database into Object Oriented domain model. This framework can handle small and enterprise level application both. Hibernate uses Prepared Statement (pre-compiled query) for data retrieval until unless you write hard coded native queries.


Database Index
A database index is a data structure that improves the speed of data retrieval operations on a database table at the minimal cost of additional writes and little more additional space to maintain a restricted set of selected data.


Hibernate and Microsoft SQL Server Index
Today we will intercept the interaction of Hibernate and SQL Server Index. We will see How actually hibernate queries stored in database.

In the following example we have table user_master. It has column user_name with datatype varchar(100). We will create an Index on column user_name and test it against Hibernate.

Step 1: Create an Index on column user_name.
Note: Index will be used only when table holds huge number of records minimum 1500-2000 records.
CREATE NONCLUSTERED INDEX [IXNc_user_master__user_name] ON [dbo].[user_master] 
(
 [user_name] ASC
)WITH (PAD_INDEX  = ON, FILLFACTOR = 80)

Step 2: Executing simple select query in SQL Server Studio.
/* Press Ctrl + M or enable execution plan in SQL Studio. */
/* After execution of query you can see the execution plan, that shows Index Seek(Search in index) of 'IXNc_user_master__user_name' */
SELECT * FROM user_master WHERE user_name = 'vicky_thakor'

Step 3: We will verify that index used for seek (search) or scan. Seek cost is very low but scan cost lot more than regular. Execute following query that shows SEEK and SCAN count on Index and save/remember the details for reference. (*Change database name and table name.)
SELECT DISTINCT OBJECT_NAME(sis.OBJECT_ID) TableName,
  si.name AS IndexName, sc.Name AS ColumnName, sic.Index_ID, sis.user_seeks, sis.user_scans, sis.user_lookups, sis.user_updates
FROM sys.dm_db_index_usage_stats sis
INNER JOIN sys.indexes si 
 ON sis.OBJECT_ID = si.OBJECT_ID AND sis.Index_ID = si.Index_ID
INNER JOIN sys.index_columns sic 
 ON sis.OBJECT_ID = sic.OBJECT_ID AND sic.Index_ID = si.Index_ID
INNER JOIN sys.columns sc 
 ON sis.OBJECT_ID = sc.OBJECT_ID AND sic.Column_ID = sc.Column_ID
WHERE sis.Database_ID = DB_ID('database_name') AND sis.OBJECT_ID = OBJECT_ID('user_master');

Step 4: Now clear all available Prepared Statements from SQL Server cache.
DBCC FREEPROCCACHE
DBCC DROPCLEANBUFFERS

Step 5: Execute same query using Hibernate Criteria
Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.eq("Username", "vicky_thakor"));        
criteria.list();

Step 6: Execute following query to check what query Hibernate generated to fetch the data.
SELECT usecounts, text 
FROM sys.dm_exec_cached_plans
CROSS APPLY sys.dm_exec_sql_text(plan_handle)
WHERE cacheobjtype != 'Parse Tree'

/* Hibernate generated following query */
(@P0 nvarchar(4000))select this_.uid as uid0_0_, this_.Firstname as Firstname0_0_, this_.Lastname as Lastname0_0_, this_.user_name as user4_0_0_ from user_master this_ where this_.user_name= @P0

Hibernate and Microsoft SQL Server database indices

Important: We have column user_name with datatype varchar but hibernate fetching data using nvarchar datatype.

Step 7: Execute Step 3 to check index is used with SEEK or SCAN. You will find that index is scanned and that cost a lot.


Cross-check
Lets check how database act with different datatype for index. You are requested to turn on execution plan setting in Microsoft SQL Server [Read more: Execution Plan in MSSQL Server]. We will use Prepared Statement at database level with both datatype.
/* Execute following query which leads to Index Scan (Check attached image) */
EXECUTE sp_executesql
@statement = N'SELECT * FROM user_master WHERE user_name = @P0',
@parameters = N'@P0 nvarchar(4000)',
@P0 = 'vicky_thakor'

/* Execute following query which leads to Index Seek (Check attached image) */
EXECUTE sp_executesql
@statement = N'SELECT * FROM user_master WHERE user_name = @P0',
@parameters = N'@P0 varchar(4000)',
@P0 = 'vicky_thakor'

Hibernate and Microsoft SQL Server database indices

Issue
Hibernate used nvarchar to support Unicode characters and we have column with varchar datatype. Database always upgrade lower datatype to higher datatype to eliminate data lose. Datatype conversion leads to index scan rather index seek.


Solution

You are suggested to change your datatype from varchar to nvarchar. If you are not interested in datatype change I have another solution for it.

Add parameter called sendStringParametersAsUnicode in your connection string. It will force hibernate to use varchar instead nvarchar.
<property name="hibernate.connection.url">jdbc:jtds:sqlserver://127.0.0.1:1433/javaQuery;sendStringParametersAsUnicode=false</property>

Conclusion
Its not only the hibernate use nvarchar, You should check all other framework you are working with. Indexes are meant to increase the performance but this intermediate framework and poor database knowledge leads to low performance of application.