Tải bản đầy đủ - 0 (trang)
Chapter 3. Accelerate with Spring DAO

Chapter 3. Accelerate with Spring DAO

Tải bản đầy đủ - 0trang

customized exceptions using DAO design pattern.



How Spring handles database?

In Java application the developers generally uses a concept of utility class to

create, open and close database connection. A pretty sound, smart and

reusable way for connection management but still the application is tightly

coupled with the utility class. Any change in the either the database or its

connectivity as URL, username, password or schema, it need to be changed

in the class. This needs to be followed by the recompilation and

redeployment of the code. In such scenario externalizing the connection

parameters will be a good solution. We cannot externalise the Connection

object, that still has to be managed by the developer and so do the exceptions

while handling it. Spring has a elegant, loosely coupled ways to manage the

connection using the DataSource at centre.



The DataSource

The DataSource is the factory for data source connections similar to the

DriverManager in JDBC who helps for Connection management. Following

are some of the implementations which can be used in the application to

obtain the Connection object:

DriverManagerDataSource : The DriverManager class provides a

simple implementation of the DataSource to be used in test or

standalone application which enable a new Connection object on every

request via getConnection().

SingleConnectionDataSource: The class is an implementation of the

SmartDatSource which gives a single Connection object which doesn't

get closed after its use. It's useful only in single threaded applications

and in making testing easy outside of the application server.

DataSourceUtils: This is a helper class who has static methods for

obtaining the database Connection from DataSource.

DataSourceTransactionManager: This class is an implementation of

the PlatformTransactionManager for a Connection per data source.



Configuring DataSource

The DataSource can be configured by following ways in the application:

Obtained from JNDI look up : Spring helps in maintaining large scale

JavaEE application which run in application servers like Glassfish,

JBoss, Wlblogic, Tomcat. All these servers support facility to configure

the pool of data sources which can be acquired by the Java Naming

Directory Interface (JNDI) look up helps in better performance. The jee

namespace can be used to obtain data source configured in the

application as shown below:


xmlns:jee="http://www.springframework.org/schema/jee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.springframework.org/schema/

beans http://www.springframework.org/schema/beans/

spring-beans.xsd http://www.springframework.org/schema/jee

http://www.springframework.org/schema/jee/spring-jee.xsd">


class="org.springframework.jndi.JndiObjectFactoryBean">


value="java:comp/env/jdbc/myDataSource"/>




resource-ref="true"/>





Where:

jndi-name : specifies name of the resource configured on server in

JNDI

id : id of the bean which gives object of DataSource

resource-ref : specifies whether to prefix with java:comp/env or not.

Fetched from the pooled connection : Spring doesn't have pooled data

source but, we can configure pooled data source provided by Jakarta

Commons Database Connection Pooling. The DBCP provided



BasicDataSource can be configured as,


class="org.apache.commons.dbcp.BasicDataSource">


value="org.hsqldb.jdbcDriver"/>


value="jdbc:hsqldb:hsql://locahost/name_of_schama"/>


value="credential_for_username"/>


value="credential_for_password"/>


value=""/>


value=""/>





Where:

initialSize: specifies how many connections to be created when the pool

is started

maxActive: specifies how many connections can be allocated from the

pool.

Along with these attributes we can even specify the time which needs to

wait till the connection is returned from the pool(maxWait), the

maximum/ minimum number of connections that can be idle in the

pool(maxIdle/ minIdle), the maximum number of prepared statements

that can be allocated from the statement pool

(maxOperationPreparedStatements).

With the help of JDBC driver : One can use of the following class to

configure the simplest way to get and object of the DataSource:

* SingleConnectionDataSource: As we already discussed it returns single

connection.

* DriverManagerDataSource: It returns a new connection object on a

request.



The DriverMangerDataSource configuration can be done as follows:


class="org.springframework.jdbc.datasource.

DriverManagerDataSource">


value="org.hsqldb.jdbcDriver"/>


value="jdbc:hsqldb:hsql://locahost/name_of_schama"/>


value="credential_for_username"/>


value="credential_for_password"/>





Note

SingleConnectionDataSource is suiltable for small single

threaded applications. DriverManagerDataSource supports

multithreaded application but hampers the performance due to

managing number of connections. It's recommended to use

pooled data source for better performance.

Let's develop a sample demo using loosely coupled modules so that we will

understand the practical aspects of Spring framework application

development.

The DataSource facilitates handling of connection with database so it needs

to be injected in the module. The choice of using setter DI or constructor DI

can be totally decided by you as you are well aware of both of these

dependency injections. We will use setter DI. Instead of starting from the

class we will start by considering interface as it's the best way to do

programming by contract. The interfaces can have multiple implementations.

So the use of interface and Spring configuration helps to achieve loosely

coupled modules. We will declare the methods for database operations, you

are free to choose the signature. But make sure that they will be testable. As

loose coupling is major feature of the framework the application will also

demonstrate why we keep on saying loosely coupled modules can be easily

written using Spring? You can use any database but we will use MySQL



throughout the book. Whatever the database you choose make sure to install

it before moving ahead So let's start by following the steps!

Case 1: using XML configuration of DriverManagerDataSource



1. Create a Core Java application as Ch03_DataSourceConfiguration and

add to it jar for Spring and JDBC as shown in the outline of the

application below:



2. Create a Book POJO in com.ch03.packt.beans package as shown below:

