EMMA Coverage Report (generated Fri Jan 30 13:20:29 EST 2009)
[all classes][org.springframework.batch.item.database]

COVERAGE SUMMARY FOR SOURCE FILE [HibernateCursorItemReader.java]

nameclass, %method, %block, %line, %
HibernateCursorItemReader.java100% (1/1)91%  (10/11)97%  (161/166)96%  (45.9/48)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class HibernateCursorItemReader100% (1/1)91%  (10/11)97%  (161/166)96%  (45.9/48)
setFetchSize (int): void 0%   (0/1)0%   (0/4)0%   (0/2)
afterPropertiesSet (): void 100% (1/1)93%  (14/15)98%  (3.9/4)
HibernateCursorItemReader (): void 100% (1/1)100% (23/23)100% (6/6)
createQuery (): Query 100% (1/1)100% (25/25)100% (5/5)
doClose (): void 100% (1/1)100% (27/27)100% (9/9)
doOpen (): void 100% (1/1)100% (21/21)100% (4/4)
doRead (): Object 100% (1/1)100% (23/23)100% (7/7)
mark (): void 100% (1/1)100% (9/9)100% (4/4)
setQueryString (String): void 100% (1/1)100% (4/4)100% (2/2)
setSessionFactory (SessionFactory): void 100% (1/1)100% (4/4)100% (2/2)
setUseStatelessSession (boolean): void 100% (1/1)100% (11/11)100% (3/3)

1/*
2 * Copyright 2006-2007 the original author or authors.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.springframework.batch.item.database;
17 
18import org.hibernate.Query;
19import org.hibernate.ScrollMode;
20import org.hibernate.ScrollableResults;
21import org.hibernate.Session;
22import org.hibernate.SessionFactory;
23import org.hibernate.StatelessSession;
24import org.springframework.batch.item.ItemReader;
25import org.springframework.batch.item.ItemStream;
26import org.springframework.batch.item.support.AbstractBufferedItemReaderItemStream;
27import org.springframework.beans.factory.InitializingBean;
28import org.springframework.util.Assert;
29import org.springframework.util.ClassUtils;
30 
31/**
32 * {@link ItemReader} for reading database records built on top of Hibernate.
33 * 
34 * It executes the HQL {@link #setQueryString(String)} when initialized and
35 * iterates over the result set as {@link #read()} method is called, returning
36 * an object corresponding to current row.
37 * 
38 * The reader can be configured to use either {@link StatelessSession}
39 * sufficient for simple mappings without the need to cascade to associated
40 * objects or standard hibernate {@link Session} for more advanced mappings or
41 * when caching is desired.
42 * 
43 * When stateful session is used it will be cleared after successful commit
44 * without being flushed (no inserts or updates are expected).
45 * 
46 * Reset(rollback) functionality is implemented by item buffering allowing the
47 * cursor used to be forward-only.
48 * 
49 * The implementation is *not* thread-safe.
50 * 
51 * @author Robert Kasanicky
52 * @author Dave Syer
53 */
54public class HibernateCursorItemReader extends AbstractBufferedItemReaderItemStream implements ItemStream,
55                InitializingBean {
56 
57        private SessionFactory sessionFactory;
58 
59        private StatelessSession statelessSession;
60 
61        private Session statefulSession;
62 
63        private ScrollableResults cursor;
64 
65        private String queryString;
66 
67        private boolean useStatelessSession = true;
68 
69        private boolean initialized = false;
70 
71        private int fetchSize = 0;
72 
73        public HibernateCursorItemReader() {
74                setName(ClassUtils.getShortName(HibernateCursorItemReader.class));
75        }
76 
77        /**
78         * Open appropriate type of hibernate session and create the query.
79         */
80        private Query createQuery() {
81                if (useStatelessSession) {
82                        statelessSession = sessionFactory.openStatelessSession();
83                        return statelessSession.createQuery(queryString);
84                }
85                else {
86                        statefulSession = sessionFactory.openSession();
87                        return statefulSession.createQuery(queryString);
88                }
89        }
90 
91        /**
92         * @param sessionFactory hibernate session factory
93         */
94        public void setSessionFactory(SessionFactory sessionFactory) {
95                this.sessionFactory = sessionFactory;
96        }
97 
98        public void afterPropertiesSet() throws Exception {
99                Assert.notNull(sessionFactory);
100                Assert.hasLength(queryString);
101                Assert.isTrue(fetchSize >= 0, "fetchSize must not be negative");
102        }
103 
104        /**
105         * @param queryString HQL query string
106         */
107        public void setQueryString(String queryString) {
108                this.queryString = queryString;
109        }
110 
111        /**
112         * Can be set only in uninitialized state.
113         * 
114         * @param useStatelessSession <code>true</code> to use
115         * {@link StatelessSession} <code>false</code> to use standard hibernate
116         * {@link Session}
117         */
118        public void setUseStatelessSession(boolean useStatelessSession) {
119                Assert.state(!initialized);
120                this.useStatelessSession = useStatelessSession;
121        }
122 
123        /**
124         * Mark is supported as long as this {@link ItemStream} is used in a
125         * single-threaded environment. The state backing the mark is a single
126         * counter, keeping track of the current position, so multiple threads
127         * cannot be accommodated.
128         * 
129         * @see org.springframework.batch.item.ItemReader#mark()
130         */
131        public void mark() {
132 
133                super.mark();
134 
135                if (!useStatelessSession) {
136                        statefulSession.clear();
137                }
138        }
139 
140        /**
141         * Gives the JDBC driver a hint as to the number of rows that should be
142         * fetched from the database when more rows are needed for this
143         * <code>ResultSet</code> object. If the fetch size specified is zero, the
144         * JDBC driver ignores the value.
145         * 
146         * @param fetchSize the number of rows to fetch, 0 by default
147         * @see Query#setFetchSize(int)
148         */
149        public void setFetchSize(int fetchSize) {
150                this.fetchSize = fetchSize;
151        }
152 
153        protected Object doRead() throws Exception {
154                if (cursor.next()) {
155                        Object[] data = cursor.get();
156                        Object item;
157 
158                        if (data.length > 1) {
159                                item = data;
160                        }
161                        else {
162                                item = data[0];
163                        }
164 
165                        return item;
166                }
167                return null;
168        }
169 
170        /**
171         * Open hibernate session and create a forward-only cursor for the
172         * {@link #setQueryString(String)}.
173         */
174        protected void doOpen() throws Exception {
175                Assert.state(!initialized, "Cannot open an already opened ItemReader, call close first");
176 
177                cursor = createQuery().setFetchSize(fetchSize).scroll(ScrollMode.FORWARD_ONLY);
178 
179                initialized = true;
180 
181        }
182 
183        /**
184         * Close the cursor and hibernate session.
185         */
186        protected void doClose() throws Exception {
187                initialized = false;
188 
189                if (cursor != null) {
190                        cursor.close();
191                }
192                if (useStatelessSession) {
193                        if (statelessSession != null) {
194                                statelessSession.close();
195                        }
196                }
197                else {
198                        if (statefulSession != null) {
199                                statefulSession.close();
200                        }
201                }
202 
203        }
204}

[all classes][org.springframework.batch.item.database]
EMMA 2.0.5312 (C) Vladimir Roubtsov