📄 Page
1
www.it-ebooks.info
📄 Page
2
www.it-ebooks.info
📄 Page
3
Just Spring Data Access Madhusudhan Konda Beijing • Cambridge • Farnham • Köln • Sebastopol • Tokyo www.it-ebooks.info
📄 Page
4
Just Spring Data Access by Madhusudhan Konda Copyright © 2012 Madhusudhan Konda. All rights reserved. Printed in the United States of America. Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472. O’Reilly books may be purchased for educational, business, or sales promotional use. Online editions are also available for most titles (http://my.safaribooksonline.com). For more information, contact our corporate/institutional sales department: 800-998-9938 or corporate@oreilly.com. Editors: Mike Loukides and Meghan Blanchette Production Editor: Iris Febres Copyeditor: Gillian McGarvey Proofreader: Iris Febres Cover Designer: Karen Montgomery Interior Designer: David Futato Illustrator: Robert Romano Revision History for the First Edition: 2012-06-01 First release See http://oreilly.com/catalog/errata.csp?isbn=9781449328382 for release details. Nutshell Handbook, the Nutshell Handbook logo, and the O’Reilly logo are registered trademarks of O’Reilly Media, Inc. Just Spring Data Access, the image of the channel-billed cuckoo, and related trade dress are trademarks of O’Reilly Media, Inc. Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in this book, and O’Reilly Media, Inc., was aware of a trademark claim, the designations have been printed in caps or initial caps. While every precaution has been taken in the preparation of this book, the publisher and authors assume no responsibility for errors or omissions, or for damages resulting from the use of the information con- tained herein. ISBN: 978-1-449-32838-2 [LSI] 1339616491 www.it-ebooks.info
📄 Page
5
Table of Contents Foreword . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . v Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vii 1. Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Using Plain JDBC 1 Spring Data Access 3 Templates 3 MySQL Database Scripts 3 Using JdbcTemplate 4 Summary 13 2. Advanced Concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 NamedParameterJdbcTemplate 15 Using Map 16 Using SqlParameterSource 16 Jdbc Batching 17 Using SqlParameterSourceUtils 17 Using BatchPreparedStatementSetter 18 Simple JDBC Classes 19 SimpleJDBCInsert Class 19 SimpleJdbcCall Class 20 In-Memory Databases 21 Callbacks 23 PreparedStatement Callback 23 Callable Statement Callbacks 25 Row Callbacks 26 Summary 27 3. Hibernate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Two-Minute Hibernate 29 iii www.it-ebooks.info
📄 Page
6
Using Spring Hibernate 31 Basic Setup 32 Hibernate Operations 35 Using HibernateTemplate 37 Transactions 38 Summary 40 4. Spring JPA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 Two-Minute JPA 41 Using Spring 43 Standalone Factory 44 Container Factory 45 Transactions 47 Using Plain JPA API 48 Using JpaTemplate 49 Support Classes 51 Summary 51 5. Spring JDO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 Spring Support 53 Plain JDO API 54 Persistent Entity 54 Persistence DAO 55 Wiring the Pieces 55 Bytecode Enhancers 56 Example Test 57 Working with JdoTemplate 57 Support Classes 59 JDO versus JPA versus Hibernate 60 Summary 61 iv | Table of Contents www.it-ebooks.info
📄 Page
7
Foreword Reading headlines like “Facebook moves 30-petabyte Hadoop cluster to new data cen- ter” shows that one of the biggest struggles we are facing today is Big Data and its management. Data centric applications, mobile front ends to complex data structures, and serving millions of clients accessing our datasets while handling billions of trans- actions a day shows that keeping data management simple and easy to handle is a first class problem in modern application development. Thankfully, tools like Spring Data and it’s many utilities make it easy to access these data sets using whichever flavor of standards best fits our team’s skills and needs. While Java blazed the trail by offering the flexible but consistent JDBC standard, it was the power of Spring that cut out the tedious amounts of boilerplate afforded to us by his- torical SQL paradigms. This has empowered developers to focus on business logic, scaling requirements, mobile platform support, and other numerous requirements while allowing Spring to handle the chores of managing connections and interacting with various data management technologies. This is analogous to migrating from the manual memory management of coding in C to Java’s sophisticated garbage collection, which removed a whole host of bugs we as developers used to face every day. By re- ducing the total amount of code we must write to access our own Big Data, we quickly cut out a huge number of potential bugs on Day One of our own projects. It is refreshing to read a slim and trim book like Just Spring Data Access, which avoids the ever popular thick-as-possible approach and instead tries to be as clear and to-the- point as possible. For the fledgling developer that has just joined a team that uses Spring Data, this book provides a fantastic means to “catch up” over the weekend and be ready to dive in on Monday. For an architect trying to choose which standard to use for a new system, it also provides a quick read, allowing him or her to start their evaluation with something more concrete than some cobbled together opinions. Finally, for the more seasoned developer, it provides a good reference to look back and polish up skills in the arena of data management and the options provided by competing Java stand- ards. None of us are experts on everything, and having a tightly focused book is often just what we need to hone in and solve the problems we have. —Greg Turnquist, Senior Software Engineer at SpringSource, a division of VMware, and author of Spring Python 1.1 v www.it-ebooks.info
📄 Page
8
www.it-ebooks.info
📄 Page
9
Preface There are two different worlds: the world where none other than objects are known, and the world where data is represented in a traditional row-column format. Bringing these two worlds together is always a cumbersome task, and many times is asking for trouble. However, we have no option: they must work together! We have JDBC to some extent, but the intricacies and complexities of persistence of Java objects to a relational databases was still a greater challenge. The Object Relational Mapping frameworks—Hibernate being the most popular open source framework— has taken away a lot of pain and grief from the developer. Spring framework has gone one more step further to simplify the usage even further. This book in an attempt in bringing the framework closer to the developer. With simple and plain language, along with easy to understand examples, this book covers just the required bits for data access in a Java world. This book covers JDBC, Hibernate, JPA, and JDO, as well as Spring’s take on these technologies. My goal is to deliver simple, straight-to-the-point explanations with intuitive, example- driven, engaging books! If you pick up the book, you should finish it in a day or two at most! I sincerely believe that one will gain adequate knowledge and ammunition after reading this book. One would require the basic understanding of Java and Spring Framework as a pre- requisite to this book. I am expecting you to enjoy this simple read. Please do get in touch even if you are unsatisfied with my writings. If you are in London, ping me (and perhaps buy me a coffee) for a meetup. Additionally, I am easily accessible via email (madhusudhan@madhusudhan.com) or via Twitter (@mkonda007). vii www.it-ebooks.info
📄 Page
10
Conventions Used in This Book The following typographical conventions are used in this book: Italic Indicates new terms, URLs, email addresses, filenames, and file extensions. Constant width Used for program listings, as well as within paragraphs to refer to program elements such as variable or function names, databases, data types, environment variables, statements, and keywords. Constant width bold Shows commands or other text that should be typed literally by the user. Constant width italic Shows text that should be replaced with user-supplied values or by values deter- mined by context. This icon signifies a tip, suggestion, or general note. This icon indicates a warning or caution. Using Code Examples This book is here to help you get your job done. In general, you may use the code in this book in your programs and documentation. You do not need to contact us for permission unless you’re reproducing a significant portion of the code. For example, writing a program that uses several chunks of code from this book does not require permission. Selling or distributing a CD-ROM of examples from O’Reilly books does require permission. Answering a question by citing this book and quoting example code does not require permission. Incorporating a significant amount of example code from this book into your product’s documentation does require permission. We appreciate, but do not require, attribution. An attribution usually includes the title, author, publisher, and ISBN. For example: “Just Spring Data Access by Madhusudhan Konda (O’Reilly). Copyright 2012 Madhusudhan Konda, 978-1-449-32838-2.” If you feel your use of code examples falls outside fair use or the permission given above, feel free to contact us at permissions@oreilly.com. viii | Preface www.it-ebooks.info
📄 Page
11
Safari® Books Online Safari Books Online (www.safaribooksonline.com) is an on-demand digital library that delivers expert content in both book and video form from the world’s leading authors in technology and business. Technology professionals, software developers, web designers, and business and cre- ative professionals use Safari Books Online as their primary resource for research, problem solving, learning, and certification training. Safari Books Online offers a range of product mixes and pricing programs for organi- zations, government agencies, and individuals. Subscribers have access to thousands of books, training videos, and prepublication manuscripts in one fully searchable da- tabase from publishers like O’Reilly Media, Prentice Hall Professional, Addison-Wesley Professional, Microsoft Press, Sams, Que, Peachpit Press, Focal Press, Cisco Press, John Wiley & Sons, Syngress, Morgan Kaufmann, IBM Redbooks, Packt, Adobe Press, FT Press, Apress, Manning, New Riders, McGraw-Hill, Jones & Bartlett, Course Tech- nology, and dozens more. For more information about Safari Books Online, please visit us online. How to Contact Us Please address comments and questions concerning this book to the publisher: O’Reilly Media, Inc. 1005 Gravenstein Highway North Sebastopol, CA 95472 800-998-9938 (in the United States or Canada) 707-829-0515 (international or local) 707-829-0104 (fax) We have a web page for this book, where we list errata, examples, and any additional information. You can access this page at: http://oreil.ly/JustSpringData To comment or ask technical questions about this book, send email to: bookquestions@oreilly.com For more information about our books, courses, conferences, and news, see our website at http://www.oreilly.com. Find us on Facebook: http://facebook.com/oreilly Follow us on Twitter: http://twitter.com/oreillymedia Watch us on YouTube: http://www.youtube.com/oreillymedia Preface | ix www.it-ebooks.info
📄 Page
12
Acknowledgments I sincerely wish to thank my editors, Mike Loukides and Meghan Blanchette, and to all of those at O’Reilly, especially Iris Febres for helping shape this book. I also sincerely express my deepest gratitude to Greg Turnquist for his guidance throughout the project. A big thanks to goes to my family, especially to my loving wife, Jeannette, for being very patient and supportive. Also to my loving five-year-old son, Joshua, who sacrificed his free time, allowing me to write when I explained to him what I was doing in return for a trip to Disneyland! I also thank my family in India for their wonderful support and love. This book was written in memory of my loving Dad—we all miss you, Dad! x | Preface www.it-ebooks.info
📄 Page
13
CHAPTER 1 Basics Persistence of data is a challenging task for developers. There are many things that could go wrong. The introduction of JDBC has given the developer community a bit of joy by taking away painstakingly cumbersome database access in Java applications. How- ever, there are a few wrinkles that come with JDBC, such as having to write boilerplate code, finding out a clue from the SQLExcetion stacktrace, resource management, and so on. Spring has gone further in simplifying the data access by providing a simple and straightforward framework. This chapter discusses Spring’s take on JDBC, and how Spring simplified the JDBC programming model; it did so by employing simple yet powerful mechanisms, such as Dependency Injection, Templates, and other patterns. Using Plain JDBC With the advent of JDBC, accessing data from a Java application has become relatively easy. Not only do we have independence from database vendor lock-in, but we also have a standard API to access multitude of databases. However, the steps involved in using a JDBC are always the same—obtain a connection, create a Statement, execute a query, run it through ResultSet, and release the resources. The following code demonstrates a simple example of selecting the TRADES data using plain JDBC: public class JdbcPlainTest { private String DB_URL="jdbc:mysql://localhost:3306/JSDATA"; private final String USER_NAME = "XXXX"; private final String PASSWORD = "XXXX"; private Connection createConnection() { Connection conn = null; try { Class.forName("com.mysql.jdbc.Driver"); conn = 1 www.it-ebooks.info
📄 Page
14
DriverManager.getConnection(DB_URL, USER_NAME,PASSWORD); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } return conn; } private void query() { ResultSet rs = null; Statement stmt = null; Connection conn = createConnection(); try { stmt = conn.createStatement(); rs = stmt.executeQuery("SELECT * FROM TRADES"); while (rs.next()) System.out.println(rs.getString(1)); } catch (SQLException e) { e.printStackTrace(); } finally { try { rs.close(); stmt.close(); conn.close(); } catch (SQLException ex) { e.printStackTrace(); } } } public static void main(String args[]) { JdbcPlainTest t = new JdbcPlainTest(); t.query(); } } Phew! That’s a lot of code for a simple task! Did you notice the code around exceptions? There are a few things that you could have noticed from the above example: • The resource management (creating and closing connections and statements) is a repetitious process. • The SQLException must be caught in both the creation and destruction processes. • The actual business logic is not more than a couple of lines; unfortunately, code is cluttered with lot of JDBC API statements and calls. We can create a home-grown framework with callbacks and handlers to resolve these issues. Although it does work, creating your own framework leads to several issues— maintenance, extending to suit newer requirements, extensive testing, and others. 2 | Chapter 1: Basics www.it-ebooks.info
📄 Page
15
If there’s already a framework that does this work, why reinvent the wheel? The Spring data access framework is specifically created to address these problems. It is a beautiful framework that promotes Dependency Injection principles and carries multiple features. Spring Data Access The Spring data access framework has made the developer’s job very easy! It creates a rich framework in which, or from which to access databases by decoupling our code from the access mechanisms. As always, the framework heavily uses Depend- ency Injection patterns, so decoupling of our code really comes to life. The components using framework’s API are easily testable, too. Moreover, there’s no exceptions that we should have to catch when using the APIs! The access logic revolves around Template patterns and Support classes. These patterns hide away all the boilerplate code and allows the developer to concentrate solely on business logic. Templates From the previous example, we can see that there is a lot of code that’s not central to business function. It would be ideal to wrap up the non-critical code away from our business code in a separate class. Spring’s JdbcTemplate class does exactly that. This class wraps up all the access logic so users only need to concentrate on the heart of the application. If you understand the workings of JdbcTemplate, I would say you’ve conquered most of Spring’s data access workings. In addition to the standard JdbcTemplate, there are two other variations of the Template class: SimpleJdbcTemplate and NamedParameterJdbcTemplate. These two varieties are nothing but wrappers around JdbcTemplate that are used for special cases. We will discuss all of these in the coming sections. Before we work out examples, we have to carry out some prerequisites such as creating a database schema and prepopulating test data. If you already have a database in place, you can skip this section without any concern. MySQL Database Scripts I am using MySQL as the database for all of the examples provided in this book. Setting up the database is easy if you follow the instructions from the provider carefully. Once you have MySQL set up, make sure you run the SQL scripts provided by the book’s source code. These scripts will create a database called JSDATA and create nec- essary tables such as ACCOUNTS, TRADES, PRICES, and others. If you are working with some Templates | 3 www.it-ebooks.info
📄 Page
16
other database, you should be able to run the scripts without any issues; personally, I have not tested them. The next important thing is to create a DataSource. The DataSource encapsulates the database provider information and hence acts like a connection factory by fetching connections to talk to the database. It should be created by driver information such as URL, username, password, and other information. Make sure that you supply the nec- essary provider (driver) information to construct a DataSource if you are using any other databases. The datasource-beans.xml file shown below creates a DataSource for MySQL database: <bean id="mySqlDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/JSDATA" /> .... </bean> The class attribute points to an implementor of the DataSource interface; in the above snippet, it is a BasicDataSource class from Apache Common’s DBCP project. The driverClassName points to a class that will be specific to a database. We will see the full definition in a minute. Throughout the book, we will use DBCP datasource, which can be downloaded from the site: http://commons.apache.org/dbcp/. If you are using Maven, add the snippet to your pom.xml file (check out the full pom.xml provided with the book’s source code) to include DBCP and MySQL connector jars: <!-- pom.xml --> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.18</version> </dependency> Using JdbcTemplate The JdbcTemplate is a framework class utilized for data access operations such as quer- ies, inserts, and deletes. It is the fundamental class in the framework, so we dwell on it in detail here. Note that the JdbcTemplate is a thread safe class—it can be easily shared across your threads. One of the biggest advantages in using the JdbcTemplate is its ability to clean up resources. Most developers forget to close the JDBC connections and other related 4 | Chapter 1: Basics www.it-ebooks.info
📄 Page
17
resources, which leads to lots of issues. JdbcTemplate comes to our rescue in doing the house cleaning job for us! Before we work with JdbcTemplate, we must set the DataSource first. This is a mandatory requirement that JdbcTemplate be configured with a DataSource object so the template will be able to create connections and statements behind the scenes. Configuring a DataSource As we have already seen, the javax.sql.DataSource is an interface that determines the connection details for a particular provider. Each provider will have their own imple- mentation of the class, usually provided in a Jar file. The MySQL driver class is defined by the com.mysql.jdbc.Driver class, for example. The following configuration shows how to set up a data source for MySQL: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <!-- MySql DataSource --> <bean id="mySqlDataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/JSDATA"/> <property name="username" value="jsuser"/> <property name="password" value="jsuser"/> </bean> </beans> The above snippet will create a bean named mySqlDataSource that points to a MySQL database running on localhost, directed by the url property. If we are using other pro- viders, we need to create another bean with the same properties, but with appropriate values relevant to our provider. Configuring JdbcTemplate Now that the data source has been configured, the next step is to create and work with the JdbcTemplate class. There are couple of ways to create this class. One is to create an instance in your class and provide a preconfigured data source, and the other is to create and instantiate the bean in the configuration file and inject it into your Data Access Object (DAO) classes. The DAOs are the classes that talk to databases in order to fulfill the data access func- tions. Templates | 5 www.it-ebooks.info
📄 Page
18
Let’s see an example of instantiating JdbcTemplate with a preconfigured DataSource. public class JdbcTemplateTest { private ApplicationContext ctx = null; private JdbcTemplate template = null; private DataSource datasource = null; public JdbcTemplateTest() { // Create a container forming the beans from datasource XML file ctx = new ClassPathXmlApplicationContext("datasources-beans.xml"); // DataSource bean has been fetched from the container datasource = ctx.getBean("mySqlDataSource",DataSource.class); // Instantiate the template with the datasource template = new JdbcTemplate(datasource); } public static void main(String[] args) { JdbcTemplateTest t = new JdbcTemplateTest(); // execute the data access methods from here .... } } The steps are simple: • Load and fetch the context from a config file that consists of datasources (in our case, it’s the datasouces-beans.xml) • Create the JdbcTemplate using the new operator providing the datasource bean to its constructor Once you have the JdbcTemplate fully configured and functional, you are ready to use it to access our databast tables. The JdbcTemplate has a lot of functionality that requires a bit of detail study. Working with JdbcTemplate The JdbcTemplate has more than 100 methods that give varied access to data sets! For example, you may wish to execute straight queries such as inserting data or creating tables. You can use the execute() method exposed on the JdbcTemplate for such actions. Likewise, if you wish to query for single or multiple data rows, you should be using queryForXXX methods. There are lots of other methods, some of them are self explana- tory and others are easy to follow using JavaDoc. We will cover the most important of all of these methods in the coming sections. Let’s say our requirement is to find out the number of rows present in the TRADES table. Querying for Single and Multiple Rows. 6 | Chapter 1: Basics www.it-ebooks.info
📄 Page
19
The following snippet shows the usage of JdbcTemplate in its simplest form—for fetch- ing the number of TRADES in the table: public int getTradesCount(){ int numOfTrades = template.queryForInt("select count(*) from TRADES"); return numOfTrades; } The queryForInt() method returns the count(*) equivalent from the table. The return type is obviously an integer. There are few variants of queryForXXX methods such as queryForString, queryForLong, queryForMap, and queryForObject. Basically, these are facility methods that convert your column value to an appropriate data type. You can also rewrite the above example by using the more generic queryForObject method. However, the method takes a second parameter, which basically describes the return value’s data type. In our example, because count(*) will return an integer, we pass the Integer class to the method call. This is illustrated below: public int getTradesCount(){ int numOfTrades = template.queryForObject("select count(*) from TRADES",Integer.class); return numOfTrades; } // Another example of get the max id of the // trade using queryForObject method public int getTradeMaxId(){ int maxId = template.queryForObject("select max(id) from TRADES", Integer.class); return maxId; } The above snippet also provides another example of using the queryForObject method to query for a Trade that has a maximum id. The queryForLong and queryForString follow the same pattern, returning a Long and String value, respectively. The queryForMap returns a single row in a Map<String,Object> format as shown below: public Map<String,Object> getTradeAsMap(){ // note that we have hardcoded ID here! Map<String,Object> tradeAsMap = template.queryForMap("select * from TRADES where id=1"); System.out.println("Trades Map:"+tradeAsMap); return tradeAsMap; } Templates | 7 www.it-ebooks.info
📄 Page
20
//The output to the console is: Trades Map:{ID=1, ACCOUNT=1234AAA, SECURITY=MDMD, QUANTITY=100000, STATUS=NEW, DIRECTION=BUY} As you can see, each column name is the key represented by String while the value is represented by the Object in the Map<String,Object> declaration. However, the queryForList is a bit different to others in that it can return multiple rows. The rows are returned as a List of Map<String,Object> format. Let’s see this at work. The getAllTrades() method fetches all of the trades and prints out to the console: public List<Map<String,Object>> getAllTrades(){ List<Map<String,Object>> trades = template.queryForList("select * from TRADES"); System.out.println("All Trades:"+trades); return trades; } //Prints to console as: All Trades: [{ID=1, ACCOUNT=1234AAA, ... STATUS=NEW, DIRECTION=BUY}, ..., {ID=5, ACCOUNT=452SEVE, ... STATUS=NEW, DIRECTION=SELL}] The queries that we used in the above examples are fairly simple. We can also write complex queries that can be executed in the same fashion. We often use where clauses and other SQL constructs to execute complex queries. However, the where clause re- quires input variables to be set. How can we parameterize these bind variables? Bind variables help to create a dynamic SQL query. If our requirement is to fetch records based on various conditions, we usually use the where clause in our SQL script. Bind variables are the preferred option as opposed to using inline variables because they protect our application against SQL injection attacks. For example, if we have to get the STATUS of a Trade whose id is 5, we need to write the SQL as follows: public String getTradeStatus(int id){ String status = template.queryForObject("select STATUS from TRADES where id= ?", new Object[]{id}, String.class); return status; } Bind Variables. 8 | Chapter 1: Basics www.it-ebooks.info