diff --git a/README b/README
index 9af179f..f9f0101 100644
--- a/README
+++ b/README
@@ -1,5 +1,5 @@
========================================================================================================================
-README - Spring in Practice Recipe 2.1
+README - Spring in Practice Recipe 2.3
Copyright (c) 2013 Manning Publications Co.
@@ -10,4 +10,4 @@ Blog: http://springinpractice.com/
Code: https://github.com/springinpractice
========================================================================================================================
-Shows how to use Spring's JdbcTemplate for data access.
+Shows how to use object/relational mapping for database access.
diff --git a/pom.xml b/pom.xml
index 327780a..27cb730 100644
--- a/pom.xml
+++ b/pom.xml
@@ -25,11 +25,11 @@ Code: https://github.com/springinpractice
1.0-RELEASE
- com.springinpractice.02_01
+ com.springinpractice.02_03
war
- Spring in Practice Section 2.1
- Shows how to use Spring's JdbcTemplate for data access.
+ Spring in Practice Section 2.3
+ Shows how to use object/relational mapping for database access.
http://springinpractice.com/
@@ -43,6 +43,13 @@ Code: https://github.com/springinpractice
com.springinpractice.api
1.0-RELEASE
+
+ com.springinpractice
+ com.springinpractice.deps-hibernate
+ 1.0-RELEASE
+ pom
+ true
+
${project.groupId}
com.springinpractice.deps-web
@@ -57,10 +64,6 @@ Code: https://github.com/springinpractice
-
- org.springframework
- org.springframework.jdbc
-
com.mysql.jdbc
com.springsource.com.mysql.jdbc
@@ -76,6 +79,9 @@ Code: https://github.com/springinpractice
org.mortbay.jetty
maven-jetty-plugin
+
+ ${chapter.conf.dir}/jetty-env.xml
+
diff --git a/sample_conf/classes/spring/environment.properties b/sample_conf/classes/spring/environment.properties
deleted file mode 100644
index e745ea7..0000000
--- a/sample_conf/classes/spring/environment.properties
+++ /dev/null
@@ -1,4 +0,0 @@
-dataSource.driverClassName=com.mysql.jdbc.Driver
-dataSource.url=jdbc:mysql://localhost:3306/sip02?autoReconnect=true
-dataSource.username=sip
-dataSource.password=sip
diff --git a/sample_conf/jetty-env.xml b/sample_conf/jetty-env.xml
new file mode 100644
index 0000000..12bce5d
--- /dev/null
+++ b/sample_conf/jetty-env.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+ jdbc/Sip02DS
+
+
+ com.mysql.jdbc.Driver
+ jdbc:mysql://localhost:3306/sip02?autoReconnect=true
+ sip
+ sip
+
+
+
+
diff --git a/src/main/java/com/springinpractice/ch02/model/Contact.java b/src/main/java/com/springinpractice/ch02/model/Contact.java
index fb82e58..8255698 100644
--- a/src/main/java/com/springinpractice/ch02/model/Contact.java
+++ b/src/main/java/com/springinpractice/ch02/model/Contact.java
@@ -7,6 +7,14 @@
*/
package com.springinpractice.ch02.model;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import javax.persistence.Transient;
import javax.validation.constraints.NotNull;
import org.hibernate.validator.constraints.Email;
@@ -17,6 +25,11 @@
/**
* @author Willie Wheeler (willie.wheeler@gmail.com)
*/
+@Entity
+@Table(name = "contact")
+@NamedQuery(
+ name = "findContactsByEmail",
+ query = "from Contact where email like :email")
public class Contact {
private Long id;
private String lastName;
@@ -24,12 +37,16 @@ public class Contact {
private String middleInitial;
private String email;
+ @Id
+ @Column
+ @GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
@NotNull
@Length(min = 1, max = 40)
+ @Column(name = "last_name")
public String getLastName() { return lastName; }
public void setLastName(String lastName) {
@@ -38,6 +55,7 @@ public void setLastName(String lastName) {
@NotNull
@Length(min = 1, max = 40)
+ @Column(name = "first_name")
public String getFirstName() { return firstName; }
public void setFirstName(String firstName) {
@@ -45,6 +63,7 @@ public void setFirstName(String firstName) {
}
@Length(max = 1)
+ @Column(name = "mi")
public String getMiddleInitial() { return middleInitial; }
public void setMiddleInitial(String mi) {
@@ -52,12 +71,14 @@ public void setMiddleInitial(String mi) {
}
@Email
+ @Column
public String getEmail() { return email; }
public void setEmail(String email) {
this.email = StringUtils.cleanup(email);
}
+ @Transient
public String getFullName() {
String fullName = lastName + ", " + firstName;
if (! (middleInitial == null || "".equals(middleInitial.trim()))) {
diff --git a/src/main/java/com/springinpractice/ch02/service/impl/ContactRowMapper.java b/src/main/java/com/springinpractice/ch02/service/impl/ContactRowMapper.java
deleted file mode 100644
index 22072c2..0000000
--- a/src/main/java/com/springinpractice/ch02/service/impl/ContactRowMapper.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2013 Manning Publications Co.
- *
- * Book: http://manning.com/wheeler/
- * Blog: http://springinpractice.com/
- * Code: https://github.com/springinpractice
- */
-package com.springinpractice.ch02.service.impl;
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-import org.springframework.jdbc.core.RowMapper;
-import org.springframework.stereotype.Component;
-
-import com.springinpractice.ch02.model.Contact;
-
-/**
- * @version $Id$
- * @author Willie Wheeler (willie.wheeler@gmail.com)
- */
-@Component
-public class ContactRowMapper implements RowMapper {
-
- @Override
- public Contact mapRow(ResultSet resultSet, int rowNum) throws SQLException {
- Contact contact = new Contact();
- contact.setId(resultSet.getLong(1));
- contact.setLastName(resultSet.getString(2));
- contact.setFirstName(resultSet.getString(3));
- contact.setMiddleInitial(resultSet.getString(4));
- contact.setEmail(resultSet.getString(5));
- return contact;
- }
-}
diff --git a/src/main/java/com/springinpractice/ch02/service/impl/ContactServiceImpl.java b/src/main/java/com/springinpractice/ch02/service/impl/ContactServiceImpl.java
index 0dcb408..c1096b0 100644
--- a/src/main/java/com/springinpractice/ch02/service/impl/ContactServiceImpl.java
+++ b/src/main/java/com/springinpractice/ch02/service/impl/ContactServiceImpl.java
@@ -9,17 +9,14 @@
import static org.springframework.util.Assert.notNull;
-import java.util.HashMap;
import java.util.List;
import javax.inject.Inject;
-import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
-import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
-import org.springframework.jdbc.core.namedparam.SqlParameterSource;
-import org.springframework.jdbc.support.GeneratedKeyHolder;
-import org.springframework.jdbc.support.KeyHolder;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
import com.springinpractice.ch02.model.Contact;
import com.springinpractice.ch02.service.ContactService;
@@ -31,71 +28,53 @@
* @author Willie Wheeler (willie.wheeler@gmail.com)
*/
@Service
+@Transactional
public class ContactServiceImpl implements ContactService {
- private static final String CREATE_SQL =
- "insert into contact (last_name, first_name, mi, email) values (:lastName, :firstName, :mi, :email)";
- private static final String FIND_ALL_SQL =
- "select id, last_name, first_name, mi, email from contact";
- private static final String FIND_ALL_BY_EMAIL_LIKE_SQL =
- "select id, last_name, first_name, mi, email from contact where email like :email";
- private static final String FIND_ONE_SQL =
- "select id, last_name, first_name, mi, email from contact where id = :id";
- private static final String UPDATE_SQL =
- "update contact set last_name = :lastName, first_name = :firstName, mi = :mi, email = :email " +
- "where id = :id";
- private static final String DELETE_SQL =
- "delete from contact where id = :id";
-
- @Inject private NamedParameterJdbcOperations jdbcTemplate;
- @Inject private ContactRowMapper contactRowMapper;
+ @Inject private SessionFactory sessionFactory;
@Override
public void createContact(Contact contact) {
notNull(contact, "contact can't be null");
- SqlParameterSource params = new MapSqlParameterSource()
- .addValue("lastName", contact.getLastName())
- .addValue("firstName", contact.getFirstName())
- .addValue("mi", contact.getMiddleInitial())
- .addValue("email", contact.getEmail());
- KeyHolder keyHolder = new GeneratedKeyHolder();
- jdbcTemplate.update(CREATE_SQL, params, keyHolder);
- contact.setId(keyHolder.getKey().longValue());
+ getSession().save(contact);
}
@Override
+ @SuppressWarnings("unchecked")
public List getContacts() {
- return jdbcTemplate.query(FIND_ALL_SQL, new HashMap(), contactRowMapper);
+ return getSession()
+ .createQuery("from Contact")
+ .list();
}
@Override
+ @SuppressWarnings("unchecked")
public List getContactsByEmail(String email) {
notNull(email, "email can't be null");
- SqlParameterSource params = new MapSqlParameterSource("email", "%" + email + "%");
- return jdbcTemplate.query(FIND_ALL_BY_EMAIL_LIKE_SQL, params, contactRowMapper);
+ return getSession()
+ .getNamedQuery("findContactsByEmail")
+ .setString("email", "%" + email + "%")
+ .list();
}
@Override
public Contact getContact(Long id) {
notNull(id, "id can't be null");
- SqlParameterSource params = new MapSqlParameterSource("id", id);
- return jdbcTemplate.queryForObject(FIND_ONE_SQL, params, contactRowMapper);
+ return (Contact) getSession().get(Contact.class, id);
}
@Override
public void updateContact(Contact contact) {
notNull(contact, "contact can't be null");
- SqlParameterSource params = new MapSqlParameterSource()
- .addValue("id", contact.getId())
- .addValue("lastName", contact.getLastName())
- .addValue("firstName", contact.getFirstName())
- .addValue("mi", contact.getMiddleInitial())
- .addValue("email", contact.getEmail());
- jdbcTemplate.update(UPDATE_SQL, params);
+ getSession().update(contact);
}
@Override
public void deleteContact(Long id) {
notNull(id, "id can't be null");
- jdbcTemplate.update(DELETE_SQL, new MapSqlParameterSource("id", id));
+ getSession().delete(getContact(id));
+ }
+
+ private Session getSession() {
+ return sessionFactory.getCurrentSession();
}
}
diff --git a/src/main/resources/spring/beans-service.xml b/src/main/resources/spring/beans-service.xml
index 3e51214..801b1b7 100644
--- a/src/main/resources/spring/beans-service.xml
+++ b/src/main/resources/spring/beans-service.xml
@@ -16,26 +16,41 @@ Code: https://github.com/springinpractice
+ http://www.springframework.org/schema/context/spring-context-3.1.xsd
+ http://www.springframework.org/schema/jee
+ http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
+ http://www.springframework.org/schema/tx
+ http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
+ http://www.springframework.org/schema/util
+ http://www.springframework.org/schema/util/spring-util-3.1.xsd">
-
+
-
+
+ org.hibernate.dialect.MySQL5InnoDBDialect
+ false
+
-
+
-
+
+
+
+
+
diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml
index a1adf72..c99c5b9 100644
--- a/src/main/webapp/WEB-INF/web.xml
+++ b/src/main/webapp/WEB-INF/web.xml
@@ -11,12 +11,12 @@
recipe
- 2.1
+ 2.3
aboutThisRecipe
Shows how to use Spring's JdbcTemplate for data access.
+Shows how to use object/relational mapping for database access.
]]>