If a loaf can full your appetite then why to order for two loafs and waste the other one. But to this people call them stereotype of miser that is wealthy and greedy, a man who lives intelligently in order to save and increase his treasure. Same thing I have seen while creating a table and columns and assigning the data-types and their sizes, if we can full fill the requirement of the data by providing the accurate or approximate size then it will not only increase the treasure(or in technical terms we used to call performance) but also we can reduce the risk which prevails in any application. If we can use tiny int and get our work done then why to use small int or simple int and burden the database and decrease the performance. Use the best data-type matching your requirement, if it is varchar don’t just define varchar, but if you know the size define it like varchar(20) or something else. Below are few data-types and the values they accommodate. I know this is the basic of but sometimes these basic things make a major difference. So when ever creating the tables BE MISER… and don’t BE SPENDTHRIFT

bigint

Integer data from -2^63 through 2^63-1

int

Integer data from -2^31 through 2^31 - 1

smallint

Integer data from -2^15 through 2^15 - 1

tinyint

Integer data from 0 through 255

bit

Integer data with either a 1 or 0 value

decimal

Fixed precision and scale numeric data from -10^38 +1 through 10^38 -1

numeric

Fixed precision and scale numeric data from -10^38 +1 through 10^38 -1

money

Monetary data values from -2^63 through 2^63 - 1

smallmoney

Monetary data values from -214,748.3648 through +214,748.3647

float

Floating precision number data from -1.79E + 308 through 1.79E + 308

real

Floating precision number data from -3.40E + 38 through 3.40E + 38

datetime

Date and time data from January 1, 1753, through December 31, 9999,with an accuracy of 3.33 milliseconds

smalldatetime

Date and time data from January 1, 1900, through June 6, 2079,with an accuracy of one minute

char

Fixed-length character data with a maximum length of 8,000 characters

varchar

Variable-length data with a maximum of 8,000 characters

text

Variable-length data with a maximum length of 2^31 - 1 characters

nchar

Fixed-length Unicode data with a maximum length of 4,000 characters

nvarchar

Variable-length Unicode data with a maximum length of 4,000 characters

ntext

Variable-length Unicode data with a maximum length of 2^30 - 1 characters

binary

Fixed-length binary data with a maximum length of 8,000 bytes

varbinary

Variable-length binary data with a maximum length of 8,000 bytes

image

Variable-length binary data with a maximum length of 2^31 - 1 bytes

timestamp

A database-wide unique number that gets updated every time a row gets updated

uniqueidentifier

A globally unique identifier

sql_variant

A data type that stores values of various data types,except text, ntext, timestamp, and sql_variant

varchar(max)

Maximum 1,073,741,824 characters

text

Maximum 2GB of text data

nvarchar(max)

Maximum 536,870,912 characters

ntext

Unicode data. Maximum 2GB of text data

Posted by sandeverma, filed under Uncategorized. Date: July 30, 2008, 6:22 pm | 4 Comments »

Hi all as I worked on setting up 4 to 5 servers, I thought its better to document the stuff so that I/developers can refer it, So I am documenting the step-by-step process for setting up the slicehost server for rails application work with nginx as a web server and mongrel as a rails application server.

Update

To update your system:

yum update

MySQL

to install mysql client and server apps

yum install mysql-server

The client package “mysql” will automatically be installed as a dependency.

Apache

yum install httpd

PHP5

To install php with soap, xml and mysql plugins:

yum install php php-soap php-xml php-mysql

some other php plugin utilities that are common:

yum install php-mbstring php-gd

Ruby

yum install ruby

Utilities

other useful utilities:

yum install nano wget elinks subversion vi

Nginx

install nginx web server:

yum install nginx

Mongrel Cluster

install mongrel_cluster:

gem install mongrel_cluster –include-dependencies

Setup your nginx configuration for your rails application and mongrel_cluster (proxy).

Below you found sample config file for nginx.conf (normally located in “/etc/nginx/conf/nginx.conf”)

