Wednesday, December 22, 2010
How does batch update improve performance vs multiple updates?
When I had technical discussion with my friend, he was asking me the question "How does batch update improve performance?". I spent sometime to find out an answer for this question. Hope this will find useful for others.
My friend thinks that batch update will update database in asynchronously, means java will hand over the control to Oracle to execute the update statement and just get back control to process next set of data. Meanwhile Oracle will process those update statements. His assumption is wrong.
When we do multiple updates using for loop in java, there is context switching happens between Java & Oracle to execute each update statement. But, when we do batch update in Java environment we collect all update statements & switch to oracle to execute all statements at once. When we avoid this context switching, we gain more performance.
Monday, June 22, 2009
Difference between get & load in hibernate
In this post, we will look into the main difference between load method & get method in hibernate session.
Order order = (Order)session.get(Order.class, 1L);
When the above line is executed within the same session then we will end up in only one database query. ie. for first time before executing query, Order object with id = 1 will be searched in the session. If it finds the object then there wont be database hit to get order object with identity 1. Hence calling the get method twice or more with identity 1 in same session will end up with only one database hit. Moreover if the order object with id = 1 is not find in the session or database then order will be null.
Order order = (Order)session.load(Order.class, 1L);
The load method will never hit the database instead it will try to fetch an order object with identity = 1 from the session cache and if it finds the object then the same will return else it will create an proxy object with identity = 1 and return to the caller. Hence how many times we call the above line in the same session, it will end up in creating only one order object with identity 1. When we try to access the property of order object then there will be dataase hit to fecth an order object. If there is no order object with id =1 then we will end up with Object Not Found Exception. If we are trying to access an order object for first time outside the session then we will end up with Lazy Initialization Exception.
We should use get method for checking the object existence. If we are very sure that we will not access the property and the order object with id =1 is available in database then we can use the load method to create a proxy and the same object can be attached to any object, where the association is required to persist the object with relationship.
Order order = (Order)session.createQuery("from Order where id = 1").uniqueResult();
The number of times the above query executed the same number of database hits will be. Even though the order object with = 1 is available in session, it will not be fetched from session cache. But, the order object will be synched in such a way that only one order object with id =1 will be available in the session.
Session sess = factory.openSession();
Transaction tx;
try {
tx = sess.beginTransaction();
//DB hit to fetch Order object with id =1
Order order1 = (Order)session.get(Order.class, 1L);
//Fetched from session cache, no DB hit
Order order2 = (Order)session.get(Order.class, 1L);
//Return true
System.out.println(order1.equals(order2));
//Return true
System.out.println(order1 == order2);
//No DB hit, display the order description
System.out.println(order1.getDescription());
System.out.println(order2.getDescription());
tx.commit();
}
catch (Exception e) {
if (tx!=null) tx.rollback();
throw e;
}
finally {
sess.close();
}
Session sess = factory.openSession();
Transaction tx;
try {
tx = sess.beginTransaction();
//Create a proxy of order object with id =1
Order order1 = (Order)session.load(Order.class, 1L);
//Fetched proxy from session cache
Order order2 = (Order)session.load(Order.class, 1L);
//Return true
System.out.println(order1.equals(order2));
//Return true
System.out.println(order1 == order2);
//DB hit to display the order description
System.out.println(order1.getDescription());
//No DB hit
System.out.println(order2.getDescription());
//Create a proxy of order object with id =-1
Order order3 = (Order)session.load(Order.class, -1L);
//Fetched proxy from session cache
Order order4 = (Order)session.load(Order.class, 1L);
//Return true
System.out.println(order3.equals(order4));
//Return true
System.out.println(order3 == order4);
//DB hit to display the order description, since it is invaild id... throws
//ObjectNotFoundException
System.out.println(order3.getDescription());
//Will not reach here
System.out.println(order2.getDescription());
tx.commit();
}
catch (Exception e) {
if (tx!=null) tx.rollback();
throw e;
}
finally {
sess.close();
}
Thursday, January 8, 2009
Spring Security Part 1 (Intro to Spring Security)
When one of my project requires well defined authentication & role authorization, I started looking into various options. When I come across Spring Security (formerly ACEGI) , I was impressed with the way we can easily plug in our existing authentication with Spring security framework.
This series of article is intended to explain usage of spring security with my knowledge. Any comments and suggestions are welcome.
This part I is aimed to give the basics of Spring security framework and authentication mechanism provided by Spring security.
Instead of taking u to the theory, let me start with a simple use case and slowly inject more complex scenarios in the later part of the article.
Use Case: User is entering their credentials to login into the web application.
Typically, the developer would have written their code to handle authentication for any web application. As developer doesn't know how much extra effort will take to understand Spring security so, developer may hesitate to change to Spring security's authentication. We will see how much change required to migrate to Spring based authentication.
The user would have written login page with username and password as field(minimum credentials) and a submit button to login to the application i.e taking them to thier Home page.
Spring Basics
To understand or usage of Spring based authentication, the developers are required to know the following components or Spring classes
1. FilterChainProxy
2. AuthenticationProcessingFilter
3. AuthenticationManager
4. AuthenticationProvider
5. UserDetailsService
6. UserDetails
7. SecurityContextHolder
8. SecurityContext
We will discuss about each & every class and its importance in terms of integration with our code.
FilterChainProxy: As the name suggest, this proxy class receives any web request and apply list of filters on the incoming request.
AuthenticationProcessingFilter: Whenever the web request comes to this class with particular URL then this class have responsibilty to do the authentication.
AuthenticationManager: The implemented have responsibility to call list of providers for creating authenticated Authentication object.
AuthenticationProvider: The implemented class have responsibility to create Authentication object with the help of UserDetails object.
UserDetailsService: The implemented class will know how to get the UserDetails object, which will useful to create Authentication object.
UserDetails: The implemented will have details about the logged in user. The details are their granted authorities, whether their account expired, locked, user name, password etc. Most of the time the UserDetails can be their domain object itself.
SecurityContextHolder: The singleton static class to hold security context object.
SecurityContext: This object will be created for each logged in user and holds the Authentication object.
Now, we armed with basic knowledge about the required classes involved in the process of Spring based authentication. We will step back ourself to see the simple use case.
The following are the required changes in your code to integrate with Spring based authentication.
1. Typically the web.xml will have the following filter entry so that the request will undergo through all configured filters.
< filter >
< filter-name >
filterChainProxy
</ filter-name >
< filter-class >
org.springframework.web.filter.DelegatingFilterProxy
</ filter-class >
</ filter >
< filter-mapping >
< filter-name > filterChainProxy </filter-name >
< url-pattern > /* </url-pattern >
< /filter-mapping >
Based on the above entry, whenever the web container receives request, the request will be handed over to FilterChainProxy to apply list of filters.
2. Add the below entry in your service context.xml
< bean id="filterChainProxy" class="org.springframework.security.util.FilterChainProxy">
< security:filter-chain-map path-type="ant">
< security:filter-chain pattern="/login**" filters="none"/>
< security:filter-chain pattern="/**" filters="authenticationProcessingFilter"/>
< /security:filter-chain-map>
< /bean>
I have defined two pattern, one doesn't have any filters to apply and another has authenticationProcessingFilter. Whenever the URL pattern has login then it will not apply any filters and take the user to login page. Whenever other than login URL pattern is accessed then the authenticationProcessingFilter will be called.
3. Add the below entry for authenticationProcessingFilter in the service context.xml
< bean id="authenticationProcessingFilter"
class="org.springframework.security.ui.webapp.AuthenticationProcessingFilter">
< property name="authenticationManager" ref="authenticationManager" />
< property name="authenticationFailureUrl" value="/login.action" />
< property name="defaultTargetUrl" value="/home.action" />
< property name="filterProcessesUrl" value="authenticateUser"/>
< property name="passwordParameter" value="PASSWORD"/>
< property name="usernameParameter" value="USERNAME"/>
< /bean>
Whatever the field name defined in your JSP have to be replaced withe passwordParameter & usernameParameter properties values. The authentication processing filter will retrieve respective parameters from the request and use it for authentication. The property filterProcessesUrl should have the value as where we are submitting the user credentials. This property will be used to decide whether to call AuthenticationManager to create new Authentication object and set it in security context. i.e if the request URL is authenticateUser then the authentication will happen else the user will be taken to authenticationFailureUrl i.e to the login page in our example. If authentication is successful then the user will be taken to defaultTargetUrl i.e home page in our example.
4. Add the below entry for AuthenticationManager in service context.xml
< bean id="authenticationManager"
class="org.springframework.security.providers.ProviderManager">
< property name="providers">
< list>
< ref local="myAppAuthenticationProvider"/>
< /list>
< /property>
< /bean>
When the authentication processing filter decides to do authentication then authentication manager will be called, which in turn call the providers and create Authentication object.
5. Add the below entry for the provider in service context.xml
< bean id="myAppAuthenticationProvider"
class="com.app.MyAppAuthenticationProvider">
< property name="userDetailsService" ref="userDetailsService"/>
< /bean>
When the AuthenticationManager calls this provider, the call will be given to User details service to retrieve user details information.
6. Add the below entry for user details service and moreover this is the first class we are writing it with respect to authentication implementation.
< bean id="userDetailsService"
class="com.app.impl.security.UserDetailsServiceImpl">
< property name="userService" ref="userService"/>
< /bean>
Typically, we would have written User Service class to retrieve the user information i.e user domain object. Use the same class to retrieve the user details object.
7. Either change ur domain object to implement UserDetails interface provided by Spring class or write a wrapper, which implements user details interface and hold reference to user domain object.
When user provided credentials are failed then AuthenticationException will be thrown.
After authentication and if the user credentials are valid then the created Authentication object will be set into the SecurityContext.
To retrieve the user domain object in your code, the following lines of code is sufficient.
Object principal =
SecurityContextHolder.getSecurityContext().getAuthentication().getPrincipal();
User user = null; //Domain object
if(principal instanceof UserDetails){
user = (User) principal; //first case
//user = ((UserWrapper)principal).getUser(); Second case
}
Thats it about migrating non Spring based authentication to Spring based authentication.
Gist of the post: Eventhough we need to do more configuration and write a couple of classes i.e UserDetails, UserDetailsService & Wrapper. It is easy to migrate to Spring based authentication. We can define a seperate context.xml for implementing Spring based security.
In the next part, we can see a simplified configuration and authorization.
Subscribe to:
Comments (Atom)