Si utilizamos los patrones DAO y Fachada para implementar la capa modelo, Spring nos provee un sistema para poder establecer estos correctamente sobre el fichero de configuración.
Para configurar los DAO debemos de hacer lo siguiente:
<!– ======= Definition of the DAOs =======–>
<bean id=”addressDao“ class=”gz.cyberbrain.cyberhotel.model.address.dao.AddressSpringDao“>
<property name=”sessionFactory“>
<ref bean=”factory“/>
</property>
</bean>
<bean id=”roomDao“ class=”gz.cyberbrain.cyberhotel.model.room.dao.RoomSpringDao“>
<property name=”sessionFactory“>
<ref bean=”factory“/>
</property>
</bean>
…
Es decir, tenemos una entrada para cada DAO en la que indicamos:
id: nombre para la entrada, debemos utilizar un nombre significativo.
class: ruta de paquetes donde se encuentra la clase con implementación del DAO, ponemos el nombre de la clase sin la extensión .java.
Tiene una propiedad sessionFactory, en ella indicamos la factoría explicada en el apartado anterior, de esta forma Spring sabe buscar para cada DAO los elementos de mapeo necesarios.
Para las fachadas la configuración es muy completa y en ella indicamos para los métodos que utilizamos, que aislamiento transaccional deseamos, pues es cada caso de uso implementado en la fachada el que se ejecuta en un entorno transaccional:
<!– ======= Definition of the Facades =======–>
<bean id=”configurationFacadeDelegate“
class=”org.springframework.transaction.interceptor.TransactionProxyFactoryBean“>
<property name=”transactionManager“>
<ref bean=”transactionManager“/>
</property>
<property name=”target“>
<ref local=”configurationTarget“/>
</property>
<property name=”transactionAttributes“>
<props>
<prop key=”show*“>readOnly</prop>
<prop key=”find*“>readOnly</prop>
<prop key=”maxPriceId“>readOnly</prop>
<prop key=”create*“>PROPAGATION_REQUIRED,ISOLATION_DEFAULT, -java.lang.Exception</prop>
<prop key=”update*“>PROPAGATION_REQUIRED,ISOLATION_DEFAULT, -java.lang.Exception</prop>
<prop key=”delete*“>PROPAGATION_REQUIRED,ISOLATION_DEFAULT, -java.lang.Exception</prop>
<prop key=”register*“>PROPAGATION_REQUIRED,ISOLATION_DEFAULT</prop>
<prop key=”change*“>PROPAGATION_REQUIRED,ISOLATION_DEFAULT, -java.lang.Exception</prop>
<prop key=”remove*“>PROPAGATION_REQUIRED,ISOLATION_DEFAULT, -java.lang.Exception</prop>
<prop key=”usersList“>readOnly</prop>
<prop key=”rolesList“>readOnly</prop>
</props>
</property>
</bean>
<bean id=”configurationTarget“ class=”gz.cyberbrain.cyberhotel.model.configurationfacade.spring.ConfigurationSpringFacadeDelegate“>
<property name=”addressDao“>
<ref local=”addressDao“/>
</property>
<property name=”roomDao“>
<ref local=”roomDao“/>
</property>
…
</bean>
id: Indicamos un nombre significativo para la entrada.
class: Clase que actúa como proxy para las transacciones, la buscamos en la documentación de Spring.
Tiene una serie de propiedades, en transactionManager indicamos el manejador de transacciones explicado en el apartado anterior, en target indicamos una entrada donde estará definida la clase de la fachada así como todos los DAO que utilizará, en transactionAttributes indicamos todos los métodos que se usan en la fachada que implementan los casos de uso, para los cuales se pueden usar expresiones regulares como por ejemplo * para cualquier carácter, así si ponemos find* damos a entender a Spring que todos los métodos que empiezan por find tienen las propiedades transaccionales definidas, por ejemplo en el fichero vemos:
<prop key=”find*“>readOnly</prop>
Con ello estamos diciendo que todos los métodos que empiezan por find son de sólo lectura y por lo tanto no necesitan transaccionalidad.
También vemos por ejemplo:
<prop key=”delete*“>PROPAGATION_REQUIRED, ISOLATION_DEFAULT, -java.lang.Exception</prop>
Estamos indicando a Spring que los métodos que comienzan por delete utilizan el método de propagación PROPAGATION_REQUIRED y el aislamiento por defecto ISOLATION_DEFAULT y que cuando ocurre una excepción de la clase java.lang.Exception o cualquiera de sus subclases, se realice un rollback de la transacción.