user  deploy;
worker_processes  1;
error_log   logs/error.log debug;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
#pid        logs/nginx.pid;
events {
    worker_connections  1024;
}
http {
  include        conf/mime.types;
  default_type   application/octet-stream;
  sendfile        on;
  #tcp_nopush     on;
  keepalive_timeout  65;
  tcp_nodelay        on;
  gzip  on;
  gzip_min_length  1100;
  gzip_buffers     4 8k;
  gzip_types       text/plain;
  upstream mongrel {
    server 127.0.0.1:8000;
    server 127.0.0.1:8001;
  }
  server {
    listen       80;
    server_name  example.com;
    root /var/www/apps/example/current/public;
    index  index.html index.htm;
    location / {
      proxy_set_header  X-Real-IP  $remote_addr;
      proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_redirect false;
      if (-f $request_filename/index.html) {
        rewrite (.*) $1/index.html break;
      }
      if (-f $request_filename.html) {
        rewrite (.*) $1.html break;
      }
      if (!-f $request_filename) {
        proxy_pass http://mongrel;
        break;
      }
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
  }
}

Restart the nginx server:

/etc/init.d/nginx restart

Mongrel Configuration:

Now Go to the application directory and create a configuration for Mongrel:

mongrel_rails cluster::configure -e production -p 8000 -a 127.0.0.1 -N 2 -c /home/APP/production/APP/current

it will create the config/mongrel_cluster.yml file; basically you do not need to edit it.

You can test cluster with

To Start:

mongrel_rails cluster::start

To Stop:

mongrel_rails cluster::stop

To Restart:

mongrel_rails cluster::restart

Capistrano Configuration:

Then create a configuration for Capistrano:

cap –apply-to .

we need to modify the generated file config/deploy.rb:

require 'mongrel_cluster/recipes'

#you set the APP name with the cap command
set :application, "APP"
#a path to your repository
set :repository, "svn+ssh://USERNAME@SVN_SERVER/projects/#{application}/trunk"

role :web, "SERVER"
role :app, "SERVER"
role :db, "SERVER", :primary => true

#where to deploy (copy the files) on the server; I created a special user APP for the application (if you do not like it, replace the /home/#{application} part with your path
set :deploy_to, "/home/#{application}/production/#{application}"
set :mongrel_conf, "#{current_path}/config/mongrel_cluster.yml"
#if the server login name is different to the development computer login name; in my case the user name is the APP name
set :user, "APP"

Make necessary changes to the config/database.yml file.

Capistrano Deployment:

Create the basic structure on the server:

cap deploy:setup

For the first deployment you can use cold deploy:

cap cold_deploy

After that for next deployments you have to use:

cap deploy

You can also run migration from capistrano with:

cap deploy:migrate*

* Note: It wont work for me, it migrating to the previous release available in the releses folder, So I suggest you manually run migration on server.

That’s it, your server is ready to run.
Hope this documentation will be helpful to you, Enjoy ;-).

Posted by Bhushan Ahire, filed under Ruby On Rails. Date: July 29, 2008, 9:38 am | No Comments »

I am using google apps for my domain www.bhushangahire.com

For one of my rails application I am using this domain mail account setup for sending mails.
But I am not able to send the mail with the default smtp setings we use for sending mail.

So I search on net and I found the Goggle Apps consider its in different way. Which is TLS ans SSH service, which is not by default comes with the Action mailler.

ActionMailer can’t send emails using GMail out of the box. To add this functionality do the following configuration in your rails application:

  1. Create the file lib/smtp_tls.rb
    require "openssl"
    require "net/smtp"
    
    Net::SMTP.class_eval do
    private
    def do_start(helodomain, user, secret, authtype)
    raise IOError, 'SMTP session already started' if @started
    check_auth_args user, secret, authtype if user or secret
    
    sock = timeout(@open_timeout) { TCPSocket.open(@address, @port) }
    @socket = Net::InternetMessageIO.new(sock)
    @socket.read_timeout = 60 #@read_timeout
    
    check_response(critical { recv_response() })
    do_helo(helodomain)
    
    raise 'openssl library not installed' unless defined?(OpenSSL)
    starttls
    ssl = OpenSSL::SSL::SSLSocket.new(sock)
    ssl.sync_close = true
    ssl.connect
    @socket = Net::InternetMessageIO.new(ssl)
    @socket.read_timeout = 60 #@read_timeout
    do_helo(helodomain)
    
    authenticate user, secret, authtype if user
    @started = true
    ensure
    unless @started
    # authentication failed, cancel connection.
    @socket.close if not @started and @socket and not @socket.closed?
    @socket = nil
    end
    end
    
    def do_helo(helodomain)
    begin
    if @esmtp
    ehlo helodomain
    else
    helo helodomain
    end
    rescue Net::ProtocolError
    if @esmtp
    @esmtp = false
    @error_occured = false
    retry
    end
    raise
    end
    end
    
    def starttls
    getok('STARTTLS')
    end
    
    def quit
    begin
    getok('QUIT')
    rescue EOFError
    rescue OpenSSL::SSL::SSLError
    end
    end
    end
  2. Add the following lines to config/environment.rb and replace the values with the appropriate username and password:
    require 'smtp_tls'
    ActionMailer::Base.perform_deliveries = true
    ActionMailer::Base.raise_delivery_errors = true
    ActionMailer::Base.server_settings = {
    :address => "smtp.gmail.com",
    :port => 587,
    :domain => "mydomain.com",
    :authentication => :plain,
    :user_name => "username@mydomain.com",
    :password => "password"
    }

    *Note:To work your domain with “mydomain.com” you have to configure your MX records to work Gmail mail sending functionality out of box.

    Else you can use a temporary address @mydomain.com.test-google-a.com, I have not tested with this as I have already configure my MX records.

    You can get more information on changing http://www.google.com/support/a/bin/answer.py?answer=33352.

    Hope this information is useful to you. ;-)

