Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
2.2. Modelo
El modelo es una clase en Java que representa mediante anotaciones una tabla en la base
de datos, esto nos ayuda porque l se encarga del mapeo de la clase a la tabla, nosotros siempre
veremos los datos como objetos, es importante que conozcan estos pasos, aunque la mayora de
las veces el encargado de crear las clases en el proyecto es el DBA.
2.2.1.Como primer paso vamos a crear la clase con el nombre de Promocin (notese es en
singular) y con los siguientes atributos: id (este atributo lo llevan todos las clases del
modelo), descripcin, porcentaje, fechaInicio, fechaFin, numeroPromociones,
fechaRegistro y restaurante.
package com.mx.ajal.technology.foodpromotions.model;
import java.io.Serializable;
import java.util.Date;
import
import
import
import
import
import
import
import
import
import
import
javax.persistence.Column;
javax.persistence.Entity;
javax.persistence.FetchType;
javax.persistence.GeneratedValue;
javax.persistence.GenerationType;
javax.persistence.Id;
javax.persistence.JoinColumn;
javax.persistence.ManyToOne;
javax.persistence.Table;
javax.persistence.Temporal;
javax.persistence.TemporalType;
import com.fasterxml.jackson.annotation.JsonIgnore;
@Entity
@Table(name = "PROMOCIONES")
public class Promocion implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID_PROMOCION")
private Integer id;
@Column(name = "DESCRIPCION", length=50)
private String descripcion;
@Column(name = "PORCENTAJE")
private Double porcentaje;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "FE_INICIO")
private Date fechaInicio;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "FE_FIN")
private Date fechaFin;
@Column(name = "NUM_PROMOCIONES")
private Integer numeroPromociones;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "FE_REGISTRO")
private Date fechaRegistro;
@ManyToOne(fetch=FetchType.LAZY)
@JsonIgnore
@JoinColumn(name="RESTAURANTE_ID")
private Restaurante restaurante;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDescripcion() {
return descripcion;
}
public void setDescripcion(String descripcion) {
this.descripcion = descripcion;
}
public Double getPorcentaje() {
return porcentaje;
}
public void setPorcentaje(Double porcentaje) {
this.porcentaje = porcentaje;
}
public Date getFechaInicio() {
return fechaInicio;
}
public void setFechaInicio(Date fechaInicio) {
this.fechaInicio = fechaInicio;
}
public Date getFechaFin() {
return fechaFin;
}
public void setFechaFin(Date fechaFin) {
this.fechaFin = fechaFin;
}
public Integer getNumeroPromociones() {
return numeroPromociones;
}
public void setNumeroPromociones(Integer numeroPromociones) {
this.numeroPromociones = numeroPromociones;
}
public Date getFechaRegistro() {
return fechaRegistro;
}
public void setFechaRegistro(Date fechaRegistro) {
this.fechaRegistro = fechaRegistro;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
}
Como podemos ver nuestra clase queda con los atributos, anotaciones que lo relacionan con
la base de datos y mtodos get y set.
2.3. Repository.
La capa de persistencia y acceso a los registros de la base de datos se les conoce como
Repository, en algunas ocasiones tambin se les llama DAO (Objetos de Acceso a Datos), para
Spring Data, se utiliza la escritura de persistencia extendiendo de la interfaz genrica
CrudRepository y mandndole como parmetro el nombre del modelo (en este caso
Promocion) y el tipo de dato del identificado (en este caso Integer), entonces nuestra interfaz
genrica quedara de la siguiente manera:
Para crear la interfaz repository tenemos que irnos al paquete de repository crear una nueva
interfaz con el nombre del modelo ms Repository en este caso seria PromocionRepository.
package com.mx.ajal.technology.foodpromotions.repository;
import org.springframework.data.repository.CrudRepository;
import com.mx.ajal.technology.foodpromotions.model.Promocion;
public interface PromocionRepository extends CrudRepository<Promocion,
{
}
Integer>
Integer>
3. Servicios
Los servicios tienen como funcin principal, comunicar a los repositorios con los
controladores, es por ello que necesitamos realizar los mtodos necesarios para el funcionamiento
del requerimiento, como vimos anteriormente los requerimientos son los siguientes:
En los servicios es necesario crear una interfaz y una clase que implemente la interfaz, a la interfaz
la llamaremos PromocionService, y va en el paquete de service y en ella escribimos los dos
mtodos que necesitamos en uno devolvemos una lista de promociones y en la otra los mensajes,
quedando la interfaz de la siguiente manera:
package com.mx.ajal.technology.foodpromotions.service;
import java.util.List;
import com.mx.ajal.technology.foodpromotions.dto.Mensaje;
import com.mx.ajal.technology.foodpromotions.model.Promocion;
import com.mx.ajal.technology.foodpromotions.model.Restaurante;
public interface PromocionService {
public Mensaje guardarPromocion(Promocion promocion, Restaurante
restaurante );
public List<Promocion> getPromocionesByRestaurante(Restaurante
restaurante);
}
Ahora vamos a crear la implementacin esta se debe de llamar como el servicio mas Impl en este caso quedara
PromocionServiceImpl.
package com.mx.ajal.technology.foodpromotions.service.impl;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import
import
import
import
import
com.mx.ajal.technology.foodpromotions.dto.Mensaje;
com.mx.ajal.technology.foodpromotions.model.Promocion;
com.mx.ajal.technology.foodpromotions.model.Restaurante;
com.mx.ajal.technology.foodpromotions.repository.PromocionRepository;
com.mx.ajal.technology.foodpromotions.service.PromocionService;
@Service
public class PromocionServiceImpl extends BaseService implements
PromocionService{
@Autowired PromocionRepository promocionRepository; // inyectamos el
repositorio
/**
* Este metodo trata de guardar una promocion y devuelve un mensaje,
* con el valor 0 si todo pasa correctamente y en caso contrario manda un
id
* diferente a 0
*/
public Mensaje guardarPromocion(Promocion promocion, Restaurante
restaurante) {
Mensaje mensaje = new Mensaje();
try{
promocion.setFechaRegistro(new Date()); // establecemos la
fecha actual
promocion.setRestaurante(restaurante); // le seteamos el
restaurante correspondiente
promocionRepository.save(promocion); // guardamos la
informacion
}catch(Exception e){
LOG.error(e.hashCode()+":"+e.getMessage(),e);
mensaje.setId(e.hashCode());
mensaje.setMensaje(e.getMessage());
}
return mensaje;
}
public List<Promocion> getPromocionesByRestaurante(Restaurante restaurante)
{
return
promocionRepository.getPromocionesByRestaurante(restaurante.getId()); //
devolvemos las promociones del restaurante.
}
}
4. Controladores
Los controladores son los encargados de comunicar a una pantalla con la capa de servicios, es
importante que un controlador no invoque directamente a un repositorio sino que siempre
pase por la capa de seguridad, aqu vamos a identificar los controladores sncronos y
asncronos
Sincronos, es cuando se hace una peticin al servidor, como por ejemplo cambiar de pantalla,
de estos vamos a tener solamente uno que se llame verPromociones dentro del controlador
de restaurates y que nos va a devolver un String que nos regrese la url del jsp a mostrar
Agregamos el mtodo a la clase RestauranteController, ya que esta ya exista solo le
agregamos un nuevo mtodo
@RequestMapping(value="ver-promociones.html")
public String verPromocion(HttpServletRequest request){
if (getLicenciaFromSession(request)==null){ // si no tiene
una sesion lo regresamos a inicio.html
return "redirec:/app/restaurante/inicio.html";
}
return "restaurante/ver-promociones";
}
Asincronos, los mtodos de los controladores asncronos nos sirven para hacer peticiones
al servidor sin neceidad de refrescar, sino que lo hacen por abajo a esto se le llama tambin
peticiones AJAX, para la pantalla que estamos desarrollando necesitamos dos mtodos asncronos
uno que nos permita guardar y otro que nos permita obtener todos las promociones del
restaurante.
Como en este caso no existe una clase asncrona para las promociones la vamos a crear en
el paquete de async.controller y se llamara AsyncPromocionController, en ella pondremos los dos
mtodos que necesitamos para guardar y para obtener las promociones de un restaurante.
org.springframework.beans.factory.annotation.Autowired;
org.springframework.stereotype.Controller;
org.springframework.web.bind.annotation.RequestBody;
org.springframework.web.bind.annotation.RequestMapping;
org.springframework.web.bind.annotation.RequestMethod;
org.springframework.web.bind.annotation.ResponseBody;
import
import
import
import
com.mx.ajal.technology.foodpromotions.controller.BaseController;
com.mx.ajal.technology.foodpromotions.dto.Mensaje;
com.mx.ajal.technology.foodpromotions.model.Promocion;
com.mx.ajal.technology.foodpromotions.service.PromocionService;
@Controller
@RequestMapping("restaurante/promocion/async")
public class AsyncPromocionController extends BaseController {
@Autowired PromocionService promocionService;
@RequestMapping(value="guardar-promocion",
method=RequestMethod.POST)
public @ResponseBody Mensaje guardarPromocion(@RequestBody
Promocion promocion, HttpServletRequest request){
return promocionService.guardarPromocion(promocion,
getRestauranteFromSession(request));
}
@RequestMapping("ver-promociones")
public @ResponseBody List<Promocion>
getPromocionesByRestaurante(HttpServletRequest request){
return
promocionService.getPromocionesByRestaurante(getRestauranteFromSession(re
quest));
}
}
Lo que estamos haciendo aqu es exponer en rutas de http para que puedan ser accedidas dentro
de Ajax.
5. JSP
A continuacin vamos a modificar la jsp restaurante/inicio.jsp para agregar un botn siempre que
exista una licencia valida, lo nico que va hacer es mandarnos a la pantalla ver-promociones.html
que fue agregada al controlador RestauranteController, si recordamos este mtodo nos devuelve
restaurante/ver-promociones, el cdigo que agregamos en el JSP es el siguiente:
<c:if test="${licenciaSession!=null}">
<form action="ver-promociones.html">
<button class="btn btn-primary">Administrar</button>
</form>
</c:if>
Ya nos lleva primero vamos hacer una tabla en la cual mostremos todas las promociones y si no
existe un mensaje que nos diga que no ha dado de alta ninguna promocin.
<th>Porcentaje</th>
<th>Fecha Inicio</th>
<th>Fecha Fin</th>
<th>Numero de Promociones</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-hide="promociones.length">
<td colspan="6">No tienes promociones dadas
de alta.</td>
</tr>
<tr ng-repeat="p in promociones">
<td>{{p.descripcion}}</td>
<td>{{p.porcentaje}}</td>
<td>{{p.fechaInicio}}</td>
<td>{{p.fechaFin}}</td>
<td>{{p.numeroPromociones}}</td>
<td></td>
</tr>
</tbody>
</table>
Ahora vamos a declarar una variable en el scope de nuestro java script que se llame promociones y
la vamos a inicializar vacia, nuestro js quedara de la siguiente manera:
var URL_BASE_PROMOCION = BASE_APP+'app/restaurante/promocion/async/';
app.controller("restauranteCtrl", function($scope, $http) {
$scope.promociones = [];
});
Ahora vamos a crear un mtodo que nos regrese todas las promociones de ese restaurante es aqu
donde vamos a invocar a un metodo asncrono a continuacin como quedara:
var URL_BASE_PROMOCION = BASE_APP+'app/restaurante/promocion/async/';
var URL_BASE_PROMOCION_VER = BASE_APP+'ver-promociones';
app.controller("restauranteCtrl", function($scope, $http) {
$scope.promociones = [];
$scope.refreshPromociones = function (){
$http.get(URL_BASE_PROMOCION_VER)
.then(function(response) {
$scope.promociones = response.data;
});
};
});
Y refrescamos nuestra pantalla para ver si se refleja algn cambio con lo anterior:
Ahora vamos a crear un formulario para el alta de una promocin, queda de la siguiente manera:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<!DOCTYPE html>
<html lang="en" ng-app="restauranteApp">
<head>
<title>FP Restaurante</title>
<jsp:include page="/WEB-INF/views/commons/head.jsp"/>
</head>
<body ng-controller="restauranteCtrl">
<c:set var="restaurante" value="${restSession}"></c:set>
<jsp:include page="/WEB-INF/views/commons/header.jsp"/>
<div class="container">
<h2>Promociones</h2>
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>Descripcion</th>
<th>Porcentaje</th>
<th>Fecha Inicio</th>
<th>Fecha Fin</th>
<th>Numero de Promociones</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-hide="promociones.length">
<td colspan="6">No tienes promociones dadas
de alta.</td>
</tr>
<tr ng-repeat="p in promociones">
<td>{{p.descripcion}}</td>
<td>{{p.porcentaje}}</td>
<td>{{p.fechaInicio}}</td>
<td>{{p.fechaFin}}</td>
<td>{{p.numeroPromociones}}</td>
<td></td>
</tr>
</tbody>
</table>
<div class="panel panel-info">
<div class="panel-heading">Alta de una promocin</div>
<div class="panel-body">
<form name="formAltaPromocion" action=""
class="form form-horizontal">
<div class="form-group">
<label class="col-md-4 controllabel">Descripcin</label>
<div class="col-md-8">
<input type="text" class="formcontrol" required="required" maxlength="30" name="descripcion" ngmodel="promocion.descripcion" />
</div>
</div>
<div class="form-group">
<label class="col-md-4 controllabel">Porcentaje</label>
<div class="col-md-8">
<input type="number"
class="form-control" required="required" maxlength="2" name="porcentaje"
ng-model="promocion.porcentaje" />
</div>
</div>
<div class="form-group">
<label class="col-md-4 controllabel">Fecha Inicio</label>
<div class="col-md-8">
<input type="date" class="formcontrol" required="required" name="finicio" ngmodel="promocion.fechaInicio" />
</div>
</div>
<div class="form-group">
<label class="col-md-4 controllabel">Fecha Final</label>
<div class="col-md-8">
<input type="date" class="formcontrol" required="required" name="ffinal" ng-model="promocion.fechaFin"
/>
</div>
</div>
<div class="form-group">
<label class="col-md-4 controllabel">Numero de promociones</label>
<div class="col-md-8">
<input type="number"
class="form-control" required="required" maxlength="2" name="promociones"
ng-model="promocion.numeroPromociones" />
</div>
</div>
<div class="form-group">
<div class="col-md-8 col-md-offset-4">
Y el javascrcipt:
var URL_BASE_PROMOCION = BASE_APP+'app/restaurante/promocion/async/';
var URL_BASE_PROMOCION_VER = URL_BASE_PROMOCION+'ver-promociones';
var URL_BASE_PROMOCION_GUARDAR = URL_BASE_PROMOCION+'guardar-promocion';
app.controller("restauranteCtrl", function($scope, $http) {
$scope.promociones = [];
$scope.promocion = {};
$scope.refreshPromociones = function (){
$http.get(URL_BASE_PROMOCION_VER)
.then(function(response) {
$scope.promociones = response.data;
});
};
$scope.guardarPromocion = function (){
$http({
method:'post',
url: URL_BASE_PROMOCION_GUARDAR,
data: $scope.promocion
}).then(function (res){
$scope.refreshPromociones();
$scope.promociones = [];
$scope.promocion = {};
showMessageServ(res.data);
});
};
$scope.refreshPromociones();
});