Publicado el 21 de Enero del 2019
713 visualizaciones desde el 21 de Enero del 2019
316,5 KB
22 paginas
Experto Universitario Java Enterprise
Spring
Sesión 2: Acceso a datos
1
Experto Universitario Java Enterprise
Puntos a tratar
• Por qué usar Spring para acceso a datos
• Problemas típicos de JDBC
• JDBC con Spring
• JPA con Spring
• Transaccionalidad declarativa
Spring
© 2012-2013 Depto. Ciencia de la Computación e IA
Acceso a datos
2
Experto Universitario Java Enterprise
Por qué usar el acceso a datos de Spring
• Spring no nos obliga a usar su módulo DAO, es decisión
nuestra aprovecharlo o usar el API que queramos
directamente
• Simplifica el código de los DAOs en APIs tediosos como
JDBC
• Gracias a los templates
• Permite usar también directamente el API si lo
preferimos
• Ofrece una rica jerarquía de excepciones independiente
del API de acceso a datos
Spring
© 2012-2013 Depto. Ciencia de la Computación e IA
Acceso a datos
3
Experto Universitario Java Enterprise
Código típico JDBC
public UsuarioTO login(String login, String password) throws DAOException {
Connection con=null;
try {
con = ds.getConnection();
PreparedStatement ps = con.prepareStatement(SQL);
ps.setString(1, login);
ps.setString(2, password);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
UsuarioTO uto = new UsuarioTO();
uto.setLogin(rs.getString("login"));
uto.setPassword(rs.getString("password"));
uto.setFechaNac(rs.getDate("fechaNac"));
return uto;
}
else
return null;
} catch(SQLException sqle) {
throw new DAOException(sqle);
}
Código “útil”
Infraestructura
Spring
© 2012-2013 Depto. Ciencia de la Computación e IA
Acceso a datos
4
Experto Universitario Java Enterprise
Código típico JDBC (II)
finally {
if (con!=null) {
try {
con.close();
}
catch(SQLException sqle2) {
throw new DAOException(sqle2);
}
}
}
Spring
© 2012-2013 Depto. Ciencia de la Computación e IA
Acceso a datos
5
Código “útil”
Infraestructura
Experto Universitario Java Enterprise
Solución 1: Templates
• El código anterior es demasiado largo. Si siempre
hay que abrir una conexión al principio y cerrarla
al final ¿por qué lo tenemos que hacer
explícitamente?
• Template: ya tiene implementadas las partes que se
hacen siempre. Solo tenemos que implementar lo que
cambia
• Hay templates para JDBC, JPA, Hibernate, myBatis,...
Nuestro código no va a ser independiente del API, pero
sí más corto que si usamos el API directamente
Spring
© 2012-2013 Depto. Ciencia de la Computación e IA
Acceso a datos
6
Experto Universitario Java Enterprise
Problema 2: Excepciones JDBC
• En JDBC, hay muy pocas. SQLException se usa para todo
• APIs como Hibernate definen muchas más, pero son exclusivas del API
• Si son comprobadas, hay que poner try/catch o throws
• Si fuerzas a la gente a poner catch, puedes conseguir que acabe
poniendo catch vacíos (lo sé, vosotros no lo haríais nunca, yo
tengo que confesar que sí)
• Además, normalmente un DAO poco puede hacer por gestionar/
arreglar una excepción (bueno, pues que la lance para arriba)
• Pero si casi siempre la tiene que lanzar ¿no es también un poco
tedioso poner siempre throws?
Spring
© 2012-2013 Depto. Ciencia de la Computación e IA
Acceso a datos
7
Experto Universitario Java Enterprise
Solución 2: Excepciones DAO en Spring
• De modo transparente, capturar la excepción del API que
se está usando y transformarla en una propia de Spring,
independiente del API
• Hay muchas: DataAccessResourceFailureException (no hay
conexión con la BD), DataIntegrityViolationException (clave
duplicada),...
• Al poner @Repository, se activa esta traslación automática
• Hacer todas las excepciones de acceso a datos no
comprobadas
• Todas las anteriores heredan de DataAccessException, que
hereda de RuntimeException
Spring
© 2012-2013 Depto. Ciencia de la Computación e IA
Acceso a datos
8
Experto Universitario Java Enterprise
JDBC en Spring con JDBCTemplate
• En Spring hay muchos más templates para JDBC, pero este
aprovecha Java 5, simplificando mucho el código
• Práctica habitual
• Nuestro DAO guarda una referencia al template
• Cuando nos inyecten el DataSource instanciamos el template
<jee:jndi-lookup id="ds" jndi-name="jdbc/MiDataSource"
resource-ref="true"/>
(en el XML con los beans)
@Repository("JDBC")
public class UsuariosDAOJDBC {
private JdbcTemplate jdbcTemplate;
@Autowired
public void setDataSource(DataSource ds) {
this.jdbcTemplate = new JdbcTemplate(ds);
}
Spring
© 2012-2013 Depto. Ciencia de la Computación e IA
Acceso a datos
9
Experto Universitario Java Enterprise
SELECT con JDBCTemplate
• Normalmente cada registro del ResultSet va a acabar siendo un TO. El
encargado de hacer esto en Spring es el RowMapper, cuyo interfaz
debemos implementar
public class UsuarioTOMapper implements RowMapper<UsuarioTO> {
public UsuarioTO mapRow(ResultSet rs, int numRow) throws SQLException {
UsuarioTO uto = new UsuarioTO();
uto.setLogin(rs.getString("login"));
uto.setPassword(rs.getString("password"));
uto.setFechaNac(rs.getDate("fechaNac"));
return uto;
}
}
Spring
© 2012-2013 Depto. Ciencia de la Computación e IA
Acceso a datos
10
Experto Universitario Java Enterprise
SELECT con JDBCTemplate (II)
• Para hacer el SELECT
• Si esperamos un solo objeto, queryForObject()
private static final String LOGIN_SQL = "select * from usuarios “ +
“where login=? and password=?";
public UsuarioTO login(String login, String password) {
//El row mapper de antes
UsuarioTOMapper miMapper = new UsuarioTOMapper();
try {
return this.jdbcTemplate.queryForObject(LOGIN_SQL, miMapper,
}
//¡Que conste que la capturo porque quiero! (es no comprobada)
catch(EmptyResultDataAccessException erdae) {
return null;
}
}
login, password);
Spring
© 2012-2013 Depto. Ciencia de la Computación e IA
Acceso a datos
11
Experto Universitario Java Enterprise
SELECT con JDBCTemplate (III)
• Para hacer el SELECT
• Si esperamos varios objetos, query()
private static final String LIST_SQL = "select * from usuarios “ +
“where localidad=?";
public List<UsuarioTO> listarPorLocalidad(String localidad) {
//El row mapper de antes
UsuarioTOMapper miMapper = new UsuarioTOMapper();
try {
return this.jdbcTemplate.query(LIST_SQL, miMapper, localidad);
}
//¡Que conste que la capturo porque quiero! (es no comprobada)
catch(EmptyResultDataAccessException erdae) {
return null;
}
}
Spring
© 2012-2013 Depto. Ciencia de la Computación e IA
Acceso a datos
12
Experto Universitario Java Enterprise
UPDATE con JDBCTemplate
private static final String REGISTRAR_SQL = "insert into usuarios” +
(login, password, fechaNac) values (?,?,?)";
public void registrar(UsuarioTO uto) {
this.jdbcTemplate.update(REGISTRAR_SQL, uto.getLogin(),
}
uto.getPassword(), uto.getFechaNac());
Spring
© 2012-2013 Depto. Ciencia de la Computación e IA
Acceso a datos
13
Experto Universitario Java Enterprise
JPA: opciones de configuración
• JPA gestionado por la aplicación
• JPA gestionado por el contenedor
• Directamente, para servidores de aplicaciones, que
tendrán soporte “nativo”
• También es posible para servidores web, como
Tomcat, el soporte lo proporciona Spring
• En cualquiera de los casos, podemos usar
anotaciones para inyectar el EM. Spring se ocupa
de los detalles
Spring
© 2012-2013 Depto. Ciencia de la Computación e IA
Acceso a datos
14
Experto Universitario Java Enterprise
Necesitamos un bean que
“fabrique” EMs
<beans xmlns="http://www.springframework.org/schema/beans"
…"> (faltan “cabeceras”, ver apuntes para código completo)
<context:component-scan base-package="es.ua.jtech"/>
<jee:jndi-lookup id="miDS" jndi-name="jdbc/MiDataSource” resource-ref="true"/>
<bean id="miEMF"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="showSql" value="true"/>
<property name="dataSource" ref="miDS"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="true"/>
<property name="databasePlatform“ value="org.hibernate.dialect.HSQLDialect"/>
</bean>
</property>
</bean>
</beans>
Spring
© 2012-2013 Depto. Ciencia de la Computación e IA
Acceso a datos
15
Experto Universitario Java Enterprise
JPA: opciones para el código
• Hay dos opciones
• Usar JPATemplate: al ser JPA un API bastante
conciso, no ganaremos mucho en código
• Usar el API JPA directamente. Esta segunda opción es
la que recomienda la propia documentación de Spring.
No atamos nuestro código al API de Spring y este será
portable directamente a cualquier servidor de
aplicaciones
Spring
© 2012-2013 Depto. Ciencia de la Computación e IA
Acceso a datos
16
Experto Universitario Java Enterprise
Código JPA “estándar”
• Lo único que tiene de especial es que funciona
en Tomcat y similares
@Repository("JPA")
public class UsuariosDAOJPA implements IUsuariosDAO {
@PersistenceContext
EntityManager em;
public UsuarioTO login(String login, String password) {
UsuarioTO uto = em.find(UsuarioTO.class, login);
if (uto!=null && password.equals(uto.getPassword()))
return uto;
else
return null;
}
}
Spring
© 2012-2013 Depto. Ciencia de la Computación e IA
Acce
Comentarios de: Spring - Sesión 2: Acceso a datos (0)
No hay comentarios