Spring MVC Acceso a datos
Anteriormente creamos una serie de tutoriales dedicados al acceso a datos con Spring Framework, ahora veremos como podemos integrar las tecnologías de datos en una aplicación Spring Web MVC, nos centraremos en la tecnología Spring Data JPA utilizando el ORM Hibernate y el motor de datos integrado HSQLDB, aunque lo aprendido se puede aplicar fácilmente a otros tecnologías.
Todos los conceptos aplicados en este tutorial ya los hemos visto en tutoriales anteriores por lo que la explicación será breve, si deseas información mas detallada puedes dirigirte a los correspondientes tutoriales, en el siguiente enlace encontrarás una lista de todos ellos: Tutoriales Spring Framework.
La configuración del Servlet la haremos programáticamente, sin XML, tratamos este tema en el tutorial Configurar Spring MVC con Java, la clase correspondiente es la siguiente:
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{RootAppConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebAppConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
La clase WebAppConfig
contiene la configuración web y la clase RootAppConfig
la configuración de acceso a datos, veamos primero la configuración del WebApplicationContext
.
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"carmelo.spring.controller"})
public class WebAppConfig {
@Bean
public ViewResolver getInternalResourceViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
}
Esta configuración también al hemos visto en tutoriales anteriores, lo siguiente que veremos será la configuración de acceso a datos, para ello tenemos la siguiente clase:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories("carmelo.spring.repository")
@ComponentScan("carmelo.spring.service")
public class RootAppConfig {
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addDefaultScripts()
.generateUniqueName(true)
.build();
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean factoryBean
= new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(dataSource());
factoryBean.setJpaVendorAdapter(jpaVendorAdapter());
factoryBean.setPackagesToScan("carmelo.spring.model");
factoryBean.setPersistenceUnitName("spring-data-pun");
return factoryBean;
}
@Bean
public JpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
jpaVendorAdapter.setGenerateDdl(false);
jpaVendorAdapter.setDatabase(Database.HSQL);
return jpaVendorAdapter;
}
@Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
}
La explicación de esta clase la tenemos disponible en la seria de tutoriales Spring IoC Acceso a Datos, de manera breve configuramos una base de datos HSQLDB como fuente de datos, para las operaciones de acceso a datos usamos el ORM Hibernate JPA.
Para crear las tablas de nuestra base de datos tenemos el siguiente script:
CREATE TABLE Customer(
ID INTEGER PRIMARY KEY,
FirstName VARCHAR(20),
LastName VARCHAR(30),
Street VARCHAR(50),
City VARCHAR(25));
CREATE TABLE Product(
ID INTEGER PRIMARY KEY,
Name VARCHAR(30),
Price DOUBLE);
Agregamos datos a estas tablas con este otro script:
INSERT INTO Customer VALUES(0,'Laura','Steel','429 Seventh Av.','Dallas');
INSERT INTO Product VALUES(0,'Iron Iron',54);
INSERT INTO Customer VALUES(1,'Susanne','King','366 - 20th Ave.','Olten');
INSERT INTO Product VALUES(1,'Chair Shoe',248);
INSERT INTO Customer VALUES(2,'Anne','Miller','20 Upland Pl.','Lyon');
INSERT INTO Product VALUES(2,'Telephone Clock',248);
INSERT INTO Customer VALUES(3,'Michael','Clancy','542 Upland Pl.','San Francisco');
INSERT INTO Product VALUES(3,'Chair Chair',254);
INSERT INTO Customer VALUES(4,'Sylvia','Ringer','365 College Av.','Dallas');
INSERT INTO Product VALUES(4,'Ice Tea Shoe',128);
INSERT INTO Customer VALUES(5,'Laura','Miller','294 Seventh Av.','Paris');
INSERT INTO Product VALUES(5,'Clock Clock',236);
INSERT INTO Customer VALUES(6,'Laura','White','506 Upland Pl.','Palo Alto');
INSERT INTO Product VALUES(6,'Ice Tea Chair',98);
INSERT INTO Customer VALUES(7,'James','Peterson','231 Upland Pl.','San Francisco');
INSERT INTO Product VALUES(7,'Telephone Shoe',84);
INSERT INTO Customer VALUES(8,'Andrew','Miller','288 - 20th Ave.','Seattle');
INSERT INTO Product VALUES(8,'Ice Tea Clock',226);
INSERT INTO Customer VALUES(9,'James','Schneider','277 Seventh Av.','Berne');
INSERT INTO Product VALUES(9,'Clock Telephone',172);
INSERT INTO Customer VALUES(10,'Anne','Fuller','135 Upland Pl.','Dallas');
INSERT INTO Product VALUES(10,'Telephone Ice Tea',204);
Con todo esto tenemos la siguiente estructura de proyecto:
En el paquete carmelo.spring.model almacenaremos las entidades JPA para las tablas Product
y Customer
, las clases tendrán el mismo nombre, primero la clase Product
:
@Data
@Entity
public class Product {
@Id private Long id;
private String name;
private Double price;
}
Usamos la anotación @Data de Lombok para simplificar la creación de nuestras clases, la siguiente entidad es la clase Customer
.
@Data
@Entity
public class Customer {
@Id private Long id;
private String firstName;
private String lastName;
private String street;
private String city;
}
En el paquete carmelo.spring.repository encontraremos los repositorios JPA, estos son los encargados de las operaciones de acceso a datos, por ejemplo, para la clase Product tenemos:
public interface ProductRepository extends CrudRepository<Product, Long> {
List<Product> findByPriceGreaterThan(Double price);
}
En el paquete carmelo.spring.service tenemos la capa de servicios.
@Service
public class ProductServiceImpl implements ProductService {
@Autowired
private ProductRepository product;
@Override
public Iterable<Product> productList() {
return product.findAll();
}
@Override
public void productDelete(Long id) {
this.product.delete(id);
}
@Override
public void productAdd(Product product) {
this.product.save(product);
}
@Override
public Long productCount() {
return this.product.count();
}
}
Comentarios
Publicar un comentario