Posted by Bhushan Ahire, filed under Ruby On Rails. Date: July 28, 2008, 9:36 am | 2 Comments »

Couple of months back, one of our clients requested an enhancement - To show some parts of the application in pop ups. I told him it would be pretty easy. I gave him the link of Redbox and said we have done this many times, it should be easy. His reply was… “Scroll up and down the pages, the pop up doesn’t seem to be moving with the page” . I said “Yes, it doesn’t”. He said he wants that to happen.

After looking around for next couple of hours, I came across Thickbox. Now how could I miss this at the first place. It was what I exactly wanted for sometime now. And it had support for iframe also. So I went ahead and downloaded the required files namely jquery-latest.js, thickbox.js and thickbox.css. For those who don’t know about jquery – Jquery is a Javascript library to handle browser events, add AJAX features to your application etc. In next 15 minutes I was ready with the sample code to check if things really work and to my disappointment it didn’t work and moreover my existing AJAX features broke. When I opened the jquery library I found that it also uses ‘$’ like prototype.js, hence a conflict.

The solution for this problem is described here.

After making the required changes it worked. I was happy, client was happy until one fine day SSL came into picture. I use nginx as my web server and had done SSL setup before. I could setup the SSL but when I clicked one of the links which use thickbox to open up the popup, it just opened the content of the popup on a new page. After playing with the code from sometime I found that the j-query file gets truncated because its too big and also the page takes lot of time to download.

Jquery provides a compact version of its library. Using this file solved my problem.

Posted by Aditya, filed under Ruby On Rails. Date: July 23, 2008, 9:23 pm | No Comments »

I have my Ruby on Rails application running on EC2.

EC2 is a web service that helps in elastic computation across the web. It is elastic because the computation is very resizable. When compared with Plain Hosting it provides the following advantages:

  • Unlike traditional hosting services EC2 provides resources that can be used unlimitedly,
  • EC2 provides full control on the resource where in the entire resource configurations can be manipulated according to the users requirement and
  • EC2’s service doesn’t require users to pay a fixed, up-front fee irrespective of their actual computing power used but instead the pay is very dynamic and the computed based on the usage of the resource.

The usage of the EC2 image becomes easier if ruby on rails application is to be hosted. As rails provide gems for additional utilities, it provides a gem called as “ec2onrails” that makes the hosting even simpler.

