Autor
|
Tema: Ejemplo de 3 capas con java (Leído 59,413 veces)
|
sapito169
Desconectado
Mensajes: 629
|
Bueno la respuesta que te voy a dar es algo rara Algunos me van a criticar por querer programar todo lo más orientado a objetos porque creo que los patrones orientados a objetos pueden ser una gran fuente de solución de problemas que pueden reducir el código basura y te dan la posibilidad de crear código reutlsable incluso sin recompilar es por eso de descubrir que el trabajo en como yo lo e implementado no es muy orientado a objetos y es mas lo conocen como modelo anémico de objetos que ironía Algunos me van a decir que tengo una opinión casi religiosa de la santa oo Es por eso que voy a hacer el post un poco diferente Otra cosa es que no puede hacer un código con el manejo de error que yo quisiera sin poner mucho código basura debido al uso de interfaces no se si alguien sabe algún patrón para solucionar eso Cambiar a la forma en que trabajaba antes no va a ser tan difícil tampoco
|
|
|
En línea
|
|
|
|
sapito169
Desconectado
Mensajes: 629
|
Primero como cualquier talibán de la oo comienzan creando un paquete paquete que diga algo como entidad dominio lógica en mí caso estoy creando una aplicación de venta de platos para el restaurant de la tía veneno creo e paquete com.tiaveneno.ventas.compartido.modelo Dentro creo la clase Orden Siguiendo algunas recomendaciones de mi compañero y aprendiz joshua bloch Utilizo lo mas que pueda la palabra reservada final así me evito problemas de que algún despistado por error vuelva a re instanciar la clase y haga que explote todo También evito crear relaciones de tipo gallina huevo por evitar problemas de loops infinitos como por ejemplo seria difícil crear el método tostring si la clase detalle de orden tenga una relación a orden además evito lo más posible utilizar el punto más de 2 veces por qué hace el código difícil de testear y crear clases mal diseñadas que hacen cosas que no le incumben evito poner cosas como orden().getDetalle().getPlato().getPrecio package com.tiaveneno.ventas.compartido.modelo; import java.util.ArrayList; import java.util.Date; import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import javax.persistence.Temporal; import javax.persistence.TemporalType; public class Orden { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; private short numero; @ManyToOne(cascade = CascadeType.ALL) private Personal cajero; @ManyToOne(cascade = CascadeType.ALL) private Personal mozo; @Temporal(TemporalType.DATE) @OneToMany(cascade = CascadeType.ALL) private final List<DetalleOrden> detalles = new ArrayList<DetalleOrden>(); public Orden(int id, short numero, Personal cajero, Personal mozo, this.id = id; this.numero = numero; this.cajero = cajero; this.mozo = mozo; this.fecha = fecha; } public Orden() { } public static Orden nueva() { return new Orden(); } public Orden detalles(DetalleOrden... detalleOrdens) { for (DetalleOrden detalleOrden : detalleOrdens) { this.con(detalleOrden); } return this; } public Orden con(DetalleOrden detalleOrden) { detalles.add(detalleOrden); return this; } public double obtenerTotal() { double total = 0; for (DetalleOrden detalleOrden : detalles) { total = total + detalleOrden.subtotal(); } return total; } //orrible codigo boilepart inebitable getter y setters public List<DetalleOrden> getDetalles() { return detalles; } @Override return "Orden [id=" + id + ", numero=" + numero + ", cajero=" + cajero + ", mozo=" + mozo + ", fecha=" + fecha + ", detalles=" + detalles + "]"; } }
|
|
« Última modificación: 2 Enero 2011, 04:14 am por sapito169 »
|
En línea
|
|
|
|
sapito169
Desconectado
Mensajes: 629
|
Todas las clases persistentes deben estar anotadas con @Entity
Todas las entidades debe tener un llave primaria en mi caso creo que la mejor opción es que sea de tipo identity no me gusta que el usuario tenga que siquiera ver las claves
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id;
Tengo que mapear las relaciones entre clases creo que es más natural pensar que cuando guardamos una orden se deberían guardar automáticamente todos sus detalles por eso pongo cascadetype.all
@ManyToOne(cascade = CascadeType.ALL) private Personal cajero;
Un constructor sin parámetro es obligatorio
Además creo un método que le concierne a la orden y otros que solo sirven como azúcar sintáctico (solo te evitan escribir un poco)
detalles(DetalleOrden... detalleOrdens) Orden con(DetalleOrden detalleOrden) double obtenerTotal()
|
|
|
En línea
|
|
|
|
sapito169
Desconectado
Mensajes: 629
|
Luego creó una abstracción la base de datos para así poder cambiarme de proveedor de persistencia sin crear tanto problema por ejemplo es fácil cambiar de jpa ibatis o lo que sea tener en cuenta que uso generics la k es la clase de la llave primaria y e es la clase de la entidad en concreto package com.tiaveneno.ventas.compartido.servicio; import java.util.List; import java.util.Map; public interface dao<K, E> { public abstract void remove(E... entities); public abstract void remove(final List<E> entities); public abstract void remove(final E entity); public abstract void persist(final E... entities); public abstract void persist(final List<E> entities); public abstract void persist(final E entity); public abstract E findById(final K id); public abstract void close(); public abstract void update(final K key, final E entity); public abstract void update(final Map<K, E> update); public abstract void update (final Map. Entry<K, E >... entries); }
y una interfas comcreta para un dao cualquiera package com.tiaveneno.ventas.compartido.servicio; import com.tiaveneno.ventas.compartido.modelo.Orden; public interface OrderDao extends dao<Integer, Orden> { // aqui pon codigo que sea propio de las orden como busca orden con un plato x }
|
|
« Última modificación: 2 Enero 2011, 04:32 am por sapito169 »
|
En línea
|
|
|
|
sapito169
Desconectado
Mensajes: 629
|
Finalmente pongo una implementación concreta de el proveedor de persistencia como en este caso jpa pero puedes poner el que mas te guste package com.tiaveneno.ventas.datos.jpa; import java.lang.reflect.ParameterizedType; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import javax.persistence.EntityManager; import org.apache.commons.beanutils.BeanUtils; import com.tiaveneno.ventas.compartido.servicio.dao; public abstract class JpaDao<K, E> implements dao<K, E> { private final Class<E> entityClass; private final EntityManager entityManager; @SuppressWarnings("unchecked") public JpaDao(EntityManager entityManager) { ParameterizedType genericSuperclass = (ParameterizedType) getClass() .getGenericSuperclass(); this.entityClass = (Class<E>) genericSuperclass .getActualTypeArguments()[1]; this.entityManager = entityManager; } @Override public void persist(final E entity) { try { entityManager.getTransaction().begin(); entityManager.persist(entity); entityManager.getTransaction().commit(); entityManager.getTransaction().rollback(); } } @Override public void persist(final List<E> entities) { try { entityManager.getTransaction().begin(); for (E e : entities) { entityManager.persist(e); } entityManager.getTransaction().commit(); entityManager.getTransaction().rollback(); } } @Override public void persist(E... entities) { List<E> es = new ArrayList<E>(); for (E e : entities) { es.add(e); } persist(es); } @Override public void remove(final E entity) { try { entityManager.getTransaction().begin(); entityManager.remove(entity); entityManager.getTransaction().commit(); entityManager.getTransaction().rollback(); } } @Override public void remove(final List<E> entities) { for (E e : entities) { remove(e); } } @Override public void remove(E... entities) { List<E> es = new ArrayList<E>(); for (E e : entities) { es.add(e); } remove(es); } @Override public E findById(final K id) { return entityManager.find(entityClass, id); } @Override public void update(final K key, final E entity) { Map<K, E> map = new HashMap<K, E>(); map.put(key, entity); update(map); } @Override public void update(final Map<K, E> update) { Iterator<Map.Entry<K, E>> iter = update.entrySet().iterator(); while (iter.hasNext()) { Map. Entry<K, E > entry = iter. next(); K key = entry.getKey(); E entity = entry.getValue(); @SuppressWarnings("unchecked") E origen = (E) entityManager.find(entity.getClass(), key); try { BeanUtils.copyProperties(origen, entity); } } } @Override public void update (final Map. Entry<K, E >... entries) { Map<K, E> map = new HashMap<K, E>(); for (Entry<K, E> entry : entries) { map.put(entry.getKey(), entry.getValue()); } update(map); }; @Override public void close() { if (entityManager != null) { if (!entityManager.isOpen()) { try { entityManager.close(); } } } } }
Un poquito de voilepart pero esta vez te vas a quedar asi porque no es ni la desina parte de lo que sería con implementado con jbc package com.tiaveneno.ventas.datos.jpa; import javax.persistence.EntityManager; import com.tiaveneno.ventas.compartido.modelo.Orden; import com.tiaveneno.ventas.compartido.servicio.OrderDao; public class JpaOrderDao extends JpaDao<Integer, Orden> implements OrderDao { public JpaOrderDao(EntityManager entityManager) { super(entityManager); } }
Si es solo eso no falta nada ahora puedes cerrar la boca
|
|
|
En línea
|
|
|
|
sapito169
Desconectado
Mensajes: 629
|
finalmente código que veríamos en el cliente package com.tiaveneno.ventas; import javax.persistence.EntityManager; import javax.persistence.Persistence; import com.tiaveneno.ventas.compartido.modelo.DetalleOrden; import com.tiaveneno.ventas.compartido.modelo.Orden; import com.tiaveneno.ventas.compartido.modelo.Personal; import com.tiaveneno.ventas.compartido.modelo.Plato; import com.tiaveneno.ventas.compartido.servicio.OrderDao; import com.tiaveneno.ventas.datos.jpa.JpaOrderDao; public class Main { public static void main (String[] args ) { EntityManager entityManager = Persistence. ( "jpa").createEntityManager(); OrderDao orderDao = new JpaOrderDao(entityManager); DetalleOrden duno = new DetalleOrden((short) 1, new Plato( "combinado fiedeos con chanfainita", 3.5)); DetalleOrden ddos = new DetalleOrden((short) 1, new Plato( "combinado fiedeos con chanfainita", 3.5)); Orden orden = new Orden(); orden.setCajero(new Personal("cajero")); orden.setMozo(new Personal("mozo")); orden.detalles(duno, ddos); orderDao.persist(orden); } }
Si está bien todo se guarda automáticamente en una sola transacción en caso de error hace rollback y muestra la pila por la salida estándar donde te dice la razón del error en que línea y de que clase es el error Y me olvidaba tienes que poner un fichero de configuración en la carpeta META-INF al (costado de las clases) con el nombre de persistence.xml y agregar una librería de jipa en mi caso puse eclipse link nota no me pregunten cómo se hace eso en netbenas por que estoy enseñando a programar en java no en netbeans asi que si quieres saberlo pon el google por que poner siguiente siguiente en un wizar no es para hombres que tengan pelo en el pecho <?xml version="1.0" encoding="UTF-8" ?> <persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"> <persistence-unit name="jpa" transaction-type="RESOURCE_LOCAL"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <class>com.tiaveneno.ventas.compartido.modelo.Cuenta</class> <class>com.tiaveneno.ventas.compartido.modelo.DetalleOrden</class> <class>com.tiaveneno.ventas.compartido.modelo.Orden</class> <class>com.tiaveneno.ventas.compartido.modelo.Personal</class> <class>com.tiaveneno.ventas.compartido.modelo.Plato</class> <properties> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" /> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/test" /> <property name="javax.persistence.jdbc.user" value="root" /> <property name="javax.persistence.jdbc.password" value="root" /> <!-- EclipseLink should create the database schema automatically --> <property name="eclipselink.ddl-generation" value="none" /> <property name="eclipselink.ddl-generation.output-mode" value="database" /> </properties> </persistence-unit> </persistence>
El fichero xml es un caso particular para eclipselink la primera ves que corras el programa debes reemplazar <property name="eclipselink.ddl-generation" value="none" /> por <property name="eclipselink.ddl-generation" value="DROP_AND_CREATE" /> ademas en <persistence-unit name="jpa" transaction-type="RESOURCE_LOCAL"> Tener en cuenta que lo que dice úntenme debe estar en tu código para ser creado dentro del createEntityManagerFactory En mi caso como dice jpa yo pongo EntityManager entityManager = Persistence. ( "jpa").createEntityManager(); Notese que estoy creando toda la aplicación desde el main asi que si quiero cambiar de proveedor de persistencia solo cambio en el main y no en 20 clases distintas si no te equicas nunca mas vas a tener que corregir la vase de datos la sincronisacion te la hace jpa Uploaded with ImageShack.ushttp://www.mediafire.com/download.php?6ff5dxyb6pb2f6j
|
|
« Última modificación: 2 Enero 2011, 05:34 am por sapito169 »
|
En línea
|
|
|
|
cyberserver
Desconectado
Mensajes: 162
Lo que una mente crea, otra lo destruye
|
Hola Sapito. muy bueno tu tema, principalmente en la primera parte. Pero tengo una duda acerca de la programacion en 3 capas. En general poniento depormedio tu codigo.
Las Arquitectura de 3 capas se divide en :
1.- Interface, la Parte visual de nuestra aplicacion 2.- Clases de mi logica. que analizan los parametros enviador por la interface. 3.- Las Clases Ajenas a nuestra logica. (Apis, clases Generales para reutilizar,Clases ya compiladas)
Es cierto esto? o la 3 capa solo es ocupada para acceso a una BD
Y digo analizando este modelo poniendo depormedio tu codigo, por lo siguiente Tu primera practica la estructuraste masomenos asi.
1.- Interface 2.- Tu logica que relaciona a la 1° y 3° capa 3.- Clases para la conexión de BD.
Y en la 3° capa tambien pusiste la clase "DBdaoProducto" que es donde especificas lo que se tiene que modificar en la BD.
Pero si supongamos que yo en la parte 3 coloco una Clase (Ya compilada que alguien me paso alguna ves) llamada PatronDeConeccion, que permite la conexión y modificacion de la BD por el envio de Query´s a los metodos muy generales especificados dentro.
Cuando yo quiera enviarle los parametros Query a algun metodo dentro de la Clase PatronDeConeccionesta, esta ultima clase donde iria? en el nivel de mi logica por que yo defino mis consultas o junto a la Clase PatronDeConeccion por el solo hecho de que tiene contacto directo con la BD
|
|
|
En línea
|
|
|
|
cyberserver
Desconectado
Mensajes: 162
Lo que una mente crea, otra lo destruye
|
Disculpen, una pregunta mas. La arquitectura de 3 capas solo es para aplicaciones que implementan una Base de Datos.?
Y si tengo una aplicacion, que no ocupa Bd, que hago ? se puede usar esta arquitectura o no ?
|
|
|
En línea
|
|
|
|
JonathanR
Desconectado
Mensajes: 4
|
Hola que tal, mi nombre es Jonathan Rojas. Curso 7mo Trimestre de Ingenieria de Sistemas en la Universidad Metropolitana en caracas. En estos momentos me encuentro de vacaciones haciendo bases de datos eficientes y mi pregunta es. Conozco la idea de la programación bajo las 3 capas. Tengo ya 3 proyectos programando así más aquellos que no me piden en la Universidad y quisiera saber bajo su tutela Qué capa inicia a qué capa? porque si nos ponemos a analizar las 3 capas:
1ra Capa: Interfaz de Usuario, visible para usuario y muestra lo que queremos que el usuario vea 2da Capa: Capa Lógica, yo la llamo motor del programa, la única capa que puede acceder directamente a la capa de datos, la 1ra Capa deberá pasar por la 2da para acceder a la 3ra. 4ra Capa: Capa de datos, Base de datos, Modelación de datos, excel o lo que quieras.
Una vez que analizamos la teoria vamos a las dudas de programación que todo el mundo se hace: Qué capa se inicializa primero? Cuál lleva el famoso main?
Bueno en mi caso he hecho los dos metodos, que la 2da capa lleve el main o la primera lo lleve. Lo lógico y teórico es que la 2da lo lleve ya que si es el motor de tu programa. Pero es un poco dificil relacionar tus ideales con la programación, hay que ser un Az para dominar esa programación. Poniendo el main en la primera capa es sencillo, ponemos el motor como un objeto dentro de la capa y listo. Pero no se vería bonito.
Necesito opiniones.. Saludos! Jonathan Rojas
|
|
|
En línea
|
|
|
|
raao10
Desconectado
Mensajes: 1
|
Hola!! q tal por aca me estoy iniciando en el mundo de los sistemas en 3 capas y me ha parecido fabuloso el aporte de todos.. pero me gustaria si me pudieran ayudar en la parte en donde muestra un arreglo para visualizar una tabla de los datos... q no he podido entender... aunque hice el ejemplo no me sale.
|
|
|
En línea
|
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
ejemplo basico de cola en java
Java
|
chaarlyyyy
|
3
|
15,145
|
16 Julio 2010, 06:06 am
por danielo-
|
|
|
un ejemplo de troyano en java
« 1 2 »
Java
|
AngelCruel
|
10
|
9,509
|
13 Agosto 2010, 18:28 pm
por 1mpuls0
|
|
|
Cálculos Java, mi primner ejemplo
Java
|
Meta
|
2
|
5,818
|
9 Febrero 2011, 02:10 am
por Meta
|
|
|
Programacion java por capas
Programación General
|
tastian
|
0
|
3,002
|
12 Abril 2013, 20:06 pm
por tastian
|
|
|
3 capas y MVC con Java
Dudas Generales
|
Panic Fryam All
|
0
|
2,172
|
11 Noviembre 2021, 18:58 pm
por Panic Fryam All
|
|