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.

]]>