Programming

Google

A simple database application with Spring and Hibernate

Submitted by Ravindra on Wed, 2008-02-27 13:11.

First let me explain the design of this source code.

there are basically
1. domain classes
2. DAO classes
3. service classes

and usually there are model classes, but in this sample application model classes are same as domain classes.

finally i have the main application LibraryApp.java , which has the main method.

public static void main(String[] args) throws Exception {

ApplicationContext context = new ClassPathXmlApplicationContext(
new String[] { "library-db.xml","library-data-hibernate.xml","library-services.xml"});

/*
Thanks to spring i define database source objects ,schema to object mappings and dependencies between classes in the above XML files and everything else is done automatically.

*/

/*
i have defined a DataSource object in "library-db.xml" , with the connection properties in "db.properties".

*/
/*
i have defined a sessionFactory that uses the previous DataSource object in "library-data-hibernate.xml" . then i have defined a HibernateTemplate bean that uses the sessionFactory bean.
finally the DAO beans are defined ,each to use the HibernateTemplate bean.

*/
/*
then there is "library-services.xml" where i have defined the service beans. there is only one service bookService.
*/

Book book = new Book();
book.setName("test");
book.setIsbn("test isbn");
// just create a Book object and set its properties.
BookRegistrationService bookService =
(BookRegistrationService) context.getBean("bookService");
/* we get a BookRegistrationService object and its DAO property is already injected by Spring automatically.
*/
bookService.registerBook(book);
/*
okay now lets try to understand the flow so far.
the front end captures some info from the user, and in this case the front end is the Main app, which captures the book name and isbn from the user(in this sample app there is no user interaction how ever) and creates a model object that can hold all that data. In this case we captured data of only a book so we do not need to define another model class to get and set book info. instead we can use the domain Book class that can set and get book properties. But if we had to collect additional information than book properties (say buying information of that book) then we have to create a separate model object that can hold all that data. so that model object (lets name it BookRegistration.java) will have setters and getter's for book properties as well as for buying properties as well.
so next step is we pass the model to the service object which contains the business logic.
in this simple case the service object simply requests its DAO object to save the book. But in practical cases there would have been more business logic other than saving to database. Note that the service object has no idea of how to interact with the database.
it does not even know whether its hibernate that is going to save it for it.thus the service object is dependent on the DAO object for all database interactions. how ever this dependency is not hard coded. instead its injected through spring. thus to change to a different DAO object i do not need to modify the service object. which is the way it should happen ,since business layer should not be affected when we change our persistent designs. only thing it should know is that it has a DAO object that case save data for it, irrespective of how.
in the case of book info+buying info, the service object would have two DAOs , one that case save book info and the other that can save buying info.
and the service object would divide the data model object provided between two domain objects. that is set book data on an instance of Book class and buy info on a similar domain class.
then the service object would pass this domain objects to the relevant DAO to save to database.
In this case the DAO that is injected is a hibernate implementation named HibernateBookDao.java.
HibernateBookDao has the addBook method which in return calls saveOrUpdate method of HibernateTemplate with the domain object as a parameter. By this time hibernate has read the hbm.xml files and there we have defined how to save a object of class "com.r4vi.libravi.domain.Book". so when the saveOrUpdate method is called , hibernate simply looks at the mappings we defined and saves to the database accordingly.

*/
List<Book> bookList=bookService.listAllBooks();
Iterator<Book> books=bookList.iterator();
while(books.hasNext()){
Book b=books.next();
System.out.println(b.getName());
System.out.println(b.getIsbn());
}
System.out.println("All books printed");
Book book2=bookService.findBook(1);
System.out.println(book2.getName());

/*
retrieving objects follow a similar flow, but be careful with lazy loading and session closed error. lazy loading is a fantastic feature where you can delay loading of object and data that are not needed immediately. how ever because of that make sure you have not closed the session that contains the data source , when those data will be needed and fetched.
*/

}

some info on hibernate properties file.
I have named it "db.properties" here.

contents are

hibernate.connection.driver_class=org.gjt.mm.mysql.Driver
hibernate.connection.url=jdbc:mysql://localhost/library
hibernate.connection.username=
hibernate.connection.password=
hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect

then i wrote "library_db-data.xml" which uses those properties
note that i have given the location of "db.properties"
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:/db.properties" />
</bean>

and i use the properties i defined in "db.properties" here
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${hibernate.connection.driver_class}" />
<property name="url" value="${hibernate.connection.url}" />
<property name="username" value="${hibernate.connection.username}" />
<property name="password" value="${hibernate.connection.password}" />
</bean>