The following are the steps in using the EC2 image:

  • Install the gem – gem install ec2onrails

  • Add the configuration files to the rails application – There are 3 files that is essential in order to use the image:

    • Capfile – The Capistrano file that includes the line, require ‘ec2onrails/recipes’ in addition to the existing config details. This makes the ec2onrails libraries available during deployment.

    • S3.yml – Instance stores appear to an instance as a local disk. They just survive intentional and unintentional reboots of the instance unless the instance terminates or the underlying drive fails. Hence the backup or replication of important data is very essential and it happens in Amazon S3. This happens using the configurations in this S3.yml file. The details comprises of aws_access_key, aws_secret_access_key and bucket_base_name. aws_access_key and aws_secret_access_key are the keys received at the time of creating an account with Amazon EC2 and bucket_base_name is the name of the bucket into which the data needs to be stored.

    • deploy.rb – This is the deployment file containing the Capistrano configurations for ec2onrails.

  • Start the instance of the image – The instance can be started as follows:

    • Signup for Amazon EC2 and S3 to acquire the necessary authentication credentials – The necessary authentication credentials are the privacy encoded mail security X509 certificate, privacy encoded mail security private key file and the account ID.

    • Installing the EC2 Tools – This basically involves no installation as such because all what is required is to get the tools downloaded from the EC2 site, unzip it into a folder. The unzipped files are the pre-installed files, hence to make the tools visible, an environment variable – EC2_HOME is set with the path to the EC2 tools folder. Apart from this we need to tell the tools for whom it is going to be used for by setting two more environment variables such as EC2_PRIVATE_KEY and EC2_CERT containing the paths of the private key file and X509 certificate.

    • Start running the instance – All what we are left now is with running the instance. In order to run the instance we need to do the following:

      • Find a suitable AMI(Amazon Machine Image) – This happens to be the crucial step. Why I say that this is a crucial one is because on executing the command: ec2-describe-images –o self –o amazon, it will list all the available images. We need to pick the most stable image that will suffice our purpose. This is where I initially went wrong. What I did was, I chose an image without reading the name of the image file, which happened to be a very unstable one and hence had to install all the required software manually which had dependencies issue and as a result of this I had to spend several additional hours in the setup process. But realized pretty early that I was in the wrong track and then chose the right one. So how do we choose the right image? In the listing we need to look for developer-image which is public and available and make a note of the ami ID(something like ami-xxxxxxxx).

      • Generating the key pair – The privacy enhanced mail security files is used for all the interactions with the image but each and every time we interact we need to use then in our command with various options. This can be avoided by generating key pair out of the two security files and use this key pair for all the usage. In order to generate the key pair execute the command: ec2-add-keypair <name>. The name can be anything and this list a key pair which needs to be stored in a file with the name of our choice.

      • Run the instance – On executing: “ec2-run-instance ami-xxxxxxxx key_pair_filename”, the instance starts running. But it takes long time to start. This is because Amazon EC2 moves the images around the network before they can be launched. For big images and/or congested networks, this takes several minutes. To improve performance, images can be cached. As you launch your images more frequently, it becomes less noticeable.

      • Authorize Network Access o the instance – The instance uses port 80 and 22 which can be authorized by executing: “ec2-authorize default -p 22” and “ec2-authorize default -p 80”. If your application requires nay other port for access, it can be done the same way.

  • Fetch the Public key – The Capistrano deployment requires the public key of the server which can be fetched by executing: “cap ec2onrails:get_public_key_from_server”

  • Finally deploy the application with Capistrano – Firstly setup the ec2onrails Capistrano deployment by saying, cap ec2onrails:setup and then the first deployment can be done by executing, cap deploy:cold and for the later successive deployments just use, cap deploy. Apart from this the Capistrano with ec2onrails provides cap ec2onrails:db:archive and cap ec2onrails:db:restore. They can be explicitly executed for archiving and restoring the data for the database. But on the cold deploy execution the ec2 instance starts the incremental archiving of the data using the predefined cron jobs.

We now have our application hosted on EC2. Yes, it is that easy.

The only question that one would have in his/her mind now is, what will happen if my instance or the ec2 server terminates? Once the server terminates, the instance is lost and can never be got back. This is one feature that ec2 lacks. But it provides a solution to handle such situation.

There is something called as bundling of the image. On bundling the image, the instance configuration and the application is uploaded to the S3 which can then be register to another instance and the application can be in form again. This can be achieved as follows:

Prepare for bundling – The server requires the two privacy enhanced mail security files. This can be got by using scp command.

Example - scp pk-xxyyzz.pem cert-xxyyzz.pem root@ec2-xx-xxx-xx-xxx.compute-1.amazonaws.com:/mnt -i keypair_file_name

Bundle the current image – From the ec2 instance bundle the image.

Example - ec2-bundle-vol -d /mnt -k /mnt/pk-xxyyzz.pem -c /mnt/cert-xxyyzz.pem -u account_number -r i386

Upload the AMI – The AMI is then uploaded to S3.

Example - ec2-upload-bundle -b bucket_name -m /mnt/image.manifest.xml -a access_key_id -s secret_access_key

Register the Uploaded image – The image needs to be register from the local system and can be done as: ec2-register bucket_name/image.manifest.xml

This gives an ami ID with which the instance can be run.

EC2 - a quick and cost effective way of hosting Web Applications.

Posted by relton, filed under Ruby On Rails. Date: July 23, 2008, 4:51 pm | 2 Comments »