public class Book {

private String bookName;

private long ISBN;

private String publication;

private int price;

private String description;

private String [] authors;

public Book() {

// TODO Auto-generated constructor stub

this.bookName="Book Name";

this.ISBN =98564567l;

this.publication="Packt Publication";



this.price=200;

this.description="this is book in general";

this.author="ABCD";

}

public Book(String bookName, long ISBN, String

publication,int price,String description,String

author)

{

this.bookName=bookName;

this.ISBN =ISBN;

this.publication=publication;

this.price=price;

this.description=description;

this.author=author;

}

// getters and setters

@Override

public String toString() {

// TODO Auto-generated method stub

return bookName+"\t"+description+"\t"+price;

}

}



3. Declare an interface BookDAO in com.ch03.packt.dao package. (DAO

means Data access Object).

4. Add to it a method for adding a book to the database. The code will be

as shown below:

interface BookDAO

{

public int addBook(Book book);

}



5. Create an implementation class for BookDAO as BookDAOImpl and

add a data member of type DataSource in the class as follows:

private DataSource dataSource;



Don't forget to use standard bean naming conventions.

6. As we are following setter injection write or generate setters for

DataSource.

7. The overridden method will deal with getting the connection from



DataSource and using PreaparedStatement insert a book object in the

table as we do in JDBC as shown in the code below:

public class BookDAOImpl implements BookDAO {

private DataSource dataSource;

public void setDataSource(DataSource dataSource) {

this.dataSource = dataSource;

}

@Override

public int addBook(Book book) {

// TODO Auto-generated method stub

int rows=0;

String INSERT_BOOK="insert into book values(?,?,?,?,?,?)";

try {

Connection connection=dataSource.getConnection();

PreparedStatement ps=

connection.prepareStatement(INSERT_BOOK);

ps.setString(1,book.getBookName());

ps.setLong(2,book.getISBN());

ps.setString(3,book.getPublication());

ps.setInt(4,book.getPrice());

ps.setString(5,book.getDescription());

ps.setString(6,book.getAuthor());

rows=ps.executeUpdate();

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return rows;

}

}



8. Create connection.xml in classpath to configure the beans.

9. Now the question will be how many beans to be declared and what has

to be their id's?



Note

A very simple thumb rule: First find out class to configure and

then what are its dependencies?



Here:

* A bean for BookDAOImpl

* BookDAOImpl has DataSource as a dependency so a bean for DataSource.

You will be wondering that DataSource is an interface! So, how could we

create and inject its object? Yes, this is what our point is! This is what we are

talking about loosely coupled modules. The DataSource implementation

which we are using here is, DriverManagerDataSource. But, if we inject

directly DriverManagerDataSource then the class will be tightly coupled on

it. Also, if tomorrow instead of using DriverManagerDataSource the team

decides to use some other implementation then the code has to be changed

which leads to recompilation and redeployment. That mean the better

solution will be using interface and injecting its implementation from the

configuration.

The id's can be of developers choice, but don't neglect to take the advantage

of auto wiring and then accordingly set the id. Here we will use auto wiring

'byName' so choose the id's accordingly. (If you are confused or want to dig

about auto wiring you can refer the previous chapter.) So the final

configuration in XML will be as follows:


class=

"org.springframework.jdbc.datasource.DriverManagerDataSource">


value="com.mysql.jdbc.Driver" />


value="jdbc:mysql://localhost:3306/bookDB" />








autowire="byname">





You use may need to customize the URL, username, password to match your

connection parameters.



1. Normally, the DAO layer will be invoked by the Service layer but here

we are not dealing with it as the application proceed we will add it. As

we yet not discussed about testing we will write a code with main

function to find out the output of it. The main function will get

BookDAO bean and invoke on it a method to insert the Book. If the

value of the row returned by the implementation code is greater than

zero the book got successfully added otherwise not. Create a class

MainBookDAO and add the following code to it:

public static void main(String[] args) {

// TODO Auto-generated method stub

ApplicationContext context=new

ClassPathXmlApplicationContext("connection.xml");

BookDAO bookDAO=(BookDAO) context.getBean("bookDao");

int rows=bookDAO.addBook(new Book("Learning Modular

Java Programming", 9781234,"PacktPub

publication",800,"explore the power of

Modular programming","T.M.Jog"));

if(rows>0)

{

System.out.println("book inserted successfully");

}

else

System.out.println("SORRY!cannot add book");

}



If you keenly observed though we configure object of BookDAOImpl we are

accepting it in BookDAO interface which helps in writing flexible code

where the main code is unaware of in actual whose object is giving

implementation.

2. Open your MYSQL console, use credentials to login. Fire query to

create BookDB schema and Book table as shown below:



3. All set to execute the code to get "book inserted successfully" on



console. You can fire "select * from book" in MySQL to get the book

details as well.

Case2: Using Annotations for DriverManagerDataSource



We will use the same Java application Ch03_DataSourceConfiguration

developed in Case1:

1. Declare a class BookDAO_Annotation implementing BookDAO in

com.packt.ch03.dao package and annotate it with @Repository as it

deals with database and specify id as 'bookDAO_new'.

2. Declare a data member of type DataSource and annotate it with

@Autowired to support auto wiring.

Don't forget to use standard bean naming conventions.

The overridden method will deal database to insert book in table. The

code will be as shown below:

@Repository(value="bookDAO_new")

public class BookDAO_Annotation implements BookDAO {

@Autowired

private DataSource dataSource;

@Override

public int addBook(Book book) {

// TODO Auto-generated method stub

int rows=0;

// code similar to insertion of book as shown in

Case1.

return rows;

}

}



3. We can edit the same connection.xml from Case1 but that may complex

the configuration. So, let's create connection_new.xml in classpath to

configure the instructions for container to consider annotation and

search for stereotype annotations as follows:







Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Chapter 3. Accelerate with Spring DAO

Tải bản đầy đủ ngay(0 tr)

×