though you could have used "xx.yy" instead of "hibernate.connection.username" and refer to same "xx.yy"
i recommend that you stick to this naming convention if you use hbm2ddl tool to setup database tables.

then i wrote the "library-data-hibernate.xml" file
important to note stuff are
under property name="mappingResources" i have listed the hibernate mapping files that should be read , and in practical usage i will put them all in some directories and specify all the files in the directories rather than listing each file.

then i have defined the hibernate DAO beans all of them to be injected with an HibernateTemplate instance.

permalink

Hello World with Spring Programming

Submitted by Ravindra on Wed, 2008-02-20 10:18.

Welcome to the first article of the Spring Programming Series i hope to write on.

This a very basic one where i simply display a hello message.
Later on the series we will see how we can fetch the message from the database and how we can display the message in a web form.

first lets define the following interface

public interface HelloMessage {
public void sayHello();
}

basically it define a method called sayHello.
Then lets implement it in the following class.

public class HelloMessageImpl implements HelloMessage{
private String helloMessage;

public HelloMessageImpl() {}

public HelloMessageImpl(String helloMessage) {
this.helloMessage = helloMessage;
}

public void sayHello() {
System.out.println(helloMessage);
}

public void setHelloMessage(String helloMessage) {
this.helloMessage = helloMessage;
}
}

HelloMessageImpl has two constructors and it must have the sayHello methods since it implements the HelloMessage interface.

Then there is a property called helloMessage and since we are going to expose this class as a bean it has a setHelloMessage method as well.

So far nothing fancy or spring specific right?
well now lets write main class.

public class HelloApp {
private static final org.apache.log4j.Logger LOGGER = org.apache.log4j.Logger
.getLogger(HelloApp.class);

public static void main(String[] args) throws Exception {
LOGGER.debug("Starting to Run HelloApp");
BeanFactory factory =
new XmlBeanFactory(new FileSystemResource("hello.xml"));
LOGGER.debug("spring XML file read");
HelloMessage helloMessage =
(HelloMessage) factory.getBean("helloMessage");
LOGGER.debug("Bean obtained");
helloMessage.sayHello();
LOGGER.debug("Run completed");
}
}

First we obtain a logger to this class. Make sure that you have log4j-1.2.14.jar (version can differ) in your classpath. In this case i am shipping all the jars with the source code and configure the classpaths using the ANT build. so nothing for you to do :)

First we read the Spring configuration file hello.xml from relative path and feed the XML to XmlBeanFactory. XmlBeanFactory reads bean info from the XML and creates a factory. Then you request a bean with ID="helloMessage" from this bean factory. Then you simply call the sayHello method in that bean.

So whats so different here? One difference is we obtained access to the HelloMessage class through the core container.

The core container is fundamental to any spring framework.
It contains the BeanFactory, which is a bean factory as the name implies. it generates beans from config files and is responsible for dependency injection at bean creation.

The core container used hello.xml to decide how to give out the HelloMessage class. if we look at hello.xml

<bean id="helloMessage"
class="com.r4vi.hello.HelloMessageImpl">
<property name="helloMessage" value="Welcome to Spring Programming !" />
</bean>

we have defined a bean with ID=helloMessage that is implemented by HelloMessageImpl class and which has a property by the name helloMessage.
and we set the value of that property through the the XML file.
well thats where spring comes in. If we look closely at the HelloMessageImpl class, it requires a helloMessage to sayHello.
In conventional applications helloMessage class would have generated the helloMessage itself or we will have to write another class to create the helloMessage and feed to HelloMessageImpl class. All of that approaches have a problem. That is we are hard coding the dependency HelloMessageImpl has on helloMessage. Since helloMessage is a string , you might not feel the significance , but the importance of that really comes in to play when you inject objects. With Spring we do not code dependencies between objects. Instead we wire them together using XML configuration. Thus it will take a lot more less time to change a dependency.

though we have resorted to BeanFactory for this simple app, in practical situations you will use Application context.

Application context
unless your application is really really simple you will nead more functionality from the framework. This module simply extends the core container to provide more functionality.

permalink

Spring with MySQL

Submitted by Ravindra on Sun, 2008-02-17 09:50.

First download the MySQL driver from
http://www.mysql.com/products/connector/j/

then edit the build.properties file as follows

db.url=jdbc:mysql://localhost/<db name>
db.driver=org.gjt.mm.mysql.Driver
db.username=<mysql  user name>
db.password=<mysql password>
hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect

only value that might not change for your configuration is the db.driver.
as for hibernate.dialect value, open hibernate3.jar and browse to /org/hibernate/dialect/ to see the available dialects.

permalink
Syndicate content