It is common to find a random number between 2 given numbers… In our java application that we are working on, We had a need to find a random time between two given timestamp.. We felt it little challenging in the beginning… But later figured out a simple solution for the same… The steps for generating a random time between 2 timestamps really turned out to be very simple & this article is about how we achieved that…

If min and max are the 2 variables that are holding minimum and maximum values, & random is the random number that is to be generated, in java the random number is calculated in this way…

random = (Math.random() * (max - min) ) + min

Here Math.random() is a function in java that generates any random value between 0 & 1… We multiply that with the difference between max & min values and finally add the obtained result with the min value to get a random number between 2 given numbers.. This idea was set as the basement for our requirement too… Wondering how?? This is how it goes…

We use Calendar object which defaults to current date and time. We then set Hour, minute & second in the same object(If required we can set the year, month & date too).. Now we have the Calendar object with the date what we set or current date and time. Calendar class has a method named getTimeInMillis which will convert this timeStamp to a long value. This long value serves as the first min variable as in the example where we generate a random number between 2 different numbers.

Now in the same way we get the long value of the second timestamp too which is the max variable value. Using a similar calculation as above we get a random long number between 2 different long numbers which are the long time. Finally we construct the date object with the long value that we obtained.. This date object’s value is the random time stamp between 2 different Calendar objects and hence the we can generate random date/time between two different Calendar objects!!!! :-)

Here goes the code for that..

//code to generate random timestamp between morning 6 to evening 8 pm
public static void main(String args[]){
Calendar cdr = Calendar.getInstance();
cdr.set(Calendar.HOUR_OF_DAY, 6);
cdr.set(Calendar.MINUTE, 0);
cdr.set(Calendar.SECOND, 0);
long val1=cdr.getTimeInMillis();


cdr.set(Calendar.HOUR_OF_DAY, 20);
cdr.set(Calendar.MINUTE, 0);
cdr.set(Calendar.SECOND, 0);
long val2=cdr.getTimeInMillis();


Random r=new Random();
long randomTS=(long)(r.nextDouble()*(val2-val1))+val1;
Date d=new Date(randomTS);
System.out.println(d.toString());
}

PS: This will work even for generating random date between two different dates which can be a month/year gap.

Posted by Nivasini, filed under Java. Date: July 17, 2008, 7:04 pm | 1 Comment »

The topic of discussion in this would not be to explain what Hibernate is or its architecture or performance issues. The reader should have a minimum knowledge of how an ORM works and Java.

One of the main reasons to move to Hibernate is to improve performance of the entire application. Traditional JDBC application is expensive and a complex job for any developer (if no DBA is available) to write the SQL queries. The developer first has to get a connection to the Database, create a Statement/PreparedStatement, ResultSets and iterate the ResultSet and embed the values into the ValueObjects (VO). Once done, the developer must ensure to close all the resources that were open during this process.

How does Hibernate eliminate all these? Hibernate requires only a DataSource to be specified and all the work of opening a connection, creating statements and executing these queries are the dirty job done by Hibernate. This shall be point of discussion in the later posts.

Let’s take a complex SQL query and convert them to Hibernate and see its advantages.

SQL Query:

select modality_type,
count(case when scheduled_ts >= DATE(NOW()) and scheduled_ts < DATE(NOW() + INTERVAL 1 DAY )
and hospital_id= 'BS' then scheduled_ts else NULL END ) as scheduled,
count(case when completed_ts != '0000-00-00 00:00:00'
and scheduled_ts >= DATE(NOW()) and scheduled_ts < DATE(NOW() + INTERVAL 1 DAY )
and hospital_id= 'BS' then completed_ts else NULL END) as completed
from order_status where modality_type in ('CT','DX','NM','US','IR','MR','PX','VA')
group by modality_type

This query is a typical Cross-tab/Pivot query. The query results in showing three columns - Modality Type, Count of Exams Scheduled for today and Count of Exams completed for the day which is grouped by Modality Type.

Let’s see how this is done with Hibernate.

1. Create a value object/java bean
Lets call our VO as CompletedAgainstScheduled

Note: For easier understanding I’ll show only a few snippets


/**
* @hibernate.class table="order_status" lazy="false"
*/
public class CompletedAgainstScheduled implements Serializable {
private Long id;
private String hospitalId;
private String modalityType;
private String completedTimestamp;
private String scheduledTimestamp;
private int completed;
private int scheduled;
private int interpretedBy;


/**
* @return
*
* @hibernate.meta attribute="id" value="ID"
* @hibernate.id type="long" column="id" generator-class="native"
*/
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}

/** other setter and getters with hibernate mapping */

…..

/**
* get and set completed orders
*
* @return
*
* @hibernate.meta attribute="completedTimestamp" value="Completed Timestamp"
* @hibernate.property column="completed_ts" formula="case when completed_ts != '0000-00-00 00:00:00' then completed_ts else null end"
*/
public String getCompletedTimestamp() {
return completedTimestamp;
}
public void setCompletedTimestamp(String completedTimestamp) {
this.completedTimestamp = completedTimestamp;
}
}

For better understanding I’ve used XDoclet for Hibernate mapping.

When this class is compiled (using maven and xdoclet-plugin), it creates the Hibernate mapping file automatically.

So what is this class doing? @hibernate.class table="order_status" says that this VO is mapped to the table order_status in our database.

@hibernate.meta attribute="completedTimestamp" value="Completed Timestamp"
@hibernate.property column="completed_ts" formula="case when completed_ts != '0000-00-00 00:00:00' then completed_ts else null end"

The @hibernate.meta is basically for API Documentation and @hibernate.property column="completed_ts" is mapped to the attribute completedTimestamp in the Value Object.

Here is a very interesting concept: formula="case when completed_ts != '0000-00-00 00:00:00' then completed_ts else null end"
Why do this at all? Value Objects are ALWAYS mapped to a table and its attributes to columns. In the above Cross-tab query, we are deriving columns that are not in the table. Hence the formula on what should be done. We are counting number of rows for completed_ts that is not equal to “0000-00-00 00:00:00″. This formula will be embedded within the count() function.

NOTE: The case when.. is compatible only with MySQL and Oracle.

2. Hibernate Query
This section covers how the query is built in the DAO layer

Criteria criteria = getSession().createCriteria(CompletedAgainstScheduled.class)
.setProjection(
Projections.projectionList()
.add(Projections.groupProperty("modalityType").as("modalityType"))
.add(Projections.count("scheduledTimestamp").as("scheduled"))
.add(Projections.count("completedTimestamp").as("completed"))
)//.add(Restrictions.in("modalityType", modArr))
.add(Expression.ge("scheduledTimestamp", sdf.format(c.getTime())))
.add(Expression.lt("scheduledTimestamp", sdf.format(cd.getTime())))
.add(Expression.eq("hospitalId", hospitalId));


List csList = null;
if (criteria != null) {
csList = criteria.setResultTransformer(new AliasToBeanResultTransformer(CompletedAgainstScheduled.class)).list();
}

We have a ProjectionList that has modalityType (the column on which the resultSet should be grouped), scheduledTimestamp and completedTimestamp (the column that should be counted). Note that the attributes we are providing in the criteria. These are the attributes from the VO not the actual column names. This is what we call as HQL (Hibernate Query Language). When Hibernate complies this criteria, it generates a SQL dynamically and executes this at the database and returns a list of Objects which is of type CompletedAgainstScheduled.

Now, let’s do a little bit of post-mortem on how this Hibernate and SQL Query:

.add(Projections.groupProperty("modalityType").as("modalityType"))
.add(Projections.count("scheduledTimestamp").as("scheduled"))
.add(Projections.count("completedTimestamp").as("completed"))

is equivalent to

select modality_type,
count(scheduled_ts) as scheduled, count(completed_ts) as completed

We know that completedTimestamp is mapped to completed_ts in the table and returns an integer. But the column completed_ts itself is a datetime column. So, what happens to the integer? Well, the Projection says that count(completedTimestamp) which is mapped to completed_ts based on the formula we have specified in the VO and store the result in the completed attribute of the VO. Simple?

We can add as many expression as possible using the Expression class.

Once the query is executed, it returns a list of Objects which we have stored in csList. How does Hibernate know what and how to map? The ResultTransformer class does this job. It uses a sub-class called AliasToBeanResultTransformer class which is called for every row in the ResultSet and maps them to our VO.

That’s it. Very simple and intelligent.

If you have any doubts, do not hesitate to ask your questions.

In the next few series we’ll explore, Why Hibernate, XDoclets, Associations and other Hibernate related challenges.

Posted by Samanth, filed under Java. Date: July 11, 2008, 1:28 pm | 1 Comment »