diff --git a/pom.xml b/pom.xml index 324a223af5..fa2f1b36f6 100644 --- a/pom.xml +++ b/pom.xml @@ -330,6 +330,8 @@ maven-site-plugin en,es,zh_CN,ja,ko + + ${project.build.directory}/site-src @@ -346,6 +348,12 @@ ${project.basedir}/src/main/resources + + + ${project.basedir}/src/site + ${project.build.directory}/site-src + true + diff --git a/src/site/es/markdown/README.md b/src/site/es/markdown/README.md new file mode 100644 index 0000000000..a3abaf2e40 --- /dev/null +++ b/src/site/es/markdown/README.md @@ -0,0 +1,18 @@ +# Tabla de contenido + +Esta página es para representar el índice en GitHub. + +> **NOTE:** +> +> Dado que el destino del enlace se especifica asumiendo que se convierte a html con maven-site-plugin, hay un ancla que se rompe en el renderizado en GitHub. + +* [Introducción](./index.md) +* [Primeros pasos](./getting-started.md) +* [SqlSessionFactoryBean](./factorybean.md) +* [Transactions](./transactions.md) +* [Uso de SqlSession](./sqlsession.md) +* [Inyección de Mappers](./mappers.md) +* [Spring Boot](./boot.md) +* [Uso del API de MyBatis](./using-api.md) +* [Spring Batch](./batch.md) +* [Código de ejemplo](./sample.md) diff --git a/src/site/es/markdown/batch.md b/src/site/es/markdown/batch.md new file mode 100644 index 0000000000..1578477f98 --- /dev/null +++ b/src/site/es/markdown/batch.md @@ -0,0 +1,351 @@ + +# Spring Batch + +Desde la versión 1.1.0 MyBatis-Spring proporciona dos beans para construir aplicaciones Spring Batch: `MyBatisPagingItemReader` y `MyBatisCursorItemReader` y `MyBatisBatchItemWriter`. +Also, As of version 2.0.0 provides three builder classes for supporting the Java Configuration: the `MyBatisPagingItemReaderBuilder`, the `MyBatisCursorItemReaderBuilder` and the `MyBatisBatchItemWriterBuilder`. + +NOTA +Esta sección se refiere a [Spring Batch](http://static.springsource.org/spring-batch/) y no a sesiones batch de MyBatis. Para obtener información sobre las sesiones batch ve a la sección [Usnado un SqlSession](sqlsession.html). + +## MyBatisPagingItemReader + +Este bean es un `ItemReader` que lee registros de una base de datos usando paginación. + +Ejecuta la sentencia especificada mediante la propiedad `setQueryId` para obtener los datos. La sentencia se ejecuta usando peticiones paginadas del tamaño indicando en la propiedad `setPageSize`. +Al llamar al método `read()` éste devuelve el objeto que corresponde a la posición actual y solicita más páginas si es necesario. + +El reader recibe algunos parametros estándar y la SQL deberá hacer uso de algunos de ellos para construir un resultset del tamaño requerido. Los parametros son: + +* `_page`: el número de página a leer (comenzando en 0) +* `_pagesize`: el tamaño de la página, es decir, el número de filas a devolver +* `_skiprows`: el producto de `_page` por `_pagesize` + +Se pueden mapear en un statement de tipo select de la siguiente forma: + +```xml + +``` + +A continuación se muestra un ejemplo de configuración: + +```xml + + + + +``` +```java +@Configuration +public class BatchAppConfig { + @Bean + public MyBatisPagingItemReader reader() { + return new MyBatisPagingItemReaderBuilder() + .sqlSessionFactory(sqlSessionFactory()) + .queryId("com.my.name.space.batch.EmployeeMapper.getEmployee") + .build(); + } +} +``` + +**Veamos un ejemplo más complejo:** + +```xml + +``` +```xml + + + + + + +``` + +```java +@Configuration +public class BatchAppConfig { + @StepScope + @Bean + public MyBatisPagingItemReader dateBasedCriteriaReader( + @Value("#{@datesParameters}") Map datesParameters) throws Exception { + return new MyBatisPagingItemReaderBuilder() + .sqlSessionFactory(batchReadingSessionFactory()) + .queryId("com.my.name.space.batch.ExampleMapper.queryUserInteractionsOnSpecificTimeSlot") + .parameterValues(datesParameters) + .pageSize(200) + .build(); + } + + @StepScope + @Bean + public Map datesParameters( + @Value("#{jobExecutionContext['EXTRACTION_START_DATE']}") LocalDate yesterday, + @Value("#{jobExecutionContext['TODAY_DATE']}") LocalDate today, + @Value("#{jobExecutionContext['FIRST_DAY_OF_THE_MONTH_DATE']}") LocalDate firstDayOfTheMonth, + @Value("#{jobExecutionContext['FIRST_DAY_OF_THE_PREVIOUS_MONTH_DATE']}") LocalDate firstDayOfThePreviousMonth) { + Map map = new HashMap<>(); + map.put("yesterday", yesterday); + map.put("today", today); + map.put("first_day_of_the_month", firstDayOfTheMonth); + map.put("first_day_of_the_previous_month", firstDayOfThePreviousMonth); + return map; + } +} +``` + +El ejemplo anterior hace uso de tres cosas distintas: + +* `sqlSessionFactory`: Puedes tu propio sessionFactory, podría ser útil si quires leer de varias bases de datos. +* `queryId`: Si el código accede a varias tablas, y tienes distintas sentencias de consulta, puede ser interesante usar ficheros de mapeo distintos con namespaces distintos. + En este caso, al referirte a la query, no olvides incluir el namespace correspondiente. +* `parameterValues`: Puedes pasar parametros adicionales en este mapa, el ejemplo de arriba usa un mapa que se construye usando una expresion SpEL y obteniendo valores del jobExecutionContext. + Las claves del mapa puede usarse en el fichero mapper de MyBatis (por ejemplo: *yesterday* se puede usar como `#{yesterday,jdbcType=TIMESTAMP}`). + Observa que el mapa y el reader se consutruyen en un solo `step` para que sea posible usar la expresión SpEL con el `jobExecutionContext`. + Adicionalmente si los type handlers de MyBatis están configurados correctamente puedes pasar instancias personalizadas como los parametros del ejemplo que son fechas JodaTime. +* `pageSize`: Si le flujo batch está configurado con un tamaño de bloque (chunk size), es importante pasar esta información al reader, y eso se hace mediante esta propiedad. + +## MyBatisCursorItemReader + +Este bean es un `ItemReader` que lee registros de la base de datos usando un cursor. + +NOTA +Para usar este bean necesitas al menos MyBatis 3.4.0 o superior. + +Ejecuta la sentencia especificada mediante la propiedad `setQueryId` para obtener los datos usando el método `selectCursor()`. +Al llamar al método `read()` se devolverá el siguiente elemento del cursor hasta que no quede ninguno por devolver. + +El reader usa una conexión separada para que la sentencia no participe en ninguna transacción creada como parte del proceso del step. + +Cuando se usar un cursor puedes usar una sentencia convencional: + +```xml + +``` + +A continuación se muestra un ejemplo de configuración: + +```xml + + + + +``` +```java +@Configuration +public class BatchAppConfig { + @Bean + public MyBatisCursorItemReader reader() { + return new MyBatisCursorItemReaderBuilder() + .sqlSessionFactory(sqlSessionFactory()) + .queryId("com.my.name.space.batch.EmployeeMapper.getEmployee") + .build(); + } +} +``` + +## MyBatisBatchItemWriter + +Es un `ItemWriter` que usa las capacidades de batch de `SqlSessionTemplate` para ejecutar sentencias batch para todos los elementos (items) proporcionados. +El `SqlSessionFactory` debe configurarse con un executor de tipo `BATCH`. + +Ejecuta la sentencia indicada en la propiedad `statementId` cuando se invoca a `write()`. Se supone que `write()` se invoca dentro de una transacción. + +A continuación se muestra un ejemplo de configuración: + +```xml + + + + +``` + +```java +@Configuration +public class BatchAppConfig { + @Bean + public MyBatisBatchItemWriter writer() { + return new MyBatisBatchItemWriterBuilder() + .sqlSessionFactory(sqlSessionFactory()) + .statementId("com.my.name.space.batch.EmployeeMapper.updateEmployee") + .build(); + } +} +``` + +**Converting a item that read using ItemReader to an any parameter object:** + +By default behavior, the `MyBatisBatchItemWriter` passes a item that read using `ItemReader` (or convert by `ItemProcessor`) to the MyBatis(`SqlSession#update()`) as the parameter object. +If you want to customize a parameter object that passes to the MyBatis, you can realize to use the `itemToParameterConverter` option. For example using `itemToParameterConverter` option, you can passes any objects other than the item object to the MyBatis. +Follows below a sample: + +At first, you create a custom converter class (or factory method). The following sample uses a factory method. + +```java +public class ItemToParameterMapConverters { + public static Converter> createItemToParameterMapConverter(String operationBy, LocalDateTime operationAt) { + return item -> { + Map parameter = new HashMap<>(); + parameter.put("item", item); + parameter.put("operationBy", operationBy); + parameter.put("operationAt", operationAt); + return parameter; + }; + } +} +``` + +At next, you write a sql mapping. + +```xml + +``` + +At last, you configure the `MyBatisBatchItemWriter`. + +```java +@Configuration +public class BatchAppConfig { + @Bean + public MyBatisBatchItemWriter writer() throws Exception { + return new MyBatisBatchItemWriterBuilder() + .sqlSessionFactory(sqlSessionFactory()) + .statementId("org.mybatis.spring.sample.mapper.PersonMapper.createPerson") + .itemToParameterConverter(createItemToParameterMapConverter("batch_java_config_user", LocalDateTime.now())) + .build(); + } +} +``` + +```xml + + + + + + + + + + +``` + +**Escribiendo en distintas tablas usando composite writers (con algunos condicionantes):** + +Esta técnica sólo puede usarse con MyBatis 3.2+, por que había un [error](http://code.google.com/p/mybatis/issues/detail?id=741) en las versiones anteriores que hacían que el writer funcionara de forma incorrecta. + +Si el batch necesita escribir datos complejos, como registros con asociaciones, o en distintas bases de datos, entonces es necesario sortear el problema de que los insert statements solo pueden escribir en una tabla. +Para conseguir esto debes preparar un Item para que sea escrito por el writer. Sin embargo, dependiendo de las circunstancias puede ser interesante usar la siguiente técnica. +El truco siguiente funciona con items con asociaciones simples o con tablas no relacionadas. + +Elabora el `item` de forma que *contenta* todos los resgistros distintos. Supon que para cada `item` hay una *Interaction* que tiene una asociación *InteractionMetadata* y dos filas no asociadas *VisitorInteraction* and *CustomerInteraction*. +El objeto contenedor será de la siguiente forma: + +```java +public class InteractionRecordToWriteInMultipleTables { + private final VisitorInteraction visitorInteraction; + private final CustomerInteraction customerInteraction; + private final Interaction interaction; + // ... +} +``` +```java +public class Interaction { + private final InteractionMetadata interactionMetadata; +} +``` + +Entonces en la configuración de spring habrá un `CompositeItemWriter` que usará writers delegados configurados especificamente para cada tipo de registro. +Fijate que el *InteractionMetadata* es una asociacióin en el ejemplo por lo que debe ser escrita antes para que la Interaction pueda recibir la clave generada. + +```xml + + + + + + + + + + + + +``` + +```java +@Configuration +public class BatchAppConfig { + @Bean + public CompositeItemWriter interactionsItemWriter() { + CompositeItemWriter compositeItemWriter = new CompositeItemWriter(); + List> writers = new ArrayList<>(4); + writers.add(visitorInteractionsWriter()); + writers.add(customerInteractionsWriter()); + writers.add(interactionMetadataWriter()); + writers.add(interactionWriter()); + compositeItemWriter.setDelegates(writers); + return compositeItemWriter; + } +} +``` + +Cada writer delegados se configura como sea necesario, por ejemplo para *Interaction* y *InteractionMetadata*: + +```xml + +``` +```xml + +``` + +Al igual que con el reader el `statementId` puede hacer referencia al statement con un namespace como prefijo. + +Ahora es debe elaborarse el fichero de mapeo para cada tipo de registro, de la siguiente forma: + +```xml + + + +``` +```xml + + + +``` + +Lo que sucede es que primeramente se llamará a `insertInteractionMetadata`, y la sentencia de update está configurada para devolver las claves autogeneradas (`keyProperty` y `keyColumn`). +Una vez que el `InteractionMetadata` se ha almacenado por esta sentencia se puede ejecutar la siguiente para escribir el objeto padre `Interaction` mediante `insertInteraction`. + +***Sin embargo, ten en cuenta que los drivers JDBC se comportan distinto en este aspecto. A la fecha en la que se escribe esto +el driver H2 1.3.168 solo devuelve el último ID incluso en modo BATCH (see `org.h2.jdbc.JdbcStatement#getGeneratedKeys`), +mientras que el driver JDBC de MySQL se comporta como es de esperar y devuelve todos los IDs.*** diff --git a/src/site/es/markdown/boot.md b/src/site/es/markdown/boot.md new file mode 100644 index 0000000000..cda8eb3a3d --- /dev/null +++ b/src/site/es/markdown/boot.md @@ -0,0 +1,4 @@ + +# Using Spring Boot + +Please see the [MyBatis Spring-boot-starter](http://www.mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure) sub project docs for details. diff --git a/src/site/es/markdown/factorybean.md b/src/site/es/markdown/factorybean.md new file mode 100644 index 0000000000..598f28aef3 --- /dev/null +++ b/src/site/es/markdown/factorybean.md @@ -0,0 +1,100 @@ + +# SqlSessionFactoryBean + +En MyBatis una `SqlSessionFactory` se crea mediante la clase `SqlSessionFactoryBuilder`. En MyBatis-Spring se usa la clase `SqlSessionFactoryBean` en su lugar. + +## Configuración + +Para crear un factory bean, pon lo siguiente en el fichero XML de configuración de Spring: + +```xml + + + +``` + +La clase `SqlSessionFactoryBean` implementa el interfaz `FactoryBean` (see [the Spring documentation(Core Technologies -Customizing instantiation logic with a FactoryBean-](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-extension-factorybean)). +Lo cual significa que el bean que crea Spring en última instancia **no** es un `SqlSessionFactoryBean` en si mismo, sino el objeto que la factoria devuelve como resultado de la llamada al método `getObject()`. +En este caso, Spring creará un bean `SqlSessionFactory` durante el arranque de la aplicación y lo guardará bajo el nombre `sqlSessionFactory`. En Java, el código equivalente sería: + +```java +@Configuration +public class MyBatisConfig { + @Bean + public SqlSessionFactory sqlSessionFactory() { + SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); + factoryBean.setDataSource(dataSource()); + return factoryBean.getObject(); + } +} +``` + +Normalmente no necesitarás utilizar directamente un `SqlSessionFactoryBean` o su correspondiente `SqlSessionFactory` directly. +En su lugar, la factoría se utilizará para ser inyectada en `MapperFactoryBean`s o DAOs que extiendan de `SqlSessionDaoSupport`. + +## Properties + +La clase `SqlSessionFactory` solo tiene una propiedad obligatoria, un `DataSource`. +Puede ser cualquier `DataSource` y se puede configurar como cualquier otra conexión a base de daots de Spring. + +Una propiedad muy común es la `configLocation` que se utiliza para indicar la localización del fichero de configuración XML de MyBatis. +Normalmente solo es necesario dicho fichero si se requiere cambiar los valores por defecto de las secciones `` o ``. + +Es importante saber que este fichero de configuración **no** tiene por qué ser un fichero de configuración de MyBatis completo. +Concretamente, los environments, dataSources y transactionManagers serán **ignorados**. +`SqlSessionFactoryBean` crea su propio `Environment` de MyBatis con los valores configurados tal y como se requieren. + +Otro motivo para necesitar un fichero de configuración es que los ficheros de mapeo XML no estén en el mismo lugar del classpath que los mapper interfaces. +En este caso hay dos opciones. La primera es especificar manualmente el classpath de los ficheros XML usando la sección `` del fichero de configuración de MyBatis. +La segunda opción es usar la propiedad `mapperLocations` del factory bean. + +La propiedad `mapperLocations` recibe una lista de localizaciones de recursos. Se utiliza para indicar la ubicación de los ficheros de mapeo XML de MyBatis. +El valor puede contener un patron tipo Ant para cargar todos los ficheros de un directorio o buscar de forma recursiva en todos los paths desde una localización base. Por ejemplo: + +```xml + + + + +``` + +Esto cargaría todos los ficheros de mapeo XML en el paquete sample.config.mappers y sus subpaquetes. + +Otra propiedad que puede ser necesaria en un entorno con transacciones gestionadas por contenedor es la `transactionFactoryClass`. Lee la sección de transacciones para obtener más detalles. + +En caso de usar la característica multi-db necesitarás informar la propiedad `databaseIdProvider` de la siguiente forma: + +```xml + + + + sqlserver + db2 + oracle + mysql + + + +``` +```xml + + + + + +``` + +NOTE +Since 1.3.0, `configuration` property has been added. It can be specified a `Configuration` instance directly without MyBatis XML configuration file. +For example: + +```xml + + + + + + + + +``` diff --git a/src/site/es/markdown/getting-started.md b/src/site/es/markdown/getting-started.md new file mode 100644 index 0000000000..fdaedcaa30 --- /dev/null +++ b/src/site/es/markdown/getting-started.md @@ -0,0 +1,99 @@ + +# Primeros pasos + +Este capítulo te mostrará en pocos pasos cómo instalar y configurar MyBatis-Spring y cómo construir +una pequeña aplicación transaccional. + +## Instalación + +Para usar el módulo MyBatis-Spring, debes incluir el fichero `mybatis-spring-${project.version}.jar` y sus dependencias en el classpath. + +Si usas Maven simplemente añade la siguiente dependencia a tu pom.xml: + +```xml + + org.mybatis + mybatis-spring + ${project.version} + +``` + +## Configuración rápida + +Para usar MyBatis con Spring necesitas definir al menos dos cosas en tu contexto Spring: una `SqlSessionFactory` y al menos un mapper interface. + +En MyBatis-Spring se usa un `SqlSessionFactoryBean` para crear una `SqlSessionFactory`. Para configurar la factory bean pon lo siguiente en tu fichero de configuración de Spring: + +```xml + + + +``` + +```java +@Configuration +public class MyBatisConfig { + @Bean + public SqlSessionFactory sqlSessionFactory() throws Exception { + SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); + factoryBean.setDataSource(dataSource()); + return factoryBean.getObject(); + } +} +``` + +Observa que la `SqlSessionFactory` requiere un `DataSource`. Éste puede ser cualquier `DataSource` y debe configurarse como cualquier otra conexión a base de datos de Spring. + +Asumamos que tienes un mapper interface definido de la siguiente forma: + +```java +public interface UserMapper { + @Select("SELECT * FROM users WHERE id = #{userId}") + User getUser(@Param("userId") String userId); +} +``` + +Este interface se añade a Spring usando un `MapperFactoryBean` de la siguiente forma: + +```xml + + + + +``` + +Observa que la clase del mapper indicada **debe** ser un interface, no una implementación. En este ejemplo se usan anotaciones para especificar la SQL, pero también es posible usar un fichero de mapeo XML. + +Una vez configurado, puedes inyectar mappers directamente en tus beans de servicio/negocio de la misma forma que inyectarías cualquier otro bean en Spring. +La clase `MapperFactoryBean` se encargará de obtener una `SqlSession` y de cerrarla. Si hay una transación Spring en curso, la sesión se comitará o se hará rollback cuando la transacción finalice. +Finalmente, cualquier excepción será traducida a una excepión `DataAccessException`s de Spring. + +If you use the Java Configuration: + +```java +@Configuration +public class MyBatisConfig { + @Bean + public UserMapper userMapper() throws Exception { + SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory()); + return sqlSessionTemplate.getMapper(UserMapper.class); + } +} +``` + +Invocar a MyBatis es sólo una línea de código: + +```java +public class FooServiceImpl implements FooService { + + private final UserMapper userMapper; + + public FooServiceImpl(UserMapper userMapper) { + this.userMapper = userMapper; + } + + public User doSomeBusinessStuff(String userId) { + return this.userMapper.getUser(userId); + } +} +``` diff --git a/src/site/es/markdown/index.md b/src/site/es/markdown/index.md new file mode 100644 index 0000000000..ed37f9ad8c --- /dev/null +++ b/src/site/es/markdown/index.md @@ -0,0 +1,55 @@ + +# Introduction + +## ¿Qué es MyBatis-Spring? + +MyBatis-Spring permite integrar MyBatis con Spring. Esta librería permite que MyBatis participe en trasacciones Spring, +se encarga de constuir mappers y `SqlSession`s e inyectarlos en otros beans, traduce excepciones de MyBatis en excepcines `DataAccessException`s de Spring y finalmente, permite construir aplicaciones libres de dependencias de MyBatis, Spring y MyBatis-Spring. + +## Motivación + +Spring version 2 sólo soporta iBATIS version 2. See hizo un intento de incluir el soporte de MyBatis 3 en Spring 3 (ver el [issue Jira](https://jira.springsource.org/browse/SPR-5991)). +Pero desafortunadamente, el desarrollo de Spring 3 finalizó antes de que MyBatis 3 fuera liberado oficialmente. +Dado que el equipo de Spring no quería liberar una versión basada en un producto no terminado el soporte de oficial tenía que esperar. +Dado el interés de la comunidad en el soporte de MyBatis, la comunidad de MyBatis decidió que era el momento de unificar a los colaboradores interesados y proporcionar la integración con Spring como un sub-projecto de MyBatis en su lugar. + +## Requisitos + +Antes de comenzar con MyBatis-Spring, es muy importante que estés familiarizado con la terminología tanto de MyBatis como de Spring. +Este documento no pretende proporcionar información de configuración básica de MyBatis o Spring. + +MyBatis-Spring requires following versions: + +| MyBatis-Spring | MyBatis | Spring Framework | Spring Batch | Java | +| --- | --- | --- | --- | --- | +| **2.0** | 3.5+ | 5.0+ | 4.0+ | Java 8+ | +| **1.3** | 3.4+ | 3.2.2+ | 2.1+ | Java 6+ | + +## Agradecimientos + +Queremos agradecer a la todos los que han hecho de este proyecto una realidad (en orden alfabético): +Eduardo Macarron, Hunter Presnall y Putthiphong Boonphong por la codificación, pruebas y documentación; +a Andrius Juozapaitis, Giovanni Cuccu, Mike Lanyon, Raj Nagappan y Tomas Pinos por sus contribuciones; +y a Simone Tripodi por encontrarlos a todos y traerlos al proyecto MyBatis ;) Sin ellos este proyecto no existiría. + +## Colabora en mejorar esta documentación... + +Si ves que hay alguna carencia en esta documentación, o que falta alguna característica por documentar, te animamos a que lo investigues y la documentes tu mismo! + +Las fuentes de este manual están disponibles en formato xdoc en el [Git del proyecto](https://github.com/mybatis/mybatis-3/tree/master/src/site). Haz un fork, cambialas y envía un pull request. + +Eres el mejor candidato para documentar porque los lectores de esta documentación son gente como tú! + +## Translations + +Users can read about MyBatis-Spring in the following translations: + + + +Do you want to read about MyBatis in your own native language? Fill an issue providing patches with your mother tongue documentation! diff --git a/src/site/es/markdown/mappers.md b/src/site/es/markdown/mappers.md new file mode 100644 index 0000000000..51dd4293d8 --- /dev/null +++ b/src/site/es/markdown/mappers.md @@ -0,0 +1,185 @@ + +# Inyectar mappers + +En lugar de codificar DAOs (data access objects) manualmente usando la clase `SqlSessionDaoSupport` o `SqlSessionTemplate`, Mybatis-Spring puede crear un mapper thread-safe que puedes inyectar directamente en otros beans. + +```xml + + + +``` + + Una vez inyectado, el mapper está listo para se usado en la lógica de aplicación: + +```java +public class FooServiceImpl implements FooService { + + private final UserMapper userMapper; + + public FooServiceImpl(UserMapper userMapper) { + this.userMapper = userMapper; + } + + public User doSomeBusinessStuff(String userId) { + return this.userMapper.getUser(userId); + } +} +``` + +Observa que no se usa la `SqlSession` ni ninguna otra referencia a MyBatis en este código. No es necesario ni siquiera crear o cerrar la sesión, MyBatis-Spring se encarga de ello. + + +## Registrar un mapper + +La forma de registrar un mapper varía según si quieres usar la configuración XML clásica o la nueva Java Config de Spring 3.0+ (También conocida como `@Configuration`). + +### Con confiugración XML + +Un mapper se registra en Spring incluyendo un `MapperFactoryBean` en tu fichero de configuración XML, de la siguiente forma: + +```xml + + + + +``` + +Si el mapper UserMapper tiene un fichero XML de mapeo asociado el `MapperFactoryBean` lo cargará automáticamente. +Por lo tanto no es necesario especificar dicho mapper en el fichero de configuración de MyBatis a no ser que los ficheros XML estén en una lugar distinto del classpath. +Ver la sección de `SqlSessionFactoryBean` y la propiedad [`configLocation`](factorybean.html) para más información. + +El `MapperFactoryBean` requiere o un `SqlSessionFactory` o un `SqlSessionTemplate`. +Ambos se pueden informar usando sendas propiedades `sqlSessionFactory` y `sqlSessionTemplate`. +Si ambas propiedades han sdo informadas la `SqlSessionFactory` se ignora. +Dado que un `SqlSessionTemplate` debe tener un session factory dicho factory se usará por el `MapperFactoryBean`. + +### Con Java Config + +```java +@Configuration +public class MyBatisConfig { + @Bean + public MapperFactoryBean userMapper() throws Exception { + MapperFactoryBean factoryBean = new MapperFactoryBean<>(UserMapper.class); + factoryBean.setSqlSessionFactory(sqlSessionFactory()); + return factoryBean; + } +} +``` + + +## Escanear mappers + +No es necesario registrar los mappers uno por uno en el fichero XML de Spring. En lugar de esto, puede dejar que MyBatis-Spring los busque en tu classpath. + +Hay tres formas distintas de hacerlo: + +* Usando el elemneto ``. +* Usando la anotación `@MapperScan` +* Usando un fichero clásico XML de configuración de Spring y añadiendo el bean `MapperScannerConfigurer` + +Tango `` como `@MapperScan` son características añadidas en MyBatis-Spring 1.2.0. `@MapperScan` requiere Spring 3.1+. + +Since 2.0.2, mapper scanning feature support a option (`lazy-initialization`) that control lazy initialization enabled/disabled of mapper bean. +The motivation for adding this option is supporting a lazy initialization control feature supported by Spring Boot 2.2. +The default of this option is `false` (= not use lazy initialization). +If developer want to use lazy initialization for mapper bean, it should be set to the `true` expressly. + +IMPORTANT +If use the lazy initialization feature, the developer need to understand following limitations. +If any of following conditions are matches, usually the lazy initialization feature cannot use on your application. + +* When refers to the statement of **other mapper** using ``(`@One`) and ``(`@Many`) +* When includes to the fragment of **other mapper** using `` +* When refers to the cache of **other mapper** using ``(`@CacheNamespaceRef`) +* When refers to the result mapping of **other mapper** using `]]> - -

A continuación se muestra un ejemplo de configuración:

- - - - -
]]> - - reader() { - return new MyBatisPagingItemReaderBuilder() - .sqlSessionFactory(sqlSessionFactory()) - .queryId("com.my.name.space.batch.EmployeeMapper.getEmployee") - .build(); -}]]> - -

Veamos un ejemplo más complejo:

- - - - - - - - -]]> - - dateBasedCriteriaReader( - @Value("#{@datesParameters}") Map datesParameters) throws Exception { - return new MyBatisPagingItemReaderBuilder() - .sqlSessionFactory(batchReadingSessionFactory()) - .queryId("com.my.name.space.batch.ExampleMapper.queryUserInteractionsOnSpecificTimeSlot") - .parameterValues(datesParameters) - .pageSize(200) - .build(); -} - -@StepScope -@Bean -public Map datesParameters( - @Value("#{jobExecutionContext['EXTRACTION_START_DATE']}") LocalDate yesterday, - @Value("#{jobExecutionContext['TODAY_DATE']}") LocalDate today, - @Value("#{jobExecutionContext['FIRST_DAY_OF_THE_MONTH_DATE']}") LocalDate firstDayOfTheMonth, - @Value("#{jobExecutionContext['FIRST_DAY_OF_THE_PREVIOUS_MONTH_DATE']}") LocalDate firstDayOfThePreviousMonth) { - Map map = new HashMap<>(); - map.put("yesterday", yesterday); - map.put("today", today); - map.put("first_day_of_the_month", firstDayOfTheMonth); - map.put("first_day_of_the_previous_month", firstDayOfThePreviousMonth); - return map; -}]]> - -

- El ejemplo anterior hace uso de tres cosas distintas: -

- -
    -
  • sqlSessionFactory: Puedes tu propio sessionFactory, podría ser útil si quires leer de - varias bases de datos.
  • -
  • queryId: Si el código accede a varias tablas, y tienes distintas sentencias de consulta, - puede ser interesante usar ficheros de mapeo distintos con namespaces distintos. - En este caso, al referirte a la query, no olvides incluir el namespace correspondiente.
  • -
  • parameterValues: Puedes pasar parametros adicionales en este mapa, el ejemplo de arriba - usa un mapa que se construye usando una expresion SpEL y obteniendo valores del jobExecutionContext. - Las claves del mapa puede usarse en el fichero mapper de MyBatis (por ejemplo: - yesterday se puede usar como #{yesterday,jdbcType=TIMESTAMP}). - Observa que el mapa y el reader se consutruyen en un solo step para que sea posible usar la expresión - SpEL con el jobExecutionContext. Adicionalmente si los type handlers de MyBatis - están configurados correctamente puedes pasar instancias personalizadas como los parametros del ejemplo que son - fechas JodaTime.
  • -
  • pageSize: Si le flujo batch está configurado con un tamaño de bloque (chunk size), - es importante pasar esta información al reader, y eso se hace mediante esta propiedad.
  • -
- - - - -

- Este bean es un ItemReader que lee registros de la base de datos usando un cursor. -

- -

- NOTA Para usar este bean necesitas al menos MyBatis 3.4.0 o superior. -

- -

- Ejecuta la sentencia especificada mediante la propiedad setQueryId para obtener los datos - usando el método selectCursor(). - Al llamar al método read() se devolverá el siguiente elemento del cursor - hasta que no quede ninguno por devolver. -

- -

- El reader usa una conexión separada para que la sentencia no participe en ninguna transacción creada como parte - del proceso del step. -

- -

Cuando se usar un cursor puedes usar una sentencia convencional:

- - SELECT id, name, job FROM employees ORDER BY id ASC -]]> - -

A continuación se muestra un ejemplo de configuración:

- - - - -
]]> - - reader() { - return new MyBatisCursorItemReaderBuilder() - .sqlSessionFactory(sqlSessionFactory()) - .queryId("com.my.name.space.batch.EmployeeMapper.getEmployee") - .build(); -}]]> - - - - - -

- Es un ItemWriter que usa las capacidades de batch de SqlSessionTemplate para - ejecutar sentencias batch para todos los elementos (items) proporcionados. - El SqlSessionFactory debe configurarse con un executor de tipo BATCH. -

- -

- Ejecuta la sentencia indicada en la propiedad statementId cuando se invoca a write(). - Se supone que write() se invoca dentro de una transacción.
-

- -

A continuación se muestra un ejemplo de configuración:

- - - - -
]]> - - writer() { - return new MyBatisBatchItemWriterBuilder() - .sqlSessionFactory(sqlSessionFactory()) - .statementId("com.my.name.space.batch.EmployeeMapper.updateEmployee") - .build(); -}]]> - - -

Converting a item that read using ItemReader to an any parameter object:

- -

- By default behavior, the MyBatisBatchItemWriter passes a item that read using ItemReader - (or convert by ItemProcessor) to the MyBatis(SqlSession#update()) as the parameter object. - If you want to customize a parameter object that passes to the MyBatis, you can realize to use the itemToParameterConverter option. - For example using itemToParameterConverter option, you can passes any objects other than the item object to the MyBatis. - Follows below a sample: -

- -

- At first, you create a custom converter class (or factory method). The following sample uses a factory method. -

- - Converter> createItemToParameterMapConverter(String operationBy, LocalDateTime operationAt) { - return item -> { - Map parameter = new HashMap<>(); - parameter.put("item", item); - parameter.put("operationBy", operationBy); - parameter.put("operationAt", operationAt); - return parameter; - }; -}]]> - -

- At next, you write a sql mapping. -

- - - insert into persons (first_name, last_name, operation_by, operation_at) - values(#{item.firstName}, #{item.lastName}, #{operationBy}, #{operationAt}) -]]> - -

- At last, you configure the MyBatisBatchItemWriter. -

- - writer() throws Exception { - return new MyBatisBatchItemWriterBuilder() - .sqlSessionFactory(sqlSessionFactory()) - .statementId("org.mybatis.spring.sample.mapper.PersonMapper.createPerson") - .itemToParameterConverter(createItemToParameterMapConverter("batch_java_config_user", LocalDateTime.now())) - .build(); -}]]> - - - - - - - - - - - - -]]> - -

Escribiendo en distintas tablas usando composite writers (con algunos condicionantes):

- -

Esta técnica sólo puede usarse con MyBatis 3.2+, por que había un - error - en las versiones anteriores que hacían que el writer funcionara de forma incorrecta. -

- -

Si el batch necesita escribir datos complejos, como registros con asociaciones, o en distintas bases de datos, - entonces es necesario sortear el problema de que los insert statements solo pueden escribir en una tabla. - Para conseguir esto debes preparar un Item para que sea escrito por el writer. Sin embargo, - dependiendo de las circunstancias puede ser interesante usar la siguiente técnica. - El truco siguiente funciona con items con asociaciones simples o con tablas no relacionadas. -

- -

- Elabora el item de forma que contenta todos los resgistros distintos. - Supon que para cada item hay una Interaction que tiene una asociación - InteractionMetadata y dos filas no asociadas VisitorInteraction and - CustomerInteraction. El objeto contenedor será de la siguiente forma: -

- - - -

- Entonces en la configuración de spring habrá un CompositeItemWriter que usará writers - delegados configurados especificamente para cada tipo de registro. Fijate que el InteractionMetadata - es una asociacióin en el ejemplo por lo que debe ser escrita antes para que la Interaction pueda recibir la clave - generada. -

- - - - - - - - - - - - -]]> - - interactionsItemWriter() { - CompositeItemWriter compositeItemWriter = new CompositeItemWriter(); - List> writers = new ArrayList<>(4); - writers.add(visitorInteractionsWriter()); - writers.add(customerInteractionsWriter()); - writers.add(interactionMetadataWriter()); - writers.add(interactionWriter()); - compositeItemWriter.setDelegates(writers); - return compositeItemWriter; -}]]> - -

Cada writer delegados se configura como sea necesario, por ejemplo para Interaction y - InteractionMetadata: -

- - -]]> - -

Al igual que con el reader el statementId puede hacer referencia al statement con un namespace como prefijo.

- -

Ahora es debe elaborarse el fichero de mapeo para cada tipo de registro, de la siguiente forma:

- - - - - - -]]> - -

- Lo que sucede es que primeramente se llamará a insertInteractionMetadata, y la sentencia de update - está configurada para devolver las claves autogeneradas (keyProperty y keyColumn). - Una vez que el InteractionMetadata se ha almacenado por esta sentencia se puede ejecutar la siguiente para - escribir el objeto padre Interaction mediante insertInteraction. -

- -

- Sin embargo, ten en cuenta que los drivers JDBC se comportan distinto en este aspecto. A la fecha en la que se escribe esto - el driver H2 1.3.168 solo devuelve el último ID incluso en modo BATCH (see org.h2.jdbc.JdbcStatement#getGeneratedKeys), - mientras que el driver JDBC de MySQL se comporta como es de esperar y devuelve todos los IDs. -

- - - - diff --git a/src/site/es/xdoc/boot.xml b/src/site/es/xdoc/boot.xml deleted file mode 100644 index fd430114c4..0000000000 --- a/src/site/es/xdoc/boot.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - MyBatis-Spring | Spring Boot - Eduardo Macarron - - - -
-

- Please see the MyBatis Spring-boot-starter - subproject docs for details. -

-
- -
diff --git a/src/site/es/xdoc/factorybean.xml b/src/site/es/xdoc/factorybean.xml deleted file mode 100644 index a3000ac76b..0000000000 --- a/src/site/es/xdoc/factorybean.xml +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - MyBatis-Spring | SqlSessionFactoryBean - Hunter Presnall - Eduardo Macarron - - - -
-

- En MyBatis una SqlSessionFactory se crea mediante la clase - SqlSessionFactoryBuilder. En MyBatis-Spring se usa la clase - SqlSessionFactoryBean en su lugar. -

- - -

- Para crear un factory bean, pon lo siguiente en el fichero XML de configuración de Spring: -

- - -]]> -

- La clase SqlSessionFactoryBean implementa el interfaz FactoryBean - (see the Spring documentation(Core Technologies -Customizing instantiation logic with a FactoryBean-)). - Lo cual significa que el bean que crea Spring - en última instancia no es un SqlSessionFactoryBean en si mismo, sino el - objeto que la factoria devuelve como resultado de la llamada al método - getObject(). En este caso, Spring creará un bean - SqlSessionFactory durante el arranque de la aplicación y lo guardará bajo el nombre - sqlSessionFactory. En Java, el código equivalente sería: -

- - - -

- Normalmente no necesitarás utilizar directamente un SqlSessionFactoryBean - o su correspondiente SqlSessionFactory directly. - En su lugar, la factoría se utilizará para ser inyectada en MapperFactoryBeans o - DAOs que extiendan de SqlSessionDaoSupport. -

-
- - - -

- La clase SqlSessionFactory solo tiene una propiedad obligatoria, un DataSource. - Puede ser cualquier DataSource y se puede configurar como cualquier otra conexión a base de daots de Spring. -

- -

- Una propiedad muy común es la configLocation que se utiliza para indicar la localización del fichero de configuración - XML de MyBatis. Normalmente solo es necesario dicho fichero si se requiere cambiar los valores por defecto de las secciones - <settings> o <typeAliases>. -

- -

- Es importante saber que este fichero de configuración no tiene por qué ser un fichero de configuración de MyBatis completo. - Concretamente, los environments, dataSources y transactionManagers serán ignorados. - SqlSessionFactoryBean crea su propio Environment de MyBatis con los valores configurados tal y como se requieren. -

- -

- Otro motivo para necesitar un fichero de configuración es que los ficheros de mapeo XML no estén en el mismo lugar del classpath - que los mapper interfaces. En este caso hay dos opciones. La primera es especificar manualmente el classpath de los ficheros XML - usando la sección <mappers> del fichero de configuración de MyBatis. La segunda opción es usar la propiedad - mapperLocations del factory bean. -

- -

- La propiedad mapperLocations recibe una lista de localizaciones de recursos. Se utiliza para indicar la ubicación de los - ficheros de mapeo XML de MyBatis. El valor puede contener un patron tipo Ant para cargar todos los ficheros de un directorio o - buscar de forma recursiva en todos los paths desde una localización base. Por ejemplo: -

- - - - -]]> - -

- Esto cargaría todos los ficheros de mapeo XML en el paquete sample.config.mappers y sus subpaquetes. -

- -

- Otra propiedad que puede ser necesaria en un entorno con transacciones gestionadas por contenedor es la - transactionFactoryClass. Lee la sección de transacciones para obtener más detalles. -

- -

- En caso de usar la característica multi-db necesitarás informar la propiedad databaseIdProvider - de la siguiente forma: -

- - - - - sqlserver - db2 - oracle - mysql - - - - - - - - -]]> - -

- NOTE - Since 1.3.0, configuration property has been added. - It can be specified a Configuration instance directly without MyBatis XML configuration file. - For example: -

- - - - - - - - -]]> - -
-
- -
diff --git a/src/site/es/xdoc/getting-started.xml.vm b/src/site/es/xdoc/getting-started.xml.vm deleted file mode 100644 index 5b4f2c5dad..0000000000 --- a/src/site/es/xdoc/getting-started.xml.vm +++ /dev/null @@ -1,158 +0,0 @@ - - - - - - MyBatis-Spring | Primeros pasos - Hunter Presnall - Eduardo Macarron - - - -
-

- Este capítulo te mostrará en pocos pasos cómo instalar y configurar MyBatis-Spring y cómo construir - una pequeña aplicación transaccional. -

- - -

- Para usar el módulo MyBatis-Spring, debes incluir el fichero - mybatis-spring-${project.version}.jar - y sus dependencias en el classpath. -

-

- Si usas Maven simplemente añade la siguiente dependencia a tu pom.xml: -

- - org.mybatis - mybatis-spring - ${project.version} -]]> -
- - -

- Para usar MyBatis con Spring necesitas definir al menos dos cosas en tu contexto Spring: una - SqlSessionFactory y al menos un mapper interface. -

- -

- En MyBatis-Spring se usa un - SqlSessionFactoryBean - para crear una - SqlSessionFactory - . Para configurar la factory bean pon lo siguiente en tu - fichero de configuración de Spring: -

- - - -]]> - - - -

- Observa que la SqlSessionFactory - requiere un - DataSource - . Éste puede ser cualquier - DataSource - y debe configurarse como cualquier otra conexión a base de datos - de Spring. -

- -

- Asumamos que tienes un mapper interface definido de la siguiente forma: -

- - -

- Este interface se añade a Spring usando un - MapperFactoryBean - de la siguiente forma: -

- - - -]]> - -

- Observa que la clase del mapper indicada - debe - ser un interface, no una implementación. En este ejemplo se usan - anotaciones para especificar la SQL, pero también es posible - usar un fichero de mapeo XML. -

- -

- Una vez configurado, puedes inyectar mappers directamente en tus - beans de servicio/negocio de la misma forma que inyectarías cualquier - otro bean en Spring. - La clase MapperFactoryBean se encargará de obtener - una SqlSession y de cerrarla. Si hay una transación Spring - en curso, la sesión se comitará o se hará rollback cuando la transacción - finalice. Finalmente, cualquier excepción será traducida a una excepión - DataAccessExceptions de Spring. -

- -

- If you use the Java Configuration: -

- - - -

- Invocar a MyBatis es sólo una línea de código: -

- -
-
- -
diff --git a/src/site/es/xdoc/index.xml b/src/site/es/xdoc/index.xml deleted file mode 100644 index 1e7aa83162..0000000000 --- a/src/site/es/xdoc/index.xml +++ /dev/null @@ -1,160 +0,0 @@ - - - - - - MyBatis-Spring | Introducción - Hunter Presnall - Eduardo Macarron - - - -
- -

- MyBatis-Spring permite integrar MyBatis con Spring. - Esta librería permite que MyBatis participe en trasacciones Spring, se encarga de constuir - mappers y SqlSessions e inyectarlos en otros beans, traduce excepciones - de MyBatis en excepcines DataAccessExceptions de Spring y finalmente, - permite construir aplicaciones libres de dependencias de MyBatis, Spring y MyBatis-Spring. -

-
- - -

- Spring version 2 sólo soporta iBATIS version 2. See hizo un intento de incluir el soporte - de MyBatis 3 en Spring 3 (ver el issue Jira). - Pero desafortunadamente, el desarrollo de Spring 3 finalizó antes de que MyBatis 3 fuera liberado oficialmente. - Dado que el equipo de Spring no quería liberar una versión basada en un producto no terminado el soporte de - oficial tenía que esperar. Dado el interés de la comunidad en el soporte de MyBatis, - la comunidad de MyBatis decidió que era el momento de unificar a los colaboradores interesados - y proporcionar la integración con Spring como un sub-projecto de MyBatis en su lugar. -

-
- - -

- Antes de comenzar con MyBatis-Spring, es muy importante que estés familiarizado con la terminología tanto de - MyBatis como de Spring. Este documento no pretende proporcionar información de configuración básica de - MyBatis o Spring. -

-

- MyBatis-Spring requires following versions: -

- - - - - - - - - - - - - - - - - - - - - - - - - - -
- MyBatis-Spring - - MyBatis - - Spring Framework - - Spring Batch - - Java -
- 2.0 - - 3.5+ - - 5.0+ - - 4.0+ - - Java 8+ -
- 1.3 - - 3.4+ - - 3.2.2+ - - 2.1+ - - Java 6+ -
-
- - -

- Queremos agradecer a la todos los que han hecho de este proyecto una realidad (en orden alfabético): - Eduardo Macarron, Hunter Presnall y Putthiphong Boonphong por la codificación, pruebas y documentación; - a Andrius Juozapaitis, Giovanni Cuccu, Mike Lanyon, Raj Nagappan y Tomas Pinos - por sus contribuciones; y a Simone Tripodi por encontrarlos a todos y traerlos al proyecto MyBatis ;) - Sin ellos este proyecto no existiría. -

-
- - -

- Si ves que hay alguna carencia en esta documentación, o que falta alguna característica por documentar, - te animamos a que lo investigues y la documentes tu mismo! -

-

- Las fuentes de este manual están disponibles en formato xdoc en el - Git del proyecto. - Haz un fork, cambialas y envía un pull request. -

-

- Eres el mejor candidato para documentar porque los lectores de esta documentación son gente como tú! -

-
- -

Users can read about MyBatis-Spring in the following translations:

- -

Do you want to read about MyBatis in your own native language? Fill an issue providing patches with your - mother tongue documentation!

-
-
- - -
diff --git a/src/site/es/xdoc/mappers.xml b/src/site/es/xdoc/mappers.xml deleted file mode 100644 index 26f6b45683..0000000000 --- a/src/site/es/xdoc/mappers.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - - - MyBatis-Spring | Inyectar mappers - Hunter Presnall - Eduardo Macarron - - - -
-

- En lugar de codificar DAOs (data access objects) manualmente usando la clase - SqlSessionDaoSupport o SqlSessionTemplate, Mybatis-Spring - puede crear un mapper thread-safe que puedes inyectar directamente en otros beans. -

- - - -]]> - -

- Una vez inyectado, el mapper está listo para se usado en la lógica de aplicación: -

- -

- Observa que no se usa la SqlSession ni ninguna otra referencia a MyBatis en este código. - No es necesario ni siquiera crear o cerrar la sesión, MyBatis-Spring se encarga de ello. -

- - - -

- La forma de registrar un mapper varía según si quieres usar la configuración XML clásica o la nueva Java Config de Spring 3.0+ - (También conocida como @Configuration).

- -

Con confiugración XML

- -

- Un mapper se registra en Spring incluyendo un MapperFactoryBean en tu fichero de configuración XML, de la siguiente forma: -

- - - -]]> - -

- Si el mapper UserMapper tiene un fichero XML de mapeo asociado el MapperFactoryBean - lo cargará automáticamente. Por lo tanto no es necesario especificar dicho mapper en el fichero - de configuración de MyBatis a no ser que los ficheros XML estén en una lugar distinto del classpath. - Ver la sección de SqlSessionFactoryBean y la propiedad - configLocation - para más información. -

- -

- El MapperFactoryBean requiere o un - SqlSessionFactory o un SqlSessionTemplate. - Ambos se pueden informar usando sendas propiedades sqlSessionFactory y - sqlSessionTemplate. - Si ambas propiedades han sdo informadas la SqlSessionFactory se ignora. - Dado que un SqlSessionTemplate debe tener un session factory - dicho factory se usará por el MapperFactoryBean. -

- -

Con Java Config

- - userMapper() throws Exception { - MapperFactoryBean factoryBean = new MapperFactoryBean<>(UserMapper.class); - factoryBean.setSqlSessionFactory(sqlSessionFactory()); - return factoryBean; -}]]> - -
- - -

- No es necesario registrar los mappers uno por uno en el fichero XML de Spring. - En lugar de esto, puede dejar que MyBatis-Spring los busque en tu classpath. -

- -

- Hay tres formas distintas de hacerlo: -

-
    -
  • Usando el elemneto <mybatis:scan/>.
  • -
  • Usando la anotación @MapperScan
  • -
  • Usando un fichero clásico XML de configuración de Spring y añadiendo el bean MapperScannerConfigurer
  • -
- -

Tango <mybatis:scan/> como @MapperScan son características añadidas en MyBatis-Spring 1.2.0. - @MapperScan requiere Spring 3.1+.

- -

- Since 2.0.2, mapper scanning feature support a option (lazy-initialization) - that control lazy initialization enabled/disabled of mapper bean. - The motivation for adding this option is supporting a lazy initialization control feature supported by Spring Boot 2.2. - The default of this option is false (= not use lazy initialization). - If developer want to use lazy initialization for mapper bean, it should be set to the true expressly. -

-

- IMPORTANT If use the lazy initialization feature, - the developer need to understand following limitations. If any of following conditions are matches, - usually the lazy initialization feature cannot use on your application. -

-
    -
  • When refers to the statement of other mapper using ]]>(@One) and ]]>(@Many)
  • -
  • When includes to the fragment of other mapper using ]]>
  • -
  • When refers to the cache of other mapper using ]]>(@CacheNamespaceRef)
  • -
  • When refers to the result mapping of other mapper using ]]>(@ResultMap)
  • -
- -

- NOTE However, It become possible to use it by simultaneously initializing dependent beans using @DependsOn(Spring's feature) as follow: -

- - - -

- Since 2.0.6, the develop become can specified scope of mapper using mapper scanning feature option(default-scope) - and scope annotation(@Scope, @RefreshScope, etc ...). - The motivation for adding this option is supporting the refresh scope provided by the Spring Cloud. - The default of this option is empty (= equiv to specify the singleton scope). - The default-scope apply to the mapper bean(MapperFactoryBean) when scope of scanned bean definition - is singleton(default scope) and create a scoped proxy bean for scanned mapper when final scope is not singleton. -

- -

<mybatis:scan/>

- -

- El elemento XML <mybatis:scan/> busca mappers de una forma muy similar a cómo - <context:component-scan/> busca beans. -

- -

A continuación se muestra un fichero XML de configuración:

- - - - - - - -]]> - -

- La propiedad basePackage te permite indicar el paquete base donde residen tus mappers. - Puedes indicar más de un paquete usando un punto y coma o una coma como separador. Los mappers serán buscados - de forma recursiva comenzando en el/los paquetes especificados. -

- -

- Fíjate que no es necesario indicar una SqlSessionFactory o - SqlSessionTemplate porque el <mybatis:scan/> - creará MapperFactoryBeans que pueden ser autowired. Pero si usas más de un DataSource - el autowire puede que no te funcione. En este caso puedes usar las propiedades factory-ref or - template-ref para indicar los beans correctos a utilizar. -

- -

- <mybatis:scan/> soporta el filtrado de mappers mediante una interfaz marcador o una anotación. - La propiedad annotation especifica la anotación que se debe buscar. - La propiedad marker-interface especifica la interfaz a buscar. - Si se indican ambas se añadirán todos los mappers que cumplan cualquier criterio. - Por defecto ambas propiedades son null asi que todos los interfaces de los paquetes base serán cargados como mappers. -

- -

- Los mappers descubiertos serán nombrados usando la estratégia de nombres por defecto de Spring para los componentes - autodetectados (see the Spring reference document(Core Technologies -Naming autodetected components-)). - Es decir, si no se encuentra ninguna anotación, se usará el nombre no cualificado sin capitalizar del mapper. - Pero si se encuentra una anotación @Component o JSR-330 @Named se obtendrá el nombre de dicha anotación. - Fíjate que puedes usar como valor de la annotation el valor org.springframework.stereotype.Component, - javax.inject.Named (if you have JSE 6) o una anotación propia - (que debe ser a su vez anotada) de forma que la anotación hará las veces de localizador y de proveedor de nombre. -

- -

- NOTE <context:component-scan/> - no puede encontrar y registrar mappers. Los mappers son interfaces y, para poderlos registrar en Spring, - el scanner deben conocer cómo crear un MapperFactoryBean para cada interfaz encontrado. -

- -

@MapperScan

- -

- Si usas la Java Configuration de Spring (@Configuration) posiblemente prefieras usar - @MapperScan en lugar de <mybatis:scan/>. -

- -

La anotación @MapperScan se usa de la siguiente forma:

- - - -

- La anotación fucniona exactamente igual que <mybatis:scan/> que hemos visto en la sección anterior. - También te permite especificar un interfaz marcador o una anotación mediante sus propiedades - markerInterface y annotationClass. - Tambien puedes indicar una SqlSessionFactory o un SqlSessionTemplate específicos - mediante las propiedades sqlSessionFactory y sqlSessionTemplate. -

- -

- NOTE Since 2.0.4, If basePackageClasses or basePackages are not defined, scanning will occur from the package of the class that declares this annotation. -

- -

MapperScannerConfigurer

- -

- MapperScannerConfigurer es un BeanDefinitionRegistryPostProcessor - que se puede incluir como un bean normal en el fichero clásico XML de configuración de Spring. - Para configurar un MapperScannerConfigurer añade lo siguiente al fichero de configuración de Spring: -

- - -]]> - -

- Si quieres indicar un sqlSessionFactory o un sqlSessionTemplate - observa que se requeiren los nombres de los beans y no sus referencias - por ello se usa el atributo value en lugar del habitual ref: -

- ]]> - -
-
- -
diff --git a/src/site/es/xdoc/sample.xml b/src/site/es/xdoc/sample.xml deleted file mode 100644 index cd0620f742..0000000000 --- a/src/site/es/xdoc/sample.xml +++ /dev/null @@ -1,177 +0,0 @@ - - - - - - MyBatis-Spring | Sample Code - Eduardo Macarron - - - -
- -

- NOTE - See JPetstore 6 demo to know about how to use Spring with a full web application server. -

- -

- You can check out sample code from the MyBatis-Spring repo: -

-

- Any of the samples can be run with JUnit 5. -

-

- The sample code shows a typical design where a transactional service gets domain objects from a data access layer. -

-

- FooService.java acts as the service: -

- -

- It is a transactional bean, so when the method is called, the transaction is started - and the transaction is committed when the method ends without throwing an uncaught exception. - Notice that transactional behaviour is configured with the - @Transactional - attribute. This is not required; any other way provided by Spring can be used to demarcate - your transactions. -

-

- This service calls a data access layer built with MyBatis. This layer - consists on a just an interface UserMapper.java - that will be used with a dynamic proxy built by MyBatis at - runtime and injected into the service by Spring. -

- -

- Note that, for the sake of simplicity we used the interface UserMapper.java for the DAO scenario - where a DAO is built with an interface and a implementation though in this case it would have been more - adequate to use an interface called UserDao.java instead. -

-

- We will see different ways to find the mapper interface, register it to Spring and inject it into the service bean: -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Scenarios
Sample testDescription
- SampleMapperTest.java - - Shows you the base configuration based on a MapperFactoryBean - that will dynamically build an implementation for UserMapper -
- SampleScannerTest.java - - Shows how to use the MapperScannerConfigurer so all the mappers in a project are autodiscovered. -
- SampleSqlSessionTest.java - - Shows how to hand code a DAO using a Spring managed SqlSession - and providing your own implementation UserDaoImpl.java. -
- SampleEnableTest - - Shows how to use Spring's @Configuration with the @MapperScann annotation so - mappers are autodiscovered. -
- SampleNamespaceTest - - Shows how to use the custom MyBatis XML namespace. -
- SampleJavaConfigTest.java - - Shows how to use Spring's @Configuration to create MyBatis beans manually. -
- SampleJobJavaConfigTest.java - - Shows how to use ItemReader and ItemWriter on Spring Batch using Java Configuration. -
- SampleJobXmlConfigTest.java - - Shows how to use ItemReader and ItemWriter on Spring Batch using XML Configuration. -
-

- Please take a look at the different applicationContext.xml files to see MyBatis-Spring in action. -

- -
- -
- diff --git a/src/site/es/xdoc/sqlsession.xml b/src/site/es/xdoc/sqlsession.xml deleted file mode 100644 index 925a7552b9..0000000000 --- a/src/site/es/xdoc/sqlsession.xml +++ /dev/null @@ -1,168 +0,0 @@ - - - - - - MyBatis-Spring | Utilizar un SqlSession - Hunter Presnall - Eduardo Macarron - - - -
-

- En MyBatis usas un SqlSessionFactory para crear un SqlSession. - Una vez tienes una sesión, la usas para ejecutar tus mapped statements, hacer commit o rollback y finalmente - cuando no la necesitas la cierras. Con MyBatis-Spring no es necesario que utilices la SqlSessionFactory - directamente porque puedes inyectar en tus beans una SqlSession thread safe (reentrante) - que hará de forma automática el commit, rollback y se cerrará conforme a la configuración de la transacción en Spring. -

- - -

- El SqlSessionTemplate is el corazón de MyBatis-Spring. - Implementa SqlSession y está pensado para que sea directamente reemplazable por cualquier código - que actualmente use SqlSession. - SqlSessionTemplate es thread safe y se puede compartir por más de un DAO. -

- -

- Cuando se invoca a cualquier método SQL, incluyendo cualquier método de un mapper devuelto por - getMapper(), el SqlSessionTemplate - se asegurará de que la SqlSession utilizada es la asociada con la transacción Spring en curso. - Adicionalmente, se encarga de gestionar su ciclo de vida, incluyendo su cierre, commit o rollback de la sesión si fuera necesario. -

- -

- Se debe usar siempre un SqlSessionTemplate en lugar de la implementación de sesión - por default MyBatis: DefaultSqlSession - porque el template puede participar en transacciones Spring y es thread safe con lo que puede ser inyectado - en múltiples mappers (proxies). Cambiar de uno a otro puede crear problemas de integridad de datos. -

- -

- El SqlSessionTemplate puede construirse usando un SqlSessionFactory como argumento de su constructor. -

- - -]]> - - - -

- Este bean puede ser inyectado directamente en tus DAOs. Necesitarás una propiedad - SqlSession en tu bean como se muestra a continuación: -

- -

- E inyectar el SqlSessionTemplate de la siguiente forma: -

- - -]]> - -

- El SqlSessionTemplate tiene también un constructor que recibe como parámetro - un ExecutorType. Esto permite construir, por ejemplo, - una SqlSession batch utilizando la siguiente configuracíon de Spring: -

- - - -]]> - - - -

- Ahora todos tus statements se ejecutarán en batch de forma que puedes programar lo siguiente: -

- users) { - for (User user : users) { - sqlSession.insert("org.mybatis.spring.sample.mapper.UserMapper.insertUser", user); - } -}]]> - -

- Fijate que esta configuración si el método de ejecución deseado es distinto del establecido por defecto - en el SqlSessionFactory. -

- -

- La contrapartida de esto es que no es posible cambiar el méodo de ejecución dentro de una transacción. - Por tanto asegurate que o bien todas las llamadas a un SqlSessionTemplates con distinto método de ejecución - se ejecutan en una transacción diferente (p.ej: with PROPAGATION_REQUIRES_NEW) o completamente fuera de la transacción. -

-
- - -

- SqlSessionDaoSupport es una clase de soporte abstracta que proporciona un SqlSession. - Llamando a getSqlSession() obtiene un SqlSessionTemplate - que puedes utilizar para ejecutar métodos SQL, como sigue: -

- -

- Normalmente es preferible usar un MapperFactoryBean a esta clase dao que no requeire código extra. - Pero esta clase es de utilidad cuando es necesario hacer algún otro tipo de trabajo no-MyBatis en el DAO y se necesitan - clases concretas. -

- -

- SqlSessionDaoSupport que se informe la propiedad - sqlSessionFactory o la sqlSessionTemplate. - Si se informan ambas propiedades, la sqlSessionFactory se ignora. -

- -

- Asumiendo una clase UserDaoImpl que extiende - SqlSessionDaoSupport, se puede configurar Spring de la siguiente forma: -

- - -]]> -
-
- -
diff --git a/src/site/es/xdoc/transactions.xml b/src/site/es/xdoc/transactions.xml deleted file mode 100644 index 5bf472c578..0000000000 --- a/src/site/es/xdoc/transactions.xml +++ /dev/null @@ -1,163 +0,0 @@ - - - - - - MyBatis-Spring | Transacciones - Hunter Presnall - Eduardo Macarron - - - -
-

- Uno de los principales motivos para usar MyBatis-Spring es que permite que MyBatis participe en transacciones - de Spring. En lugar de haber creado un TransactionManager especifico para MyBatis, MyBatis-Spring aprovecha - el existente DataSourceTransactionManager de Spring. -

-

- Una vez que has configurado un TransactionManager in Spring puedes configurar tus transacciones en Spring como siempre. - Tanto las anotaciones @Transactional como las configuraciones de tipo AOP se soportan. - Se creará una sola instancia de SqlSession para toda la transacción. - Se hará commit o rollback de esta sesión cuando la transacción finalice. -

-

- MyBatis-Spring se encargará de gestionar las transacciones de forma transparente una vez se hayan configurado. No es necesario - incluir código adicional en tus clases. -

- - -

- Para habilitar las transacciones Spring, simplemente crea un DataSourceTransactionManager en tu fichero de configuración: -

- - -]]> - - - -

- El DataSource especificado puede ser cualquier DataSource JDBC que usarías normalmente con Spring. - Esto incluye connection pools y DataSources obtenidos mediante JNDI. -

-

- Fijate que el DataSource especificado en el transaction manager debe ser el mismo que el que se use para - crear el SqlSessionFactoryBean o la gestión de transacciones no funcionará. -

-
- - -

- Si estás usando un contenedor JEE y quiere que spring participe en las transacciones gestionadas por contenedor (CMT), entonces debes - configurar un JtaTransactionManager en Spring o alguna de sus clases específicas de cada contenedor. - Lo más sencillo es utilizar el namespace tx de Spring or the JtaTransactionManagerFactoryBean: -

- ]]> - - - -

- Con esta configuración, MyBatis se comportará como cualquier otro recurso configurado con CMT. - Spring utilizará cualquier transacción CMT existente y asociará la SqlSession a ella. - Si no no hay ninguna transacción previa pero se necesita una en base a la configuración de la transacción, Spring creará - una transacción gestionada por contenedor nueva. -

-

- Fijate que si quieres usar transacciones CMT pero no quieres utilizar la gestión de transacciones de Spring - no debes configurar ningun transaction manager en Spring y debes - configurar el SqlSessionFactoryBean para que use la clase ManagedTransactionFactory de MyBatis de la siguiente forma: -

- - - - - -]]> - - - -
- - -

- La interfaz SqlSession proporciona métodos especificos para gestionar la transacción. - Pero al usar MyBatis-Spring en tus beans se inyectará una SqlSession o un mapper gestionados por Spring. - Esto significa que Spring siempre gestionará tus transacciones. -

-

- No puedes llamar a los métodos SqlSession.commit(), SqlSession.rollback() - o SqlSession.close() en una SqlSession gestionada por Spring. - Si lo intentas obtendrás una excepción UnsupportedOperationException. - Además, estos métodos no se exponen en los mapper interfaces. -

-

- Independientemente de el estado del autocommit de la conexión JDBC cualquier llamada - a un metodo SQL de SqlSession fuera de una transacción Spring será automaticamente commitada. -

-

- Si quieres controlar las transacciones programaticamente consulta el the Spring reference document(Data Access -Programmatic transaction management-). - Este código muetra como controlar una transacción manualmente usando el PlatformTransactionManager. -

- - -

- You can omit to call the commit and rollback method using the TransactionTemplate. -

- - { - userMapper.insertUser(user); - return null; -});]]> - -

- Este código usa un mapper pero también funcionaría con SqlSession. -

-
-
- -
diff --git a/src/site/es/xdoc/using-api.xml b/src/site/es/xdoc/using-api.xml deleted file mode 100644 index f07f473f3c..0000000000 --- a/src/site/es/xdoc/using-api.xml +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - MyBatis-Spring | Using the MyBatis API - Hunter Presnall - Eduardo Macarron - - - -
-

- With MyBatis-Spring, you can continue to directly use the MyBatis API. - Simply create an SqlSessionFactory in Spring using - SqlSessionFactoryBean and use the factory in your code. -

- - -

- Use this option with care because wrong usage may produce runtime errors or - worse, data integrity problems. Be aware of the following caveats with direct API usage: -

-
    -
  • -

    - It will not participate in any Spring transactions. -

    -
  • -
  • -

    - If the SqlSession is using a DataSource - that is also being used by a Spring transaction manager and there is currently - a transaction in progress, this code will throw an exception. -

    -
  • -
  • -

    - MyBatis' DefaultSqlSession is not thread safe. If you - inject it in your beans you will get errors. -

    -
  • -
  • -

    - Mappers created using DefaultSqlSession are not thread safe either. - If you inject them it in your beans you will get errors. -

    -
  • -
  • -

    - You must make sure that your SqlSessions - are always closed in a finally block. -

    -
  • -
-
- -
diff --git a/src/site/ja/markdown/README.md b/src/site/ja/markdown/README.md new file mode 100644 index 0000000000..3280241e0c --- /dev/null +++ b/src/site/ja/markdown/README.md @@ -0,0 +1,18 @@ +# 目次 + +このページはGitHub上でドキュメントの目次を表示するため用意したものです。 + +> **NOTE:** +> +> リンクはmaven-site-pluginでHTMLに変換することを前提に指定されているため、GitHubでのレンダリングではリンク切れになっているものがあります。 + +* [イントロダクション](./index.md) +* [スタートガイド](./getting-started.md) +* [SqlSessionFactoryBean](./factorybean.md) +* [トランザクション](./transactions.md) +* [SqlSessionの利用](./sqlsession.md) +* [Mapperの注入](./mappers.md) +* [Spring Boot](./boot.md) +* [MyBatis APIの利用](./using-api.md) +* [Spring Batch](./batch.md) +* [サンプルコード](./sample.md) diff --git a/src/site/ja/markdown/batch.md b/src/site/ja/markdown/batch.md new file mode 100644 index 0000000000..0c0d55257e --- /dev/null +++ b/src/site/ja/markdown/batch.md @@ -0,0 +1,344 @@ + +# Spring Batch + +MyBatis-Spring 1.1.0 以降では、 Spring Batch を構築するための Bean として `MyBatisPagingItemReader` 、 `MyBatisCursorItemReader` 、 `MyBatisBatchItemWriter` が用意されています。 +また、2.0.0 以降では、Java Configuration をサポートするための Builder クラスとして `MyBatisPagingItemReaderBuilder` 、 `MyBatisCursorItemReaderBuilder` 、 `MyBatisBatchItemWriterBuilder` が用意されています。 + +NOTE +ここで扱うのは [Spring Batch](http://static.springsource.org/spring-batch/) を使ったバッチ処理で、MyBatis の [`SqlSession`](sqlsession.html) を利用したバッチ処理ではありません。 + +## MyBatisPagingItemReader + +この Bean は、MyBatis を利用してデータベースからページ単位でレコードを読み出す `ItemReader` です。 + +結果を取得する際は `setQueryId` プロパティで指定したクエリが実行されます。1ページあたりの件数は setPageSize プロパティで指定することができます。 +`read()` メソッドが呼び出されると、必要に応じて追加のページを取得するクエリが実行されます。 +実行されるクエリでは、Reader によって提供されるページング処理を行う際に必要となるパラメーターを使って期待される結果を返す SQL 文を記述することになります(実際の SQL 文は方言依存です)。 +提供されるパラメーターは次の通りです。 + +* `_page`: 取得対象のページ番号(最初のページは0 +* `_pagesize`: 1ページあたりの件数 +* `_skiprows`: `_page` と `_pagesize` の積 + +これらのパラメーターは、例えば次のように SELECT 文中で指定することができます。 + +```xml + +``` + +設定例: + +```xml + + + + +``` + +```java +@Configuration +public class BatchAppConfig { + @Bean + public MyBatisPagingItemReader reader() { + return new MyBatisPagingItemReaderBuilder() + .sqlSessionFactory(sqlSessionFactory()) + .queryId("com.my.name.space.batch.EmployeeMapper.getEmployee") + .build(); + } +} +``` + +**さらに複雑な例:** + +```xml + +``` +```xml + + + + + + +``` + +```java +@Configuration +public class BatchAppConfig { + @StepScope + @Bean + public MyBatisPagingItemReader dateBasedCriteriaReader( + @Value("#{@datesParameters}") Map datesParameters) throws Exception { + return new MyBatisPagingItemReaderBuilder() + .sqlSessionFactory(batchReadingSessionFactory()) + .queryId("com.my.name.space.batch.ExampleMapper.queryUserInteractionsOnSpecificTimeSlot") + .parameterValues(datesParameters) + .pageSize(200) + .build(); + } + + @StepScope + @Bean + public Map datesParameters( + @Value("#{jobExecutionContext['EXTRACTION_START_DATE']}") LocalDate yesterday, + @Value("#{jobExecutionContext['TODAY_DATE']}") LocalDate today, + @Value("#{jobExecutionContext['FIRST_DAY_OF_THE_MONTH_DATE']}") LocalDate firstDayOfTheMonth, + @Value("#{jobExecutionContext['FIRST_DAY_OF_THE_PREVIOUS_MONTH_DATE']}") LocalDate firstDayOfThePreviousMonth) { + Map map = new HashMap<>(); + map.put("yesterday", yesterday); + map.put("today", today); + map.put("first_day_of_the_month", firstDayOfTheMonth); + map.put("first_day_of_the_previous_month", firstDayOfThePreviousMonth); + return map; + } +} +``` + +The previous example makes use of a few different things: + +* `sqlSessionFactory`: あなた自身の sessionFactory を reader に指定することができます。複数のデータベースから読み取る場合は有用かも知れません。 +* `queryId`: レコード取得時に実行されるクエリの ID を指定します。異なるネームスペースに属するクエリを指定する場合はネームスペースの指定を忘れないようにしてください。 +* `parameterValues`: クエリ実行時に使用する追加のパラメーターを Map 形式で渡すことができます。上の例では Spring が `jobExecutionContext` から SpEL 式を使って取得した値をもとに構築した `Map` を指定しています。 + MyBatis の Mapper ファイルでは `Map` のキーをパラメーター名として指定します(例: *yesterday* を指定する場合は `#{yesterday,jdbcType=TIMESTAMP}` のように指定します)。 + `jobExecutionContext` と Spring EL 式を利用するため、`Map` および `Reader` はどちらも `step` スコープ内で構築されているという点に注意してください。 + また、MyBatis の `TypeHandler` が正しく設定されていれば、この例のように JodaTime のようなカスタムのインスタンスを引数として渡すこともできます。 +* `pageSize`: バッチ処理のチャンクサイズを指定します。 + +## MyBatisCursorItemReader + +This bean is an `ItemReader` that reads records from a database using a cursor. + +NOTE +To use this bean you need at least MyBatis 3.4.0 or a newer version. + +It executes the query specified as the `setQueryId` property to retrieve requested data by using the method `selectCursor()`. +Each time a `read()` method is called it will return the next element of the cursor until no more elements are left. + +The reader will use a separate connection so the select statement does no participate in any transactions created as part of the step processing. + +When using the cursor you can just execute a regular query: + +```xml + +``` + +Follows below a sample configuration snippet: + +```xml + + + + +``` + +```java +@Configuration +public class BatchAppConfig { + @Bean + public MyBatisCursorItemReader reader() { + return new MyBatisCursorItemReaderBuilder() + .sqlSessionFactory(sqlSessionFactory()) + .queryId("com.my.name.space.batch.EmployeeMapper.getEmployee") + .build(); + } +} +``` + +## MyBatisBatchItemWriter + +`SqlSessionTemplate` のバッチ機能を使って渡された一連のアイテムを処理する `ItemWriter` です。 `SqlSessionFactory` は `ExecutorType.BATCH` を使って設定する必要があります。 + +`write()` の呼び出し時に実行するステートメントの ID を指定しておく必要があります。 `write()` はトランザクション内で呼び出されることを前提としています。 + +設定例: + +```xml + + + + +``` + +```java +@Configuration +public class BatchAppConfig { + @Bean + public MyBatisBatchItemWriter writer() { + return new MyBatisBatchItemWriterBuilder() + .sqlSessionFactory(sqlSessionFactory()) + .statementId("com.my.name.space.batch.EmployeeMapper.updateEmployee") + .build(); + } +} +``` + +**`ItemReader`を使用して読み込んだアイテムを任意のパラメータオブジェクトへ変換する** + +デフォルトの動作では、`MyBatisBatchItemWriter` は `ItemReader` を使用して読みこんだアイテム (または `ItemProcessor` によって変換したアイテム)を、そのままMyBatis(`SqlSession` の `update` メソッド)のパラメーターオブジェクトとして渡します。 +もしMyBatisへ渡すパラメーターオブジェクトをカスタマイズしたい場合は、`itemToParameterConverter` オプションを利用することで実現するすることができます。 +たとえば、`itemToParameterConverter` オプションを使用すると、 アイテムオブジェクト以外のオブジェクトをMyBatisへ渡すことができます。 +以下にサンプルを示します。 + +まず、任意のパラメータオブジェクトに変換するためのコンバータクラス(またはファクトリメソッド)を作成します。以下のサンプルではファクトリメソッドを使用します。 + +```java +public class ItemToParameterMapConverters { + public static Converter> createItemToParameterMapConverter(String operationBy, LocalDateTime operationAt) { + return item -> { + Map parameter = new HashMap<>(); + parameter.put("item", item); + parameter.put("operationBy", operationBy); + parameter.put("operationAt", operationAt); + return parameter; + }; + } +} +``` + +つぎに, SQLマッピングを書きます。 + +```xml + +``` + +さいごに, `MyBatisBatchItemWriter` の設定を行います。 + +```java +@Configuration +public class BatchAppConfig { + @Bean + public MyBatisBatchItemWriter writer() throws Exception { + return new MyBatisBatchItemWriterBuilder() + .sqlSessionFactory(sqlSessionFactory()) + .statementId("org.mybatis.spring.sample.mapper.PersonMapper.createPerson") + .itemToParameterConverter(createItemToParameterMapConverter("batch_java_config_user", LocalDateTime.now())) + .build(); + } +} +``` + +```xml + + + + + + + + + + +``` + +**Composite Writer を使って複数のテーブルに書き込む(注意事項あり)** + +このテクニックを使うには MyBatis 3.2 以降が必要です。それ以前のバージョンには [問題](http://code.google.com/p/mybatis/issues/detail?id=741) があるため、Writer が期待通りに動作しません。 + +まず、*Interaction* と1対1の関係にある *InteractionMetadata* と、これらとは独立した *VisitorInteraction* および *CustomerInteraction* を保持する Item クラスを用意します。 + +```java +public class InteractionRecordToWriteInMultipleTables { + private final VisitorInteraction visitorInteraction; + private final CustomerInteraction customerInteraction; + private final Interaction interaction; + // ... +} +``` +```java +public class Interaction { + private final InteractionMetadata interactionMetadata; +} +``` + +`CompositeItemWriter` の設定では、それぞれのオブジェクトの writer を順番に呼び出すように設定します。 +この例では *Interaction* をアップデートするためのキーを取得するため、*InteractionMetadata* を先に書き込む必要があります。 + +```xml + + + + + + + + + + + + +``` + +```java +@Configuration +public class BatchAppConfig { + @Bean + public CompositeItemWriter interactionsItemWriter() { + CompositeItemWriter compositeItemWriter = new CompositeItemWriter(); + List> writers = new ArrayList<>(4); + writers.add(visitorInteractionsWriter()); + writers.add(customerInteractionsWriter()); + writers.add(interactionMetadataWriter()); + writers.add(interactionWriter()); + compositeItemWriter.setDelegates(writers); + return compositeItemWriter; + } +} +``` + +それぞれの writer を必要に応じて設定します。例えば *Interaction* と *InteractionMetadata* の設定は次のようになります。 + +```xml + +``` +```xml + +``` + +reader の場合と同様、 `statementId` はネームスペースを含むステートメント ID です。 + +Mapper ファイルにステートメントを定義します。 + +```xml + + + +``` +```xml + + + +``` + +はじめに `insertInteractionMetadata` が呼ばれ、その際に取得した主キーを使って親となる `Interaction` を `insertInteraction` を使って書き込むことができます。 + +***JDBC ドライバによって動作が異なるので注意が必要です。例えば MySQL の JDBC ドライバは作成された全ての行の ID を返しますが、H2 バージョン 1.3.168 ではバッチモードでも最後に作成された行の ID のみが返されます。*** diff --git a/src/site/ja/markdown/boot.md b/src/site/ja/markdown/boot.md new file mode 100644 index 0000000000..0243b87200 --- /dev/null +++ b/src/site/ja/markdown/boot.md @@ -0,0 +1,4 @@ + +# Using Spring Boot + +詳細は [MyBatis Spring-boot-starter](http://www.mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure) のドキュメントを参照してください。 diff --git a/src/site/ja/markdown/factorybean.md b/src/site/ja/markdown/factorybean.md new file mode 100644 index 0000000000..f1fef7443c --- /dev/null +++ b/src/site/ja/markdown/factorybean.md @@ -0,0 +1,99 @@ + +# SqlSessionFactoryBean + +基となる MyBatis では、`SqlSessionFactory` をビルドする際 `SqlSessionFactoryBuilder` を使いましたが、MyBatis-Spring では、`SqlSessionFactoryBean` を使います。 + +## 設定 + +Spring の XML 設定ファイルに次の Bean を定義することで Factory Bean を生成することができます。 + +```xml + + + +``` + +`SqlSessionFactoryBean` は Spring の `FactoryBean` インターフェイス([the Spring documentation(Core Technologies -Customizing instantiation logic with a FactoryBean-](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-extension-factorybean) を参照してください)を実装しています。 +これはつまり、最終的に Spring が生成するのは `SqlSessionFactoryBean` ではなく、Factory の `getObject()` メソッドによって返されるオブジェクトであるということです。 +上記の設定では、Spring は `SqlSessionFactory` を生成し、`sqlSessionFactory` という名前の Bean として登録します。 +これに相当する Java のコードは下記のようになるでしょう。 + +```java +@Configuration +public class MyBatisConfig { + @Bean + public SqlSessionFactory sqlSessionFactory() { + SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); + factoryBean.setDataSource(dataSource()); + return factoryBean.getObject(); + } +} +``` + +通常 MyBatis-Spring を使う場合、`SqlSessionFactoryBean` や対応する `SqlSessionFactory` を直接利用する必要はありません。 +`SqlSessionFactory` は `MapperFactoryBean` や `SqlSessionDaoSupport` を継承した他の DAO にインジェクト(注入)されます。 + +## プロパティ + +`SqlSessionFactory` で必須のプロパティは JDBC の `DataSource` のみです。 どのような `DataSource` でも構いません。Spring でデータベース接続を定義する通常の手順で定義してください。 + +`configLocation` は、MyBatis の XML 設定ファイルの場所を指定する際に使用します。これは、例えば基になる MyBatis の設定の一部を変更したい場合などに必要となります。 +よくあるのは `>settings>` や `` などの設定です。 + +ここで指定する設定ファイルは、完全な MyBatis 設定ファイルである必要はありません。 環境、データソース、MyBatis のトランザクションマネージャーに関する設定は**無視されます**。 +`SqlSessionFactoryBean` は、独自にカスタマイズした MyBatis `Environment` を生成し、必要に応じてこれらの値を設定するようになっています。 + +設定ファイルの指定が必要とされるもう一つの例は、MyBatis の Mapper XML ファイルが Mapper クラスとは別のクラスパスに存在する場合です。 +このような構成にする場合、次のどちらかの方法で設定することができます。最初の方法は、MyBatis の設定ファイルの `` で各 XML ファイルのクラスパスを指定する方法です。 +そしてもう一つは、Factory Bean の `mapperLocations` を使った方法です。 + +`mapperLocations` プロパティは Resource Location のリストを取り、ここで MyBatis の XML Mapper ファイルの場所を指定することができます。 +Ant スタイルのパターン文字列を使って特定のディレクトリ内の全ファイルを指定したり、内包するディレクトリを再帰的に検索対象にすることもできます。次の例を見てください。 + +```xml + + + + +``` + +このように指定すると、クラスパス内の `sample.config.mappers` パッケージと、そのサブパッケージに含まれる全ての MyBatis Mapper XML ファイルがロードされます。 + +Container-Managed トランザクションを利用する環境では、`transactionFactoryClass` プロパティが必須となります。「トランザクション」章の該当する節を参照してください。 + +複数のデータベースを使用する場合は、`databaseIdProvider` プロパティを設定する必要があります。 + +```xml + + + + sqlserver + db2 + oracle + mysql + + + +``` +```xml + + + + + +``` + +NOTE +1.3.0より、`configuration` プロパティが追加されました。このプロパティには、MyBatisのXML設定ファイルを使わずに`Configuration`インスタンスを直接指定することができます。 +次の例を見てください。 + +```xml + + + + + + + + +``` diff --git a/src/site/ja/markdown/getting-started.md b/src/site/ja/markdown/getting-started.md new file mode 100644 index 0000000000..d1ed42e4c1 --- /dev/null +++ b/src/site/ja/markdown/getting-started.md @@ -0,0 +1,100 @@ + +# スタートガイド + +この章では、MyBatis-Spring のインストール・設定手順と、トランザクション処理を含むシンプルなアプリケーションの構築する方法について説明します。 + +## インストール + +MyBatis-Spring を使うためには、 `mybatis-spring-${project.version}.jar` と依存するライブラリをクラスパスに追加するだけで OK です。 + +Maven をお使いの場合は、 pom.xml に次の dependency を追加してください。 + +```xml + + org.mybatis + mybatis-spring + ${project.version} + +``` + +## クイックセットアップ + +MyBatis と Spring を組み合わせて使う場合、Spring の Application Context 内に少なくとも `SqlSessionFactory` と一つ以上の Mapper インターフェイスを定義する必要があります。 + +MyBatis-Spring では `SqlSessionFactory` の生成に `SqlSessionFactoryBean` を使います。この Factory Bean を設定するため、Spring の 設定ファイルに次の Bean を追加してください。 + +```xml + + + +``` + +```java +@Configuration +public class MyBatisConfig { + @Bean + public SqlSessionFactory sqlSessionFactory() throws Exception { + SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); + factoryBean.setDataSource(dataSource()); + return factoryBean.getObject(); + } +} +``` + +`SqlSessionFactory` が `DataSource` を必要としている点に注意してください。どのような `DataSource` でも構いません。通常の手順で設定してください。 + +Mapper インターフェイスが次のように定義されている場合... + +```java +public interface UserMapper { + @Select("SELECT * FROM users WHERE id = #{userId}") + User getUser(@Param("userId") String userId); +} +``` + +`MapperFactoryBean` を使ってこのインターフェイスを Spring に登録する場合、以下のように設定します。 + +```xml + + + + +``` + +ここで指定した Mapper は、実装クラスではなく **インターフェイス** である必要がありますので注意してください。 +この例では、アノテーションを使って SQL を指定していますが、Mapper XML ファイルを使うこともできます。 + +上記のように設定しておけば、あとは他の Spring Bean と同様にビジネス/サービス層のオブジェクトにインジェクト(注入)することができます。 +`MapperFactoryBean` は `SqlSession` の生成とクローズを行います。 +もし Spring のトランザクション内で実行された場合は、トランザクション終了時にセッションがコミットあるいはロールバックされます。 +最後にもう一点、全ての例外は Spring の `DataAccessException` に変換されます。 + +Java Configurationを使用する場合: + +```java +@Configuration +public class MyBatisConfig { + @Bean + public UserMapper userMapper() throws Exception { + SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory()); + return sqlSessionTemplate.getMapper(UserMapper.class); + } +} +``` + +MyBatis のデータメソッドは、一行だけで実行可能となります。 + +```java +public class FooServiceImpl implements FooService { + + private final UserMapper userMapper; + + public FooServiceImpl(UserMapper userMapper) { + this.userMapper = userMapper; + } + + public User doSomeBusinessStuff(String userId) { + return this.userMapper.getUser(userId); + } +} +``` diff --git a/src/site/ja/markdown/index.md b/src/site/ja/markdown/index.md new file mode 100644 index 0000000000..0c6adb2296 --- /dev/null +++ b/src/site/ja/markdown/index.md @@ -0,0 +1,52 @@ + +# イントロダクション + +## MyBatis-Spring とは? + +MyBatis-Spring によって MyBatis と Spring をシームレスに連携させることができます。このライブラリを使えば、MyBatis のステートメントを Spring のトランザクション内で実行することもできますし、Mapper や `SqlSession` の生成、他の Bean への注入、MyBatis の例外から Spring の `DataAccessException` への変換、さらには MyBatis や Spring, MyBatis-Spring に依存しないコードでアプリケーションを構築することも可能になります。 + +## 動機 + +Spring バージョン 2 は iBATIS バージョン 2 しかサポートしていません。Spring 3 の開発時に MyBatis 3 への対応が検討されました(こちらの [チケット](https://jira.springsource.org/browse/SPR-5991) 参照)が、Spring 3 が MyBatis 3 よりも前に正式リリースを迎えたため、残念ながら実装は見送られました。Spring 開発陣としては、未リリースの MyBatis 3 に合わせたコードをリリースしたくなかったという事情があり、Spring 側での正式対応は保留となっていました。MyBatis コミュニティの中で Spring 対応への要望が強かったため、有志によって Spring との連携を行う MyBatis のサブプロジェクトが立ち上げられました。 + +## 動作条件 + +MyBatis-Spring を利用するためには、MyBatis と Spring の用語について理解しておくことが重要です。このドキュメントには MyBatis や Spring についての説明や基本設定といった情報は含まれていません。 + +MyBatis-Spring は以下のバージョンを必要とします。 + +| MyBatis-Spring | MyBatis | Spring Framework | Spring Batch | Java | +| --- | --- | --- | --- | --- | +| **2.0** | 3.5+ | 5.0+ | 4.0+ | Java 8+ | +| **1.3** | 3.4+ | 3.2.2+ | 2.1+ | Java 6+ | + +## 謝辞 + +このプロジェクトの実現にご協力頂いた次の方々に感謝します(アルファベット順): +Eduardo Macarron, Hunter Presnall, Putthiphong Boonphong(コーディング、テスト、ドキュメント作成); +Andrius Juozapaitis, Giovanni Cuccu, Mike Lanyon, Raj Nagappan, Tomas Pinos(コントリビューション); +Simone Tripodi(メンバーを集め、MyBatis のサブプロジェクトとしてまとめてくれました) +このプロジェクトは彼らの協力なしには実現できなかったでしょう。 + +## このドキュメントの改善にご協力ください... + +このドキュメントの中で誤りや特定の機能に関する記述が抜けていることに気づいたら、詳しく調べてドキュメントを更新して頂けると助かります。 + +このマニュアルのソースは markdown 形式で、[プロジェクトの Git リポジトリ](https://github.com/mybatis/spring/tree/master/src/site) で配布されています。 +リポジトリをフォーク、それらを更新します、とプルリクエストを送信します。 + +このドキュメントを必要としている人、つまりあなたこそが最高の著者なのです! + +## Translations + +MyBatis-Spring は以下の言語の翻訳を用意しています。 + + + +母国語でMyBatis Springのリファレンスを読んでみませんか? ぜひドキュメントを母国語へ翻訳するためのIssue(パッチ)を作成してください! diff --git a/src/site/ja/markdown/mappers.md b/src/site/ja/markdown/mappers.md new file mode 100644 index 0000000000..03dcb250a1 --- /dev/null +++ b/src/site/ja/markdown/mappers.md @@ -0,0 +1,188 @@ + +# Mapper の注入 + +MyBatis-Spring がスレッドセーフな Mapper を生成してくれるので、`SqlSessionDaoSupport` や `SqlSessionTemplate` を使って手動で DAO オブジェクトを生成するコードは不要となります。 +生成された Mapper は他の Bean に注入することができます。 + +```xml + + + +``` + +アプリケーション側の処理では、注入された Mapper のメソッドを呼び出すだけです。 + +```java +public class FooServiceImpl implements FooService { + + private final UserMapper userMapper; + + public FooServiceImpl(UserMapper userMapper) { + this.userMapper = userMapper; + } + + public User doSomeBusinessStuff(String userId) { + return this.userMapper.getUser(userId); + } +} +``` + +このコードには `SqlSession` や MyBatis への参照が含まれていない点に注目してください。また、セッションの生成やオープン、クローズも MyBatis-Spring が処理してくれるため不要となります。 + + +## Mapper の登録 + +Mapper を Bean として登録する方法は、Spring の設定を XML ファイルを使って行う場合と Spring 3.0 以降で導入された Java Config (= `@Configuration`) を使う場合で異なります。 + +### XML で設定する場合 + +XML ファイルを使って Spring を設定する場合、次のように `MapperFactoryBean` のエントリーを追加することで Mapper を Spring Bean として登録することができます。 + +```xml + + + + +``` + +ここで指定した UserMapper のインターフェイスと同じクラスパスに MyBatis の XML Mapper ファイルが配置されている場合は自動的にロードされます。 +XML Mapper が異なるクラスパスに配置されている場合を除けば、MyBatis の設定ファイルでこの Mapper を指定する必要はありません。 +詳しくは `SqlSessionFactoryBean` の [`configLocation`](factorybean.html) プロパティの説明を参照してください。 + +`MapperFactoryBean` を登録する際は `SqlSessionFactory` あるいは `SqlSessionTemplate` のどちらかを指定する必要があります。 +指定対象のプロパティは、それぞれ `sqlSessionFactory` と `sqlSessionTemplate` です。 +両方が指定された場合、 `SqlSessionFactory` の指定は無視され、`SqlSessionTemplate` の登録時に指定した Session Factory が使われます。 + +### Java Config で設定する場合 + +```java +@Configuration +public class MyBatisConfig { + @Bean + public MapperFactoryBean userMapper() throws Exception { + MapperFactoryBean factoryBean = new MapperFactoryBean<>(UserMapper.class); + factoryBean.setSqlSessionFactory(sqlSessionFactory()); + return factoryBean; + } +} +``` + + +## Mapper の自動検出 + +上で説明した方法では Mapper を個別に指定していましたが、MyBatis-Spring では特定のクラスパスに含まれる Mapper を自動検出させることもできます。 + +これには3通りの方法があります。 + +* `` 要素を使う。 +* `@MapperScan` アノテーションを使う。 +* Spring の XML 設定ファイルに `MapperScannerConfigurer` のエントリーを追加する。 + +`` または `@MapperScan` を使う場合は MyBatis-Spring 1.2.0 以降が必要です。また `@MapperScan` を使う場合は Spring 3.1 以降が必要となります。 + +2.0.2以降では、Mapperの自動検出機能は、Mapper Beanの遅延初期化の有効/無効を制御するオプション(`lazy-initialization`)をサポートします。 +このオプションを追加する動機は、Spring Boot 2.2でサポートされた遅延初期化を制御する機能をサポートすることです。このオプションのデフォルトは`false`です(遅延初期化を使用しません)。 +開発者がMapper Beanを遅延初期化したい場合は、明示的にこのオプションを`true`に設定する必要があります。 + +重要 +遅延初期化機能を使用する場合は、開発者は以下の制限を理解しておく必要があります。以下の条件のいずれかに一致する場合、通常あなたのアプリケーションで遅延初期化機能を使用することはできません。 + +* ``(`@One`) and ``(`@Many`)を利用して、**他のMapperの**ステートメントを参照している場合 +* ``を利用して、**他のMapperの**フラグメントをインクルードしている場合 +* ``(`@CacheNamespaceRef`)を利用して、**他のMapperの**キャッシュを参照している場合 +* `]]> - -

設定例:

- - - - -
]]> - - reader() { - return new MyBatisPagingItemReaderBuilder() - .sqlSessionFactory(sqlSessionFactory()) - .queryId("com.my.name.space.batch.EmployeeMapper.getEmployee") - .build(); -}]]> - -

さらに複雑な例:

- - - - - - - - -]]> - - dateBasedCriteriaReader( - @Value("#{@datesParameters}") Map datesParameters) throws Exception { - return new MyBatisPagingItemReaderBuilder() - .sqlSessionFactory(batchReadingSessionFactory()) - .queryId("com.my.name.space.batch.ExampleMapper.queryUserInteractionsOnSpecificTimeSlot") - .parameterValues(datesParameters) - .pageSize(200) - .build(); -} - -@StepScope -@Bean -public Map datesParameters( - @Value("#{jobExecutionContext['EXTRACTION_START_DATE']}") LocalDate yesterday, - @Value("#{jobExecutionContext['TODAY_DATE']}") LocalDate today, - @Value("#{jobExecutionContext['FIRST_DAY_OF_THE_MONTH_DATE']}") LocalDate firstDayOfTheMonth, - @Value("#{jobExecutionContext['FIRST_DAY_OF_THE_PREVIOUS_MONTH_DATE']}") LocalDate firstDayOfThePreviousMonth) { - Map map = new HashMap<>(); - map.put("yesterday", yesterday); - map.put("today", today); - map.put("first_day_of_the_month", firstDayOfTheMonth); - map.put("first_day_of_the_previous_month", firstDayOfThePreviousMonth); - return map; -}]]> - -

- The previous example makes use of a few different things: -

- -
    -
  • sqlSessionFactory: あなた自身の sessionFactory を reader に指定することができます。複数のデータベースから読み取る場合は有用かも知れません。
  • -
  • queryId: レコード取得時に実行されるクエリの ID を指定します。異なるネームスペースに属するクエリを指定する場合はネームスペースの指定を忘れないようにしてください。
  • -
  • parameterValues: クエリ実行時に使用する追加のパラメーターを Map 形式で渡すことができます。上の例では Spring がjobExecutionContext から SpEL 式を使って取得した値をもとに構築した Map を指定しています。 - MyBatis の Mapper ファイルでは Map のキーをパラメーター名として指定します(例: yesterday を指定する場合は #{yesterday,jdbcType=TIMESTAMP} のように指定します)。 - jobExecutionContext と Spring EL 式を利用するため、Map および reader はどちらも step スコープ内で構築されているという点に注意してください。 - また、MyBatis の Type Handler が正しく設定されていれば、この例のように JodaTime のようなカスタムのインスタンスを引数として渡すこともできます。
  • -
  • pageSize: バッチ処理のチャンクサイズを指定します。
  • -
- - - - -

- This bean is an ItemReader that reads records from a database using a cursor. -

- -

- NOTE To use this bean you need at least MyBatis 3.4.0 or a newer version. -

- -

- It executes the query specified as the setQueryId property to retrieve requested data - by using the method selectCursor(). - Each time a read() method is called it will return the next element of the cursor until no more - elements are left. -

- -

- The reader will use a separate connection so the select statement does no participate in any transactions created - as part of the step processing. -

- -

When using the cursor you can just execute a regular query:

- - SELECT id, name, job FROM employees ORDER BY id ASC -]]> - -

Follows below a sample configuration snippet:

- - - - -
]]> - - reader() { - return new MyBatisCursorItemReaderBuilder() - .sqlSessionFactory(sqlSessionFactory()) - .queryId("com.my.name.space.batch.EmployeeMapper.getEmployee") - .build(); -}]]> - - - - - -

- SqlSessionTemplate のバッチ機能を使って渡された一連のアイテムを処理する ItemWriter です。 - SqlSessionFactoryExecutorType.BATCH を使って設定する必要があります。 -

- -

- write() の呼び出し時に実行するステートメントの ID を指定しておく必要があります。 - write() はトランザクション内で呼び出されることを前提としています。 -

- -

設定例:

- - - - -
]]> - - writer() { - return new MyBatisBatchItemWriterBuilder() - .sqlSessionFactory(sqlSessionFactory()) - .statementId("com.my.name.space.batch.EmployeeMapper.updateEmployee") - .build(); -}]]> - - -

ItemReaderを使用して読み込んだアイテムを任意のパラメータオブジェクトへ変換する

- -

- デフォルトの動作では、MyBatisBatchItemWriterItemReader を使用して読みこんだアイテム - (または ItemProcessor によって変換したアイテム)を、 - そのままMyBatis(SqlSessionupdate メソッド)のパラメーターオブジェクトとして渡します。 - もしMyBatisへ渡すパラメーターオブジェクトをカスタマイズしたい場合は、 - itemToParameterConverter オプションを利用することで実現するすることができます。 - たとえば、itemToParameterConverter オプションを使用すると、 アイテムオブジェクト以外のオブジェクトをMyBatisへ渡すことができます。 - 以下にサンプルを示します。 -

- -

- まず、任意のパラメータオブジェクトに変換するためのコンバータクラス(またはファクトリメソッド)を作成します。以下のサンプルではファクトリメソッドを使用します。 -

- - Converter> createItemToParameterMapConverter(String operationBy, LocalDateTime operationAt) { - return item -> { - Map parameter = new HashMap<>(); - parameter.put("item", item); - parameter.put("operationBy", operationBy); - parameter.put("operationAt", operationAt); - return parameter; - }; -}]]> - -

- つぎに, SQLマッピングを書きます。 -

- - - insert into persons (first_name, last_name, operation_by, operation_at) - values(#{item.firstName}, #{item.lastName}, #{operationBy}, #{operationAt}) -]]> - -

- さいごに, MyBatisBatchItemWriterの設定を行います。 -

- - writer() throws Exception { - return new MyBatisBatchItemWriterBuilder() - .sqlSessionFactory(sqlSessionFactory()) - .statementId("org.mybatis.spring.sample.mapper.PersonMapper.createPerson") - .itemToParameterConverter(createItemToParameterMapConverter("batch_java_config_user", LocalDateTime.now())) - .build(); -}]]> - - - - - - - - - - - - -]]> - - -

Composite Writer を使って複数のテーブルに書き込む(注意事項あり)

- -

このテクニックを使うには MyBatis 3.2 以降が必要です。それ以前のバージョンには 問題 があるため、Writer が期待通りに動作しません。 -

- -

まず、Interaction と1対1の関係にある InteractionMetadata と、これらとは独立した VisitorInteraction および CustomerInteraction を保持する Item クラスを用意します。 -

- - - -

CompositeItemWriter の設定では、それぞれのオブジェクトの writer を順番に呼び出すように設定します。 - この例では Interaction をアップデートするためのキーを取得するため、InteractionMetadata を先に書き込む必要があります。 -

- - - - - - - - - - - - -
]]> - - interactionsItemWriter() { - CompositeItemWriter compositeItemWriter = new CompositeItemWriter(); - List> writers = new ArrayList<>(4); - writers.add(visitorInteractionsWriter()); - writers.add(customerInteractionsWriter()); - writers.add(interactionMetadataWriter()); - writers.add(interactionWriter()); - compositeItemWriter.setDelegates(writers); - return compositeItemWriter; -}]]> - -

それぞれの writer を必要に応じて設定します。例えば InteractionInteractionMetadata の設定は次のようになります。 -

- - -]]> - -

reader の場合と同様、 statementId はネームスペースを含むステートメント ID です。

- -

Mapper ファイルにステートメントを定義します。

- - - - - - -]]> - -

はじめに insertInteractionMetadata が呼ばれ、その際に取得した主キーを使って親となる InteractioninsertInteraction を使って書き込むことができます。 -

- -

JDBC ドライバによって動作が異なるので注意が必要です。例えば MySQL の JDBC ドライバは作成された全ての行の ID を返しますが、H2 バージョン 1.3.168 ではバッチモードでも最後に作成された行の ID のみが返されます。 -

- - - - diff --git a/src/site/ja/xdoc/boot.xml b/src/site/ja/xdoc/boot.xml deleted file mode 100644 index 102d8d1127..0000000000 --- a/src/site/ja/xdoc/boot.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - MyBatis-Spring | Spring Boot - Eduardo Macarron - - - -
-

- 詳細は MyBatis Spring-boot-starter のドキュメントを参照してください。 -

-
- -
diff --git a/src/site/ja/xdoc/factorybean.xml b/src/site/ja/xdoc/factorybean.xml deleted file mode 100644 index 4f9db4e4a7..0000000000 --- a/src/site/ja/xdoc/factorybean.xml +++ /dev/null @@ -1,152 +0,0 @@ - - - - - - MyBatis-Spring | SqlSessionFactoryBean - Hunter Presnall - Eduardo Macarron - Iwao AVE! - - - -
-

- 基となる MyBatis では、SqlSessionFactory をビルドする際 SqlSessionFactoryBuilder を使いましたが、MyBatis-Spring では、SqlSessionFactoryBean を使います。 -

- - -

- Spring の XML 設定ファイルに次の Bean を定義することで Factory Bean を生成することができます。 -

- - -]]> -

- SqlSessionFactoryBean は Spring の FactoryBean インターフェイス(the Spring documentation(Core Technologies -Customizing instantiation logic with a FactoryBean-) を参照してください)を実装しています。 - これはつまり、最終的に Spring が生成するのは SqlSessionFactoryBean ではなく、Factory の getObject() メソッドによって返されるオブジェクトであるということです。
- 上記の設定では、Spring は SqlSessionFactory を生成し、sqlSessionFactory という名前の Bean として登録します。 - これに相当する Java のコードは下記のようになるでしょう。 -

- - - -

- 通常 MyBatis-Spring を使う場合、SqlSessionFactoryBean や対応する SqlSessionFactory を直接利用する必要はありません。 - sqlSessionFactory は MapperFactoryBeanSqlSessionDaoSupport を継承した他の DAO にインジェクト(注入)されます。 -

-
- - - -

- SqlSessionFactory で必須のプロパティは JDBC の DataSource のみです。 - どのような DataSource でも構いません。Spring でデータベース接続を定義する通常の手順で定義してください。 -

- -

- configLocation は、MyBatis の XML 設定ファイルの場所を指定する際に使用します。
- これは、例えば基になる MyBatis の設定の一部を変更したい場合などに必要となります。 - よくあるのは <settings><typeAliases> などの設定です。 -

- -

- ここで指定する設定ファイルは、完全な MyBatis 設定ファイルである必要はありません。 - 環境、データソース、MyBatis のトランザクションマネージャーに関する設定は無視されます。 - SqlSessionFactoryBean は、独自にカスタマイズした MyBatis Environment を生成し、必要に応じてこれらの値を設定するようになっています。 -

- -

- 設定ファイルの指定が必要とされるもう一つの例は、MyBatis の Mapper XML ファイルが Mapper クラスとは別のクラスパスに存在する場合です。 - このような構成にする場合、次のどちらかの方法で設定することができます。 - 最初の方法は、MyBatis の設定ファイルの <mappers> で各 XML ファイルのクラスパスを指定する方法です。 - そしてもう一つは、Factory Bean の mapperLocations を使った方法です。 -

- -

- mapperLocations プロパティは Resource Location のリストを取り、ここで MyBatis の XML Mapper ファイルの場所を指定することができます。 - Ant スタイルのパターン文字列を使って特定のディレクトリ内の全ファイルを指定したり、内包するディレクトリを再帰的に検索対象にすることもできます。次の例を見てください。 -

- - - - -]]> - -

- このように指定すると、クラスパス内の sample.config.mappers パッケージと、そのサブパッケージに含まれる全ての MyBatis Mapper XML ファイルがロードされます。 -

- -

- Container-Managed トランザクションを利用する環境では、transactionFactoryClass プロパティが必須となります。 - 「トランザクション」章の該当する節を参照してください。 -

- -

- 複数のデータベースを使用する場合は、databaseIdProviderプロパティを設定する必要があります。 -

- - - - - sqlserver - db2 - oracle - mysql - - - - - - - - -]]> - -

- NOTE - 1.3.0より、configurationプロパティが追加されました。 - このプロパティには、MyBatisのXML設定ファイルを使わずにConfigurationインスタンスを直接指定することができます。 - 次の例を見てください。 -

- - - - - - - - -]]> - -
-
- -
diff --git a/src/site/ja/xdoc/getting-started.xml.vm b/src/site/ja/xdoc/getting-started.xml.vm deleted file mode 100644 index d2e5a91c8c..0000000000 --- a/src/site/ja/xdoc/getting-started.xml.vm +++ /dev/null @@ -1,140 +0,0 @@ - - - - - - MyBatis-Spring | スタートガイド - Hunter Presnall - Eduardo Macarron - Iwao AVE! - - - -
-

- この章では、MyBatis-Spring のインストール・設定手順と、トランザクション処理を含むシンプルなアプリケーションの構築する方法について説明します。 -

- - -

- MyBatis-Spring を使うためには、 - mybatis-spring-${project.version}.jar と依存するライブラリをクラスパスに追加するだけで OK です。 -

-

- Maven をお使いの場合は、 - pom.xml に次の dependency を追加してください。 -

- - org.mybatis - mybatis-spring - ${project.version} -]]> -
- - -

- MyBatis と Spring を組み合わせて使う場合、Spring の Application Context 内に少なくとも - SqlSessionFactory と一つ以上の Mapper インターフェイスを定義する必要があります。 -

- -

- MyBatis-Spring では - SqlSessionFactory の生成に SqlSessionFactoryBean を使います。この Factory Bean を設定するため、Spring の 設定ファイルに次の Bean を追加してください。 -

- - - -]]> - - - -

- SqlSessionFactoryDataSource を必要としている点に注意してください。 - どのような DataSource でも構いません。通常の手順で設定してください。 -

- -

- Mapper インターフェイスが次のように定義されている場合... -

- - -

- MapperFactoryBean を使ってこのインターフェイスを Spring に登録する場合、以下のように設定します。 -

- - - -]]> - -

- ここで指定した Mapper は、実装クラスではなく インターフェイス である必要がありますので注意してください。
- この例では、アノテーションを使って SQL を指定していますが、Mapper XML ファイルを使うこともできます。 -

- -

- 上記のように設定しておけば、あとは他の Spring Bean と同様にビジネス/サービス層のオブジェクトにインジェクト(注入)することができます。 - MapperFactoryBeanSqlSession の生成とクローズを行います。
- もし Spring のトランザクション内で実行された場合は、トランザクション終了時にセッションがコミットあるいはロールバックされます。 - 最後にもう一点、全ての例外は Spring の DataAccessException に変換されます。 -

- -

- Java Configurationを使用する場合: -

- - - -

- MyBatis のデータメソッドは、一行だけで実行可能となります。 -

- -
-
- -
diff --git a/src/site/ja/xdoc/index.xml b/src/site/ja/xdoc/index.xml deleted file mode 100644 index edc7ac52c7..0000000000 --- a/src/site/ja/xdoc/index.xml +++ /dev/null @@ -1,148 +0,0 @@ - - - - - - MyBatis-Spring | イントロダクション - Hunter Presnall - Eduardo Macarron - Iwao AVE! - - - -
- -

- MyBatis-Spring によって MyBatis と Spring をシームレスに連携させることができます。このライブラリを使えば、MyBatis のステートメントを Spring のトランザクション内で実行することもできますし、Mapper や SqlSession の生成、他の Bean への注入、MyBatis の例外から Spring の DataAccessException への変換、さらには MyBatis や Spring, MyBatis-Spring に依存しないコードでアプリケーションを構築することも可能になります。 -

-
- - -

- Spring バージョン 2 は iBATIS バージョン 2 しかサポートしていません。Spring 3 の開発時に MyBatis 3 への対応が検討されました(こちらの チケット 参照)が、Spring 3 が MyBatis 3 よりも前に正式リリースを迎えたため、残念ながら実装は見送られました。Spring 開発陣としては、未リリースの MyBatis 3 に合わせたコードをリリースしたくなかったという事情があり、Spring 側での正式対応は保留となっていました。MyBatis コミュニティの中で Spring 対応への要望が強かったため、有志によって Spring との連携を行う MyBatis のサブプロジェクトが立ち上げられました。 -

-
- - -

- MyBatis-Spring を利用するためには、MyBatis と Spring の用語について理解しておくことが重要です。 - このドキュメントには MyBatis や Spring についての説明や基本設定といった情報は含まれていません。 -

-

- MyBatis-Spring は以下のバージョンを必要とします。 -

- - - - - - - - - - - - - - - - - - - - - - - - - - -
- MyBatis-Spring - - MyBatis - - Spring Framework - - Spring Batch - - Java -
- 2.0 - - 3.5+ - - 5.0+ - - 4.0+ - - Java 8+ -
- 1.3 - - 3.4+ - - 3.2.2+ - - 2.1+ - - Java 6+ -
-
- - -

- このプロジェクトの実現にご協力頂いた次の方々に感謝します(アルファベット順): - Eduardo Macarron, Hunter Presnall, Putthiphong Boonphong(コーディング、テスト、ドキュメント作成); - Andrius Juozapaitis, Giovanni Cuccu, Mike Lanyon, Raj Nagappan, Tomas Pinos(コントリビューション); - Simone Tripodi(メンバーを集め、MyBatis のサブプロジェクトとしてまとめてくれました)
- このプロジェクトは彼らの協力なしには実現できなかったでしょう。 -

-
- - -

- このドキュメントの中で誤りや特定の機能に関する記述が抜けていることに気づいたら、詳しく調べてドキュメントを更新して頂けると助かります。 -

-

- このマニュアルのソースは xdoc 形式で、プロジェクトの Git リポジトリで配布されています。
- リポジトリをフォーク、それらを更新します、とプルリクエストを送信します。 -

-

- このドキュメントを必要としている人、つまりあなたこそが最高の著者なのです! -

-
- - -

MyBatis-Spring は以下の言語の翻訳を用意しています。

- -

母国語でMyBatis Springのリファレンスを読んでみませんか? ぜひドキュメントを母国語へ翻訳するためのIssue(パッチ)を作成してください!

-
-
- - -
diff --git a/src/site/ja/xdoc/mappers.xml b/src/site/ja/xdoc/mappers.xml deleted file mode 100644 index 16884c5181..0000000000 --- a/src/site/ja/xdoc/mappers.xml +++ /dev/null @@ -1,249 +0,0 @@ - - - - - - MyBatis-Spring | Mapper をインジェクト(注入)する - Hunter Presnall - Eduardo Macarron - Iwao AVE! - - - -
-

- MyBatis-Spring がスレッドセーフな Mapper を生成してくれるので、SqlSessionDaoSupportSqlSessionTemplate を使って手動で DAO オブジェクトを生成するコードは不要となります。 - 生成された Mapper は他の Bean に注入することができます。 -

- - - -]]> - -

- アプリケーション側の処理では、注入された Mapper のメソッドを呼び出すだけです。 -

- -

- このコードには SqlSession や MyBatis への参照が含まれていない点に注目してください。 - また、セッションの生成やオープン、クローズも MyBatis-Spring が処理してくれるため不要となります。 -

- - -

- Mapper を Bean として登録する方法は、Spring の設定を XML ファイルを使って行う場合と Spring 3.0 以降で導入された Java Config (= @Configuration) を使う場合で異なります。

- -

XML で設定する場合

- -

- XML ファイルを使って Spring を設定する場合、次のように MapperFactoryBean のエントリーを追加することで Mapper を Spring Bean として登録することができます。 -

- - - -]]> - -

- ここで指定した UserMapper のインターフェイスと同じクラスパスに MyBatis の XML Mapper ファイルが配置されている場合は自動的にロードされます。 - XML Mapper が異なるクラスパスに配置されている場合を除けば、MyBatis の設定ファイルでこの Mapper を指定する必要はありません。 - 詳しくは SqlSessionFactoryBeanconfigLocation プロパティの説明を参照してください。 -

- -

- MapperFactoryBean を登録する際は SqlSessionFactory あるいは SqlSessionTemplate のどちらかを指定する必要があります。 - 指定対象のプロパティは、それぞれ sqlSessionFactorysqlSessionTemplate です。 - 両方が指定された場合、 SqlSessionFactory の指定は無視され、SqlSessionTemplate の登録時に指定した Session Factory が使われます。 -

- -

Java Config で設定する場合

- - userMapper() throws Exception { - MapperFactoryBean factoryBean = new MapperFactoryBean<>(UserMapper.class); - factoryBean.setSqlSessionFactory(sqlSessionFactory()); - return factoryBean; -}]]> - -
- - -

- 上で説明した方法では Mapper を個別に指定していましたが、MyBatis-Spring では特定のクラスパスに含まれる Mapper を自動検出させることもできます。 -

- -

- これには3通りの方法があります。 -

-
    -
  • <mybatis:scan/> 要素を使う。
  • -
  • @MapperScan アノテーションを使う。
  • -
  • Spring の XML 設定ファイルに MapperScannerConfigurer のエントリーを追加する。
  • -
- -

<mybatis:scan/> または @MapperScan を使う場合は MyBatis-Spring 1.2.0 以降が必要です。また @MapperScan を使う場合は Spring 3.1 以降が必要となります。

- -

- 2.0.2以降では、Mapperの自動検出機能は、Mapper Beanの遅延初期化の有効/無効を制御するオプション(lazy-initialization)をサポートします。 - このオプションを追加する動機は、Spring Boot 2.2でサポートされた遅延初期化を制御する機能をサポートすることです。 - このオプションのデフォルトはfalseです(遅延初期化を使用しません)。 - 開発者がMapper Beanを遅延初期化したい場合は、明示的にこのオプションをtrueに設定する必要があります。 -

-

- 重要 遅延初期化機能を使用する場合は、開発者は以下の制限を理解しておく必要があります。 - 以下の条件のいずれかに一致する場合、通常あなたのアプリケーションで遅延初期化機能を使用することはできません。 -

-
    -
  • ]]>(@One) and ]]>(@Many)を利用して、他のMapperのステートメントを参照している場合
  • -
  • ]]>を利用して、他のMapperのフラグメントをインクルードしている場合
  • -
  • ]]>(@CacheNamespaceRef)を利用して、他のMapperのキャッシュを参照している場合
  • -
  • ]]>(@ResultMap)を利用して、他のMapperの結果マッピングを参照している場合
  • -
- -

- NOTE しかしながら、以下のように@DependsOn(Springの機能)を利用して、 - 依存するMapper Beanも同時に初期化すると遅延初期化機能を利用することができるようになります。 -

- - - -

- 2.0.6以降では、開発者はMapper BeanのスコープをMapperの自動検出機能のオプション(default-scope) - とスコープを指定するアノテーション(@Scope@RefreshScope など)を使用して指定することができるようになります。 - このオプションを追加する動機は、Spring Cloudから提供されている refresh スコープをサポートすることです。 - このオプションのデフォルトは空(singletonスコープを指定するのと同等)です。 - default-scope オプションで指定した値は、スキャンしたMapperのBean定義に指定されているスコープが singleton の際に適用され、 - 最終的なMapperのスコープが singleton でない場合はScoped ProxyのBeanを作成します。 -

- -

<mybatis:scan/>

- -

- <mybatis:scan/> は、Spring の <context:component-scan/> が Bean を検索するのと良く似た方法で Mapper を検出します。 -

- -

XML 設定の例:

- - - - - - - -]]> - -

- base-package 属性で Mapper ファイルを含むパッケージを指定します。 - セミコロンまたはカンマ区切りで複数のパッケージを指定することもできます。 - また、指定されたパッケージが内包するパッケージも検索対象となります。 -

- -

- ここでは <mybatis:scan/>SqlSessionFactorySqlSessionTemplate を指定していませんが、この場合は Autowired 可能な MapperFactoryBean が自動的に生成されます。 - ただし、複数の DataSource を利用する場合は Autowired に頼ることができないので、 factory-ref または template-ref 属性を使って適切な Bean を指定する必要があります。 -

- -

- <mybatis:scan/> を使う場合、マーカーインターフェイスまたはアノテーションを指定して Mapper をフィルタリングすることができます。 - 検出対象のアノテーションを指定するには annotation 属性を使います。 - 検出対象の Mapper が実装するインターフェイスを指定する場合は marker-interface 属性を使います。 - 両方の属性が指定された場合、どちらかの条件を満たすインターフェイスが Mapper として登録されます。 - デフォルトではどちらも null となっており、base-package で指定したパッケージに含まれるすべてのインターフェイスが Mapper としてロードされます。 -

- -

- 検出された Mapper は、Spring の自動検出コンポーネントに対するデフォルト命名規則によって Bean 名が決められます(the Spring reference document(Core Technologies -Naming autodetected components-) を参照してください)。 - アノテーションによる指定がない場合はクラス名の先頭を小文字にした文字列が Bean 名となりますが、@Component あるいは JSR-330 の @Named アノテーションを使って Bean 名を明示的に指定することもできます。 - 先に説明した annotation 属性で org.springframework.stereotype.Componentjavax.inject.Named (Java 6 以降を利用している場合のみ)を指定すれば、検出時のマーカーと Bean 名の指定を1つのアノテーションで兼ねることができます。 - 同じ目的で独自に定義したアノテーションを使うこともできますが、このアノテーション自体に @Component か @Named を付加しておく必要があります。 -

- -

- NOTE Spring 標準の <context:component-scan/> を使って Mapper を検出することはできません。 - Mapper はインターフェイスなので、各 Mapper に対する MapperFactoryBean の生成方法が分かっていないと Spring Bean として登録することができないのです。 -

- -

@MapperScan

- -

- Java Config を使って Spring を設定しているのなら、<mybatis:scan/> よりも @MapperScan を使う方が気に入ると思います。 -

- -

@MapperScan アノテーションは次のように使用します。

- - - -

- このアノテーションは前章で説明した <mybatis:scan/> と全く同じ要領で Mapper の検出を行います。 - 引数 markerInterface, annotationClass を使えば検出対象のマーカーインターフェイスとアノテーションを指定することもできますし、sqlSessionFactory, sqlSessionTemplateSqlSessionFactorySqlSessionTemplate を指定することができます。 -

- -

- NOTE 2.0.4以降では、 basePackageClasses もしくは basePackages が指定されていない場合、このアノテーションが定義されているクラスのパッケージを基準にスキャンします。 -

- -

MapperScannerConfigurer

- -

- MapperScannerConfigurerBeanDefinitionRegistryPostProcessor として定義されているので、従来の XML による設定で通常の Bean として登録することができます。 - MapperScannerConfigurer の登録は次のように行います。 -

- - -]]> - -

- 特定の sqlSessionFactory または sqlSessionTemplate を指定する場合は、 Bean を参照ではなく 名前で 指定する必要があるので、ref ではなく value を使います。 -

- ]]> - -

- NOTE MyBatis-Spring 1.0.2 までは有効なプロパティは sqlSessionFactoryBeansqlSessionTemplateBean のみでしたが、 MapperScannerConfigurerPropertyPlaceholderConfigurer よりも先に読み込まれるためエラーの原因となっていました。 - この問題を回避するため、これらのプロパティの使用は非推奨となり、新たに追加された sqlSessionFactoryBeanNamesqlSessionTemplateBeanName を使うことが推奨されています。 -

-
-
- -
diff --git a/src/site/ja/xdoc/sample.xml b/src/site/ja/xdoc/sample.xml deleted file mode 100644 index cd0620f742..0000000000 --- a/src/site/ja/xdoc/sample.xml +++ /dev/null @@ -1,177 +0,0 @@ - - - - - - MyBatis-Spring | Sample Code - Eduardo Macarron - - - -
- -

- NOTE - See JPetstore 6 demo to know about how to use Spring with a full web application server. -

- -

- You can check out sample code from the MyBatis-Spring repo: -

-

- Any of the samples can be run with JUnit 5. -

-

- The sample code shows a typical design where a transactional service gets domain objects from a data access layer. -

-

- FooService.java acts as the service: -

- -

- It is a transactional bean, so when the method is called, the transaction is started - and the transaction is committed when the method ends without throwing an uncaught exception. - Notice that transactional behaviour is configured with the - @Transactional - attribute. This is not required; any other way provided by Spring can be used to demarcate - your transactions. -

-

- This service calls a data access layer built with MyBatis. This layer - consists on a just an interface UserMapper.java - that will be used with a dynamic proxy built by MyBatis at - runtime and injected into the service by Spring. -

- -

- Note that, for the sake of simplicity we used the interface UserMapper.java for the DAO scenario - where a DAO is built with an interface and a implementation though in this case it would have been more - adequate to use an interface called UserDao.java instead. -

-

- We will see different ways to find the mapper interface, register it to Spring and inject it into the service bean: -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Scenarios
Sample testDescription
- SampleMapperTest.java - - Shows you the base configuration based on a MapperFactoryBean - that will dynamically build an implementation for UserMapper -
- SampleScannerTest.java - - Shows how to use the MapperScannerConfigurer so all the mappers in a project are autodiscovered. -
- SampleSqlSessionTest.java - - Shows how to hand code a DAO using a Spring managed SqlSession - and providing your own implementation UserDaoImpl.java. -
- SampleEnableTest - - Shows how to use Spring's @Configuration with the @MapperScann annotation so - mappers are autodiscovered. -
- SampleNamespaceTest - - Shows how to use the custom MyBatis XML namespace. -
- SampleJavaConfigTest.java - - Shows how to use Spring's @Configuration to create MyBatis beans manually. -
- SampleJobJavaConfigTest.java - - Shows how to use ItemReader and ItemWriter on Spring Batch using Java Configuration. -
- SampleJobXmlConfigTest.java - - Shows how to use ItemReader and ItemWriter on Spring Batch using XML Configuration. -
-

- Please take a look at the different applicationContext.xml files to see MyBatis-Spring in action. -

- -
- -
- diff --git a/src/site/ja/xdoc/sqlsession.xml b/src/site/ja/xdoc/sqlsession.xml deleted file mode 100644 index 72be2d5841..0000000000 --- a/src/site/ja/xdoc/sqlsession.xml +++ /dev/null @@ -1,156 +0,0 @@ - - - - - - MyBatis-Spring | Using an SqlSession - Hunter Presnall - Eduardo Macarron - Iwao AVE! - - - -
-

- MyBatis では SqlSessionFactory を使って SqlSession を生成しました。 - そして取得したセッションを使って Mapped Statement を実行し、接続をコミットあるいはロールバックした後、最終的に不要となったセッションをクローズする、というのが一連の流れでした。 - MyBatis-Spring では、SPring のトランザクション設定に基づいて自動的にコミット、ロールバック、クローズされるスレッドセーフな SqlSession が注入されるので、直接 SqlSessionFactory を使う必要はありません。 -

- - -

- SqlSessionTemplate は MyBatis-Spring で最も重要なクラスです。 - このクラスが MyBatis の SqlSession を管理して、SQL メソッドの実行や例外の変換を行なっています。 - このクラスは既存のコードで使用している SqlSession の代わりに使うことを前提に SqlSession インターフェイスを実装しています。 - SqlSessionTemplate はスレッドセーフで、複数の DAO, Mapper 間で共有することができます。 -

- -

- getMapper() から返された Mapper のメソッドも含めて、SQL メソッドを呼び出す場合、確実に現在の Spring トランザクションに付加された SqlSession が使われるようにするのも SqlSessionTemplate の仕事です。 - それ以外にも、セッションのクローズや状況に応じたコミットあるいはロールバックといったライフサイクルの管理、更には MyBatis の例外を Spring の DataAccessException に変換する処理も行います。 -

- -

- SqlSessionTemplate は Spring が管理するトランザクション内で実行され、また Spring によってインジェクトされる複数の Mapper から呼び出すことができるようにスレッドセーフとなっているので、常にこのクラスを MyBatis のデフォルト実装である DefaultSqlSession の代わりに使用するべきです。 - 同一アプリケーション内でこれら2つのクラスを混在させて使用するとデータの不整合などの問題が発生する可能性があります。 -

- -

- SqlSessionTemplate を生成する際は、SqlSessionFactory をコンストラクタ引数として渡します。 -

- - -]]> - - - -

- この Bean は、直接あなたの DAO Bean にインジェクト(注入)することができます。 - 注入対象の Bean には SqlSession プロパティを定義しておく必要があります。 -

- -

- そして、以下のようにして SqlSessionTemplate を注入します。 -

- - -]]> - -

- SqlSessionTemplate には、ExecutorType を引数に取るコンストラクタも定義されています。 - このコンストラクタを使うと、例えばバッチ処理を行う SqlSession を取得することができます。 -

- - - -]]> - - - -

- これで実行されるステートメントは全てバッチ処理の対象となります。 - DAO クラス中では、例えば次のように書くことができます。 -

- users) { - for (User user : users) { - sqlSession.insert("org.mybatis.spring.sample.mapper.UserMapper.insertUser", user); - } -}]]> - -

- デフォルト以外の ExecutorType を使用する場合にのみ SqlSessionFactory の Bean を定義する際に2つの引数を指定する必要があります。 -

- -

- この初期化方式を使用する場合の注意点として、このメソッドが呼び出される時点で異なる ExecutorType で実行されているトランザクションが存在していてはならない、という制限があります。 - そのためには、異なる ExecutorType が指定された SqlSessionTemplate への呼び出しを、それぞれが独立したトランザクション内で実行する(例えば PROPAGATION_REQUIRES_NEW を指定しておく)か、あるいは完全にトランザクションの外で実行するようにしてください。 -

-
- - -

- SqlSessionDaoSupportSqlSession を提供する抽象クラスです。 - getSqlSession() を呼び出すことで、SQL メソッドを実行するための SqlSessionTemplate を取得することができます。 -

- -

- 普通は MapperFactoryBean を使った方がコード量が少なくて済みますが、DAO の中で MyBatis 以外の処理を行うため実装クラスが必要となる場合には便利なクラスです。 -

- -

- SqlSessionDaoSupport を使用する際は、sqlSessionFactory または sqlSessionTemplate をセットする必要があります。 - もし両方のプロパティがセットされた場合、sqlSessionFactory は無視されます。 -

- -

- SqlSessionDaoSupport のサブクラスである UserDaoImpl を Spring Bean として定義する例を挙げておきます。 -

- - -]]> -
-
- -
diff --git a/src/site/ja/xdoc/transactions.xml b/src/site/ja/xdoc/transactions.xml deleted file mode 100644 index 36d6324f4e..0000000000 --- a/src/site/ja/xdoc/transactions.xml +++ /dev/null @@ -1,155 +0,0 @@ - - - - - - MyBatis-Spring | トランザクション - Hunter Presnall - Eduardo Macarron - Iwao AVE! - - - -
-

- これは MyBatis-Spring を使う主な理由の一つでもありますが、MyBatis-Spring を使うと MyBatis の処理を Spring が管理するトランザクションの一部として実行できるようになります。 - MyBatis-Spring は、MyBatis のために新しいトランザクションマネージャーを生成するのではなく、Spring が生成した DataSourceTransactionManager を利用します。 -

-

- Spring のトランザクションマネージャーが定義されていれば、通常の手順で Spring のトランザクションを利用することができます。 - @Transactional アノテーションと AOP 形式での指定、どちらも利用可能です。 - トランザクション内では SqlSession が一つ生成され、トランザクションの生存期間中はこの SqlSession が使用されます。 - このセッションは、トランザクション完了時にコミットあるいはロールバックされます。 -

-

- MyBatis-Spring ではトランザクションは透過的に管理されるので、あなたの DAO クラスにコードを追加する必要はありません。 -

- - -

- Spring の 設定ファイルで DataSourceTransactionManager を生成するだけで、Spring のトランザクション処理が有効となります。 -

- - -]]> - - - -

- ここで指定する DataSource は、通常 Spring で利用される JDBC DataSource であればどのようなデータソースでも構いません。 - 例えば、コネクションプールや JNDI 経由で取得した DataSource などです。 -

-

- ただし、トランザクションマネージャーに対して指定する DataSource は、SqlSessionFactoryBean に対して指定したものと同じでなくてはなりません。もし別のデータソースを指定した場合、トランザクション機能は正しく動作しません。 -

-
- - -

- JEEコンテナを利用していて、Spring の処理を CMT (Container Managed Transaction) の一部として利用したい場合、JtaTransactionManager あるいはそのコンテナ固有のサブクラスを使って Spring を設定する必要があります。 - 最も簡単なのは、Spring のトランザクション名前空間 又は JtaTransactionManagerFactoryBean を使う方法です。 -

- ]]> - - - -

- このように設定しておくと MyBatis は、CMT を使うように設定された他の Spring リソースと同じように動作します。 - Spring は、既存のコンテナ管理されたトランザクションがあれば、そのトランザクションに SqlSession を付加して利用します。 - もしトランザクションを要求する処理が呼び出された時点で開始されたトランザクションがなければ、Spring が新しいコンテナ管理されたトランザクションを開始します。 -

-

- CMT は使いたいが、Spring のトランザクション管理は利用したくないという場合、Spring のトランザクションマネージャーを定義してはいけません。 - またこの場合、MyBatis 側で生成された ManagedTransactionFactory を使うように SqlSessionFactoryBean を設定する必要があります。 -

- - - - - -]]> - - - -
- - -

- MyBatis の SqlSession では、トランザクションをプログラム的に制御するためのメソッドが用意されています。 - しかし、MyBatis-Spring では、あなたの Bean にインジェクト(注入)されるのは Spring が管理する SqlSession あるいは Mapper です。 - つまり、トランザクションを制御するのは常に Spring でなくてはなりません。 -

-

- Spring が管理している SqlSession に対して SqlSession.commit(), SqlSession.rollback(), SqlSession.close() を呼び出すことはできません。 - もしこれらのメソッドを呼び出した場合、UnsupportedOperationException がスローされます。 - あなたの Bean に注入される Mapper クラスでは、これらのメソッドは隠蔽されています。 -

-

- Spring が管理するトランザクションの外側で SqlSession のデータメソッドあるいは Mapper メソッドを呼び出した場合、JDBC 接続に対する auto-commit の設定に関わらず、変更は直ちにコミットされます。 -

-

- もしあなたがトランザクションをプログラム的に制御したいのであれば、the Spring reference document(Data Access -Programmatic transaction management-) を参照してください。 - 以下のコードは、PlatformTransactionManager を使ってトランザクションを手動で制御する例です。 -

- - -

- TransactionTemplate を使用して commitrollback メソッドを省略することもできます。 -

- - { - userMapper.insertUser(user); - return null; -});]]> - -

- ここでは Mapper を使っていますが、SqlSession を使うこともできます。 -

-
-
- -
diff --git a/src/site/ja/xdoc/using-api.xml b/src/site/ja/xdoc/using-api.xml deleted file mode 100644 index e853d45986..0000000000 --- a/src/site/ja/xdoc/using-api.xml +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - MyBatis-Spring | MyBatis API の使用 - Hunter Presnall - Eduardo Macarron - Iwao AVE! - - - -
-

- MyBatis-Spring を使っている場合でも、直接 MyBatis API を呼び出すことができます。 - Spring の設定で SqlSessionFactoryBean を使って SqlSessionFactory を生成すれば、コード内で使用することができます。 -

- - -

- この方法を使う場合は注意が必要です。 - なぜなら、誤った使い方をすると実行時エラーや、最悪の場合データの不整合といった問題を生じる可能性があるからです。 - MyBatis API を直接使用する場合、次のような点に注意してください。 -

-
    -
  • -

    - API の呼び出しは Spring で管理されているトランザクション内では実行されません。 -

    -
  • -
  • -

    - SqlSession が Spring のトランザクションマネージャーが使っているのと同じ DataSource を使っていて、既に進行中のトランザクションが存在している場合、このコードは例外を投げます。 -

    -
  • -
  • -

    - MyBatis の DefaultSqlSession はスレッドセーフではありません。 - もしあなたの Bean に注入した場合、エラーが発生します。 -

    -
  • -
  • -

    - DefaultSqlSession を使って生成した Mapper もスレッドセーフとはなりません。 - もしあなたの Bean に注入した場合、エラーが発生します。 -

    -
  • -
  • -

    - SqlSession は常に finally ブロックでクローズする必要があります。 -

    -
  • -
-
- -
diff --git a/src/site/ko/markdown/README.md b/src/site/ko/markdown/README.md new file mode 100644 index 0000000000..4e31a121bc --- /dev/null +++ b/src/site/ko/markdown/README.md @@ -0,0 +1,18 @@ +# 목차 + +이 페이지는 GitHub에서 인덱스를 렌더링하기위한 것입니다. + +> **NOTE:** +> +> 링크 대상은 maven-site-plugin을 사용하여 html로 변환된다는 가정하에 지정되므로 GitHub의 렌더링에서 끊어진 앵커가 있습니다. + +* [소개](./index.md) +* [시작하기](./getting-started.md) +* [SqlSessionFactoryBean](./factorybean.md) +* [트랜잭션](./transactions.md) +* [SqlSession 사용](./sqlsession.md) +* [매퍼 주입](./mappers.md) +* [Spring Boot](./boot.md) +* [MyBatis API 사용](./using-api.md) +* [Spring Batch](./batch.md) +* [샘플 코드](./sample.md) diff --git a/src/site/ko/markdown/batch.md b/src/site/ko/markdown/batch.md new file mode 100644 index 0000000000..29ec3f6df6 --- /dev/null +++ b/src/site/ko/markdown/batch.md @@ -0,0 +1,353 @@ + +# Spring Batch + +마이바티스 스프링 연동모듈의 1.1.0버전에서는 스프링 배치 애플리케이션을 만들기 위해 두개의 빈을 제공한다. +두개의 빈은 `MyBatisPagingItemReader` 와 `MyBatisCursorItemReader` 와 MyBatisBatchItemWriter이다. + +또한 2.0.0 버전에서는 Java Configuration 을 지원하는 다음의 세 가지 Builder class 를 제공한다. +`MyBatisPagingItemReaderBuilder`, `MyBatisCursorItemReaderBuilder` 그리고 `MyBatisBatchItemWriterBuilder` 이다. + +중요 +이 문서는 [스프링 배치](http://static.springsource.org/spring-batch/) 에 대한 것으로 마이바티스 배치 `SqlSession` 을 다루지는 않는다. +배치 세션에 대해서는 [SqlSession 사용](sqlsession.html) 에서 좀더 다루었다. + +# MyBatisPagingItemReader + +이 빈은 마이바티스로 페이지를 처리하는 형태로 데이터베이스 데이터를 읽어오는 `ItemReader`이다. + +요청된 데이터를 가져오기 위해 `setQueryId` 프로퍼티에 명시된 쿼리를 실행한다. +쿼리는 `setPageSize` 프로퍼티에 명시된 크기만큼 데이터를 가져오도록 실행된다. +`read()` 메서드를 사용하면 필요할 때 현재 위치에서 정해진 수 만큼 더 추가 데이터를 가져온다. +reader는 몇가지의 표준적인 쿼리 파라미터를 제공하고 명명된 쿼리의 SQL은 요청된 크기만큼의 데이터를 만들기 위해 파라미터의 일부 혹은 모두 사용한다. +여기서 사용가능한 파라미터이다. + +* `_page`: 읽을 페이지 수(0부터 시작) +* `_pagesize`: 페이지의 크기, 이를테면 리턴하는 로우 수 +* `_skiprows`: `_page` 와 `_pagesize`의 결과 + +각각의 파라미터는 selet구문에서 다음처럼 매핑될 수 있다. + +```xml + +``` + +다음의 코드는 샘플 설정이다. + +```xml + + + + +``` + +```java +@Configuration +public class BatchAppConfig { + @Bean + public MyBatisPagingItemReader reader() { + return new MyBatisPagingItemReaderBuilder() + .sqlSessionFactory(sqlSessionFactory()) + .queryId("com.my.name.space.batch.EmployeeMapper.getEmployee") + .build(); + } +} +``` + +**좀더 복잡한 예제를 보자.** + +```xml + +``` +```xml + + + + + + +``` + +```java +@Configuration +public class BatchAppConfig { + @StepScope + @Bean + public MyBatisPagingItemReader dateBasedCriteriaReader( + @Value("#{@datesParameters}") Map datesParameters) throws Exception { + return new MyBatisPagingItemReaderBuilder() + .sqlSessionFactory(batchReadingSessionFactory()) + .queryId("com.my.name.space.batch.ExampleMapper.queryUserInteractionsOnSpecificTimeSlot") + .parameterValues(datesParameters) + .pageSize(200) + .build(); + } + + @StepScope + @Bean + public Map datesParameters( + @Value("#{jobExecutionContext['EXTRACTION_START_DATE']}") LocalDate yesterday, + @Value("#{jobExecutionContext['TODAY_DATE']}") LocalDate today, + @Value("#{jobExecutionContext['FIRST_DAY_OF_THE_MONTH_DATE']}") LocalDate firstDayOfTheMonth, + @Value("#{jobExecutionContext['FIRST_DAY_OF_THE_PREVIOUS_MONTH_DATE']}") LocalDate firstDayOfThePreviousMonth) { + Map map = new HashMap<>(); + map.put("yesterday", yesterday); + map.put("today", today); + map.put("first_day_of_the_month", firstDayOfTheMonth); + map.put("first_day_of_the_previous_month", firstDayOfThePreviousMonth); + return map; + } +} +``` + +앞의 예제와는 몇가지 차이점이 있다. + +* `sqlSessionFactory`: reader에 별도로 구현한 sessionFactory를 지정할 수 있다. 이 옵션은 다양한 데이터베이스에서 데이터를 읽을때 유용하다. +* `queryId`: 여러개의 테이블에서 데이터를 읽어야 하고 서로 다른 쿼리를 사용한다면 서로다른 네임스페이스를 가진 매퍼 파일을 사용하는게 좋을수 있다. 쿼리를 알아볼때, 매퍼 파일의 네임스페이스를 잊지 말아야 한다. +* `parameterValues`: 이 맵을 사용해서 추가로 파라미터를 전달할 수 있다. 위 예제는 `jobExecutionContext`에서 값들을 가져오는 SpEL표현식을 사용하는 맵을 사용하고 있다. + 맵의 키는 매퍼파일에서 마이바티스가 사용할 것이다. (예: *yesterday* 는 `#{yesterday,jdbcType=TIMESTAMP}` 로 사용될수 있다.). + 맵과 reader 모두 `jobExecutionContext`에서 SpEL표현식을 사용하기 위해 `step` 스코프를 사용한다. 마이바티스의 타입핸들러가 제대로 설정이 되었다면 JodaTime날짜를 맵을 사용해서 파라미터로 넘길수 있다. +* `pageSize`: 배치가 청크크기가 지정된 형태로 처리가 되면 reader에 이 값을 전달하는게 적절하다. + +## MyBatisCursorItemReader + +이 빈은 cursor 를 사용하여 데이터베이스에서 레코드를 읽는 `ItemReader` 이다. + +중요 +이 빈을 사용하려면 최소한 MyBatis 3.4.0 이나 그 이상이어야 한다. + +`setQueryId` 속성으로 지정된 쿼리를 실행하여 `selectCursor()` 메서드를 사용하여 요청 된 데이터를 검색한다. `read()` 메서드가 호출 될 때마다 요소가 더 이상 남아 있지 않을 때까지 cursor 의 다음 요소를 반환한다. + +reader 는 별도의 connection 을 사용하므로 select 문은 step processing 일부로 생성된 트랜잭션에 속하지 않는다. + +cursor 를 사용할 때 다음과 같이 일반 쿼리를 실행할 수 있다. + +```xml + +``` + +아래는 샘플 설정이다. + +```xml + + + + +``` + +```java +@Configuration +public class BatchAppConfig { + @Bean + public MyBatisCursorItemReader reader() { + return new MyBatisCursorItemReaderBuilder() + .sqlSessionFactory(sqlSessionFactory()) + .queryId("com.my.name.space.batch.EmployeeMapper.getEmployee") + .build(); + } +} +``` + +# MyBatisBatchItemWriter + +모든 아이템을 배치로 구문을 일괄실행하기 위해 `SqlSessionTemplate`에서 배치로 작업을 처리하는 `ItemWriter`이다. `SqlSessionFactory`는 `BATCH` 실행자로 설정할 필요가 있다. + +사용자는 `write()` 메서드가 호출될때 실행될 매핑구문 아이디를 제공해야 한다. `write()` 메서드는 트랜잭션내에서 호출되는 것으로 예상된다. + +다음의 코드는 샘플설정이다. + +```xml + + + + +``` +```java +@Configuration +public class BatchAppConfig { + @Bean + public MyBatisBatchItemWriter writer() { + return new MyBatisBatchItemWriterBuilder() + .sqlSessionFactory(sqlSessionFactory()) + .statementId("com.my.name.space.batch.EmployeeMapper.updateEmployee") + .build(); + } +} +``` + + +**Converting a item that read using ItemReader to an any parameter object:** + +By default behavior, the `MyBatisBatchItemWriter` passes a item that read using `ItemReader` (or convert by `ItemProcessor`) to the MyBatis(`SqlSession#update()`) as the parameter object. +If you want to customize a parameter object that passes to the MyBatis, you can realize to use the `itemToParameterConverter` option. +For example using `itemToParameterConverter` option, you can passes any objects other than the item object to the MyBatis. +Follows below a sample: + +At first, you create a custom converter class (or factory method). The following sample uses a factory method. + +```java +public class ItemToParameterMapConverters { + public static Converter> createItemToParameterMapConverter(String operationBy, LocalDateTime operationAt) { + return item -> { + Map parameter = new HashMap<>(); + parameter.put("item", item); + parameter.put("operationBy", operationBy); + parameter.put("operationAt", operationAt); + return parameter; + }; + } +} +``` + +At next, you write a sql mapping. + +```xml + +``` + +At last, you configure the `MyBatisBatchItemWriter`. + +```java +@Configuration +public class BatchAppConfig { + @Bean + public MyBatisBatchItemWriter writer() throws Exception { + return new MyBatisBatchItemWriterBuilder() + .sqlSessionFactory(sqlSessionFactory()) + .statementId("org.mybatis.spring.sample.mapper.PersonMapper.createPerson") + .itemToParameterConverter(createItemToParameterMapConverter("batch_java_config_user", LocalDateTime.now())) + .build(); + } +} +``` + +```xml + + + + + + + + + + +``` + +**여러개의 테이블에 데이터를 쓰려면 한꺼번에 처리할 수 있도록 만든 writer(몇가지 규칙을 가지고)를 사용하자.** + +이 기능은 마이바티스 3.2이상에서만 사용할 수 있다. 이전의 버전에서는 예상과 다르게 동작하는데 그 내용은 [이슈](http://code.google.com/p/mybatis/issues/detail?id=741)를 참고하면 된다. + +배치가 관계를 가지는 데이터나 여러개의 데이터베이스를 다루는 것처럼 복잡한 데이터를 작성할때 필요하다면 insert구문이 한개에 테이블에만 데이터를 넣을수 있다는 사실만 피하면 가능하기도 하다. +이런 복잡한 데이터를 처리하기 위해 writer가 작성하는 아이템(Item)을 준비해야 한다. 다음의 기술을 사용하면 단순한 관계를 가진 데이터나 관계가 없는 테이블을 처리하는 아이템에서 사용할 수 있다. + +이러한 방법으로 스프링 배치 아이템은 모든 레코드를 *다룰것이다*. +여기에는 1:1 *관계*를 가지는 *InteractionMetadata*, 관계가 없는 두개의 로우는 *VisitorInteraction* 와 *CustomerInteraction*이 있다. +이 각각의 객체는 다음과 같이 볼수 있다. + +```java +public class InteractionRecordToWriteInMultipleTables { + private final VisitorInteraction visitorInteraction; + private final CustomerInteraction customerInteraction; + private final Interaction interaction; + // ... +} +``` +```java +public class Interaction { + private final InteractionMetadata interactionMetadata; +} +``` + +그리고 스프링 설정에는 각각의 레코드를 처리하기위해 특별히 설정된 전용(delegates) writer를 사용하는 `CompositeItemWriter`가 있다. + +```xml + + + + + + + + + + + + +``` +```java +@Bean +@Configuration +public class BatchAppConfig { + public CompositeItemWriter interactionsItemWriter() { + CompositeItemWriter compositeItemWriter = new CompositeItemWriter(); + List> writers = new ArrayList<>(4); + writers.add(visitorInteractionsWriter()); + writers.add(customerInteractionsWriter()); + writers.add(interactionMetadataWriter()); + writers.add(interactionWriter()); + compositeItemWriter.setDelegates(writers); + return compositeItemWriter; + } +} +``` + +각각의 전용(delegate) writer는 필요할 만큼 설정할 수 있다. 예를들면 *Interaction* 과 *InteractionMetadata*를 위한 writer가 있다. + +```xml + +``` +```xml + +``` + +reader와 동일하게 `statementId`는 네임스페이스를 가진 구문을 가리킬수 있다. + +매퍼 파일에서 구문은 다음과 같은 방법으로 각각의 레코드를 위해 만들어져있다. + +```xml + + + +``` +```xml + + + +``` + +먼저 `insertInteractionMetadata`가 호출될것이고 update구문은 jdbc드라이버에 의해(`keyProperty` 와 `keyColumn`) 생성된 아이디들을 리턴하기 위해 설정되었다. +`InteractionMetadata` 객체가 이 쿼리에 의해 업데이트되면 다음의 쿼리는 `insertInteraction`를 통해 상위객체인 `Interaction`를 작성하기 위해 사용될수 있다. + +***방금 언급한 내용에 관련하여 JDBC드라이버가 똑같이 동작하지 않을수 있다. +이 글을 쓰는 시점에 H2 드라이버 1.3.168버전(`org.h2.jdbc.JdbcStatement#getGeneratedKeys`를 보라)만 배치모드에서 마지막 인덱스를 리턴한다. +반면에 MySQL 드라이버는 기대한 것과 동일하게 동작하고 모든 아이디를 리턴한다.*** diff --git a/src/site/ko/markdown/boot.md b/src/site/ko/markdown/boot.md new file mode 100644 index 0000000000..7e932a7fa6 --- /dev/null +++ b/src/site/ko/markdown/boot.md @@ -0,0 +1,4 @@ + +# 스프링 부트 사용하기 + +자세한 내용은 [MyBatis Spring-boot-starter](http://www.mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure) 하위 프로젝트 문서를 참조하십시오. diff --git a/src/site/ko/markdown/factorybean.md b/src/site/ko/markdown/factorybean.md new file mode 100644 index 0000000000..e0a79081ad --- /dev/null +++ b/src/site/ko/markdown/factorybean.md @@ -0,0 +1,97 @@ + +# SqlSessionFactoryBean + +마이바티스만 사용하면, `SqlSessionFactory`는 `SqlSessionFactoryBuilder`를 사용해서 생성한다. +마이바티스 스프링 연동모듈에서는, `SqlSessionFactoryBean`가 대신 사용된다. + +## 설정 + +팩토리 빈을 생성하기 위해, 스프링 XML설정파일에 다음설정을 추가하자. + +```xml + + + +``` + +`SqlSessionFactoryBean` 은 스프링의 `FactoryBean` 인터페이스를 구현(see [the Spring documentation(Core Technologies -Customizing instantiation logic with a FactoryBean-)](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-extension-factorybean))한다는 점을 알아야 한다. +이 설정은 스프링이 `SqlSessionFactoryBean` 자체를 생성하는 것이 **아니라** 팩토리에서 `getObject()` 메서드를 호출한 결과를 리턴한다는 것을 의미한다. +이 경우, 스프링은 애플리케이션 시작 시점에 `SqlSessionFactory`를 빌드하고 `sqlSessionFactory` 라는 이름으로 저장한다. 자바에서 코드로 표현하면 아래와 같다. + +```java +@Configuration +public class MyBatisConfig { + @Bean + public SqlSessionFactory sqlSessionFactory() { + SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); + factoryBean.setDataSource(dataSource()); + return factoryBean.getObject(); + } +} +``` + +일반적인 마이바티스 스프링 사용법에서는, `SqlSessionFactoryBean`이나 관련된 `SqlSessionFactory`를 직접 사용할 필요가 없다. +대신 세션 팩토리가 `MapperFactoryBean`나 `SqlSessionDaoSupport`를 확장하는 다른 DAO에 주입될것이다. + +## 속성 + +`SqlSessionFactory`는 JDBC `DataSource`의 필수 프로퍼티가 필요하다. 어떤 `DataSource`라도 상관없고 다른 스프링 데이터베이스 연결처럼 설정되어야만 한다. + +하나의 공통적인 프로퍼티는 마이바티스 XML설정파일의 위치를 지정하기 위해 사용되는 `configLocation`이다. 이 프로퍼티를 설정하는 것은 디폴트 설정을 가진 마이바티스 설정을 변경해야 할 경우 뿐이다. +대개는 ``과 `` 섹션을 변경하는 경우이다. + +설정파일이 마이바티스 설정을 완전히 다룰 필요는 없다. 어떤 환경, 어떤 데이터소스 그리고 마이바티스 트랜잭션 관리자가 **무시**될수도 있다. +`SqlSessionFactoryBean` 는 필요에 따라 이 값들을 설정하여 자체적인 MyBatis `Environment` 를 만든다. + +설정파일이 필요한 다른 이유는 마이바티스 XML파일이 매퍼 클래스와 동일한 클래스패스에 있지 않은 경우이다. 이 설정을 사용하면 두가지 옵션이 있다. +첫번째는 마이바티스 설정파일에 `` 섹션을 사용해서 XML파일의 클래스패스를 지정하는 것이다. 두번째는 팩토리 빈의 `mapperLocations` 프로퍼티를 사용하는 것이다. + +`mapperLocations` 프로퍼티는 매퍼에 관련된 자원의 위치를 나열한다. 이 프로퍼티는 마이바티스의 XML매퍼 파일들의 위치를 지정하기 위해 사용될 수 있다. +디렉터리 아래 모든 파일을 로드하기 위해 앤트(Ant) 스타일의 패턴을 사용할수도 있고 가장 상위 위치를 지정하는 것으로 재귀적으로 하위 경로를 찾도록 할수도 있다. 예를 들어보면 다음과 같다. + +```xml + + + + +``` + +이 설정은 `sample.config.mappers` 패키지 아래와 그 하위 패키지를 모두 검색해서 마이바티스 매퍼 XML파일을 모두 로드할 것이다. + +컨테이너 관리 트랜잭션을 사용하는 환경에서 필요한 하나의 프로퍼티는 `transactionFactoryClass` 이다. 이에 관련해서는 트랜잭션을 다루는 장에서 볼수 있다. + +만약 multi-db 기능을 사용한다면 다음과 같이 `databaseIdProvider` 속성을 설정해야 한다. + +```xml + + + + sqlserver + db2 + oracle + mysql + + + +``` +````xml + + + + + +```` + +NOTE +1.3.0 버전 부터 `configuration` 속성이 추가되었다. 다음과 같이 MyBatis XML 설정 파일없이 `Configuration` 인스턴스를 직접 지정할 수 있습니다. + +```xml + + + + + + + + +``` diff --git a/src/site/ko/markdown/getting-started.md b/src/site/ko/markdown/getting-started.md new file mode 100644 index 0000000000..f04bde22cc --- /dev/null +++ b/src/site/ko/markdown/getting-started.md @@ -0,0 +1,98 @@ + +# 시작하기 + +이 장은 마이바티스 스프링 연동모듈을 설치하고 셋팅하는 방법에 대해 간단히 보여준다. 그리고 트랜잭션을 사용하는 간단한 애플리케이션을 만드는 방법까지 다룰 것이다. + +## 설치 + +마이바티스 스프링 연동모듈을 사용하기 위해서, 클래스패스에 `mybatis-spring-${project.version}.jar`를 포함시켜야 한다. + +메이븐을 사용하고 있다면 pom.xml에 다음처럼 의존성을 추가하면 된다. + +```xml + + org.mybatis + mybatis-spring + ${project.version} + +``` + +## 빠른 설정 + +마이바티스를 스프링과 함께 사용하려면 스프링의 애플리케이션 컨텍스트에 적어도 두개를 정의해줄 필요가 있다. +두가지는 `SqlSessionFactory`와 한개 이상의 매퍼 인터페이스이다. + +마이바티스 스프링 연동모듈에서, `SqlSessionFactoryBean`은 `SqlSessionFactory`를 만들기 위해 사용된다. 팩토리 빈을 설정하기 위해, 스프링 설정파일에 다음 설정을 추가하자. + +```xml + + + +``` + +```java +@Configuration +public class MyBatisConfig { + @Bean + public SqlSessionFactory sqlSessionFactory() throws Exception { + SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); + factoryBean.setDataSource(dataSource()); + return factoryBean.getObject(); + } +} +``` + +`SqlSessionFactory`는 `DataSource`를 필요로 하는 것을 알아둘 필요가 있다. 어떤 `DataSource`도 상관없지만 다른 스프링의 데이터베이스 연결과 동일하게 설정되어야 한다. + +매퍼 인터페이스가 다음처럼 정의되었다고 가정해보자. + +```java +public interface UserMapper { + @Select("SELECT * FROM users WHERE id = #{userId}") + User getUser(@Param("userId") String userId); +} +``` + +UserMapper인터페이스는 다음처럼 `MapperFactoryBean`을 사용해서 스프링에 추가된다. + +```xml + + + + +``` + +매퍼는 **반드시** 구현체 클래스가 아닌 인터페이스로 정의되어야 한다. 예를들어, 애노테이션이 SQL을 명시하기 위해 사용되지만 마이바티스 매퍼 XML파일 또한 사용될 수 있다. + +한번만 설정하면, 다른 스프링 빈에 주입하는 같은 방법으로 비즈니스/서비스 객체에 매퍼를 직접 주입할 수 있다. `MapperFactoryBean`은 `SqlSession`을 생성하고 닫는 작업을 잘 다룬다. +실행중인 스프링 트랜잭션이 있다면, 트랜잭션이 완료되는 시점에 커밋이나 롤백이 될 것이다. 마지막으로 예외가 발생하면 스프링의 `DataAccessException`예외가 발생한다. + +자바로 설정하면 다음과 같다. + +```java +@Configuration +public class MyBatisConfig { + @Bean + public UserMapper userMapper() throws Exception { + SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory()); + return sqlSessionTemplate.getMapper(UserMapper.class); + } +} +``` + +마이바티스의 데이터 관련 메서드는 호출하는 것은 한줄이면 된다. + +```java +public class FooServiceImpl implements FooService { + + private final UserMapper userMapper; + + public FooServiceImpl(UserMapper userMapper) { + this.userMapper = userMapper; + } + + public User doSomeBusinessStuff(String userId) { + return this.userMapper.getUser(userId); + } +} +``` diff --git a/src/site/ko/markdown/index.md b/src/site/ko/markdown/index.md new file mode 100644 index 0000000000..393eec171f --- /dev/null +++ b/src/site/ko/markdown/index.md @@ -0,0 +1,54 @@ + +# 소개 + +## MyBatis-Spring 은 무엇일까? + +마이바티스 스프링 연동모듈은 마이바티스와 스프링을 편하고 간단하게 연동한다. 이 모듈은 마이바티스로 하여금 스프링 트랜잭션에 쉽게 연동되도록 처리한다. 게다가 마이바티스 매퍼와 `SqlSession`을 다루고 다른 빈에 주입시켜준다. +마이바티스 예외를 스프링의 `DataAccessException`로 변환하기도 하고 마이바티스, 스프링 또는 마이바티스 스프링 연동모듈에 의존성을 없애기도 한다. + +## 동기 부여 + +스프링 2.x은 아이바티스 2.x만을 지원한다. 스프링 3.x에서 마이바티스 3.x를 지원하기 위한 시도가 진행중이다. (스프링의 이슈관리 시스템인 [이슈](https://jira.springsource.org/browse/SPR-5991) 를 보라.) +불행하게도 스프링 3의 개발이 마이바티스 3.0의 정식릴리즈전에 개발이 완료되었다. 그래서 스프링팀은 릴리즈가 안된 마이바티스 코드를 함께 릴리즈하는 것을 원하지 않았고 실제적인 스프링 지원을 기다릴수밖에 없었다. +스프링의 마이바티스 지원에 대한 관심으로 인해, 마이바티스 커뮤니티는 재결합하는 형태로 결정을 내고 대신 마이바티스의 하위 프로젝트 형태로 스프링 연동 프로젝트를 추가한다. + +## 필요 조건 + +마이바티스 스프링 연동을 시작하기 전에, 마이바티스와 스프링의 용어를 맞추는 일이 굉장히 중요했다. 이 문서는 배경지식이나 기본적인 셋업방법 그리고 마이바티스와 스프링의 설정에 대한 튜토리얼등은 제공하지 않는다. + +MyBatis-Spring requires following versions: + +| MyBatis-Spring | MyBatis | Spring Framework | Spring Batch | Java | +| --- | --- | --- | --- | --- | +| **2.0** | 3.5+ | 5.0+ | 4.0+ | Java 8+ | +| **1.3** | 3.4+ | 3.2.2+ | 2.1+ | Java 6+ | + +## 감사 인사 + +이 프로젝트가 실제로 만들어지게 도와준 모든 특별한 분들에게 정말 감사한다. +알파벳 순서로 보면, 코딩및 테스트 그리고 문서화를 담당했던 Eduardo Macarron, Hunter Presnall, Putthiphong Boonphong; +그외 다양한 프로젝트 기여자인 Andrius Juozapaitis, Giovanni Cuccu, Mike Lanyon, Raj Nagappan, Tomas Pinos; +그리고 마이바티스에 하위 프로젝트로 가져올수 있도록 많은 것을 찾아준 Simone Tripodi 에게 감사한다. ;) +이들이 없었다면 이 프로젝트는 존재하지 않았을 것이다. + +## 이 문서가 더 나아지도록 도와주세요… + +만약에 어떤 방법으로든 이 문서의 취약점이 발견되거나 기능에 대한 문서화가 빠진 부분이 보인다면, 가장 좋은 방법은 먼저 공부해서 자신만의 문서를 작성하는 것이다. + +이 문서의 원본은 xdoc포맷이며 [프로젝트의 Git](https://github.com/mybatis/spring/tree/master/src/site)에서 찾을 수 있다. repository 를 fork 하고, 업데이트하고 pull request 를 보내주십시오. + +당신처럼 이 문서를 읽는 사람들에게 이 문서의 최고의 저자가 될수 있다! + +## 번역 + +사용자들은 다음의 번역문서별로 마이바티스 스프링 연동모듈에 대해 알수 있다. + + + +위 번역문서에는 없지만 자국의 언어로 문서로 보고 싶다면, 자국의 언어로 된 문서를 만들어서 우리에게 보내달라. diff --git a/src/site/ko/markdown/mappers.md b/src/site/ko/markdown/mappers.md new file mode 100644 index 0000000000..c56ba731ff --- /dev/null +++ b/src/site/ko/markdown/mappers.md @@ -0,0 +1,184 @@ + +# 매퍼 주입 + +`SqlSessionDaoSupport` 나 `SqlSessionTemplate` 를 직접적으로 사용하는 데이터 접근 객체(DAO)를 생성하기 보다, 마이바티스 스프링 연동모듈은 다른 빈에 직접 주입할 수 있는 쓰레드에 안전한 매퍼를 생성할 수 있다. + +```xml + + + +``` + +한번 주입하고나면 매퍼는 애플리케이션 로직에서 사용할수 있는 준비가 된다. + +```java +public class FooServiceImpl implements FooService { + + private final UserMapper userMapper; + + public FooServiceImpl(UserMapper userMapper) { + this.userMapper = userMapper; + } + + public User doSomeBusinessStuff(String userId) { + return this.userMapper.getUser(userId); + } +} +``` + +이 코드를 보면 `SqlSession`이나 마이바티스 객체가 보이지 않는다. 게다가 세션을 생성하거나 열고 닫을필요도 없어보인다. 마이바티스 스프링 연동모듈이 알아서 처리할 것이다. + + +## 매퍼 등록하기 + +매퍼를 등록하는 방법은 기존의 전통적인 XML설정법을 사용하거나 새로운 3.0 이후의 자바설정(일명 `@Configuration`)을 사용하느냐에 따라 다르다. + +### XML설정 사용 + +매퍼는 다음처럼 XML설정파일에 `MapperFactoryBean`을 두는 것으로 스프링에 등록된다. + +```xml + + + + +``` + +UserMapper가 매퍼 인터페이스와 같은 경로의 클래스패스에 마이바티스 XML매퍼 파일을 가지고 있다면 `MapperFactoryBean`이 자동으로 파싱할것이다. +매퍼 XML파일을 다른 클래스패스에 두는게 아니라면 마이바티스 설정파일에 매퍼를 지정할 필요가 없다. 좀더 세부적인 정보는 `SqlSessionFactoryBean`의 [`configLocation`](factorybean.html) 프로퍼티를 살펴보자. + +`MapperFactoryBean`은 `SqlSessionFactory` 나 `SqlSessionTemplate`가 필요하다. `sqlSessionFactory` 와 `sqlSessionTemplate` 프로퍼티를 셋팅하면 된다. +둘다 셋팅하면 `SqlSessionFactory`가 무시된다. 세션 팩토리 셋은 `SqlSessionTemplate`이 필요하고 `MapperFactoryBean`는 팩토리를 사용할것이다. + +### 자바설정 사용 + +```java +@Configuration +public class MyBatisConfig { + @Bean + public MapperFactoryBean userMapper() throws Exception { + MapperFactoryBean factoryBean = new MapperFactoryBean<>(UserMapper.class); + factoryBean.setSqlSessionFactory(sqlSessionFactory()); + return factoryBean; + } +} +``` + + +## 매퍼 스캔 + +하나씩 매퍼를 모두 등록할 필요가 없다. 대신 클래스패스를 지정해서 마이바티스 스프링 연동모듈의 자동스캔기능을 사용할 수 있다. + +자동스캔을 사용하는데는 3가지 방법이 있다. + +* `` 엘리먼트 사용 +* `@MapperScan` 애노테이션 사용 +* 스프링 XML파일을 사용해서 `MapperScannerConfigurer`를 등록 + +`` 와 `@MapperScan` 모두 마이바티스 스프링 연동모듈 1.2.0에서 추가된 기능이다. `@MapperScan` 은 스프링 버전이 3.1이상이어야 한다. + +Since 2.0.2, mapper scanning feature support a option (`lazy-initialization`) that control lazy initialization enabled/disabled of mapper bean. +The motivation for adding this option is supporting a lazy initialization control feature supported by Spring Boot 2.2. +The default of this option is `false` (= not use lazy initialization). If developer want to use lazy initialization for mapper bean, it should be set to the `true` expressly. + +IMPORTANT +If use the lazy initialization feature, the developer need to understand following limitations. If any of following conditions are matches, usually the lazy initialization feature cannot use on your application. + +* When refers to the statement of **other mapper** using ``(`@One`) and ``(`@Many`) +* When includes to the fragment of **other mapper** using `` +* When refers to the cache of **other mapper** using ``(`@CacheNamespaceRef`) +* When refers to the result mapping of **other mapper** using `]]> - -

다음의 코드는 샘플 설정이다.

- - - - -
]]> - - reader() { - return new MyBatisPagingItemReaderBuilder() - .sqlSessionFactory(sqlSessionFactory()) - .queryId("com.my.name.space.batch.EmployeeMapper.getEmployee") - .build(); -}]]> - -

좀더 복잡한 예제를 보자.

- - - - - - - - -]]> - - dateBasedCriteriaReader( - @Value("#{@datesParameters}") Map datesParameters) throws Exception { - return new MyBatisPagingItemReaderBuilder() - .sqlSessionFactory(batchReadingSessionFactory()) - .queryId("com.my.name.space.batch.ExampleMapper.queryUserInteractionsOnSpecificTimeSlot") - .parameterValues(datesParameters) - .pageSize(200) - .build(); -} - -@StepScope -@Bean -public Map datesParameters( - @Value("#{jobExecutionContext['EXTRACTION_START_DATE']}") LocalDate yesterday, - @Value("#{jobExecutionContext['TODAY_DATE']}") LocalDate today, - @Value("#{jobExecutionContext['FIRST_DAY_OF_THE_MONTH_DATE']}") LocalDate firstDayOfTheMonth, - @Value("#{jobExecutionContext['FIRST_DAY_OF_THE_PREVIOUS_MONTH_DATE']}") LocalDate firstDayOfThePreviousMonth) { - Map map = new HashMap<>(); - map.put("yesterday", yesterday); - map.put("today", today); - map.put("first_day_of_the_month", firstDayOfTheMonth); - map.put("first_day_of_the_previous_month", firstDayOfThePreviousMonth); - return map; -}]]> - -

앞의 예제와는 몇가지 차이점이 있다.

- -
    -
  • sqlSessionFactory: reader에 별도로 구현한 sessionFactory를 지정할 수 있다. - 이 옵션은 다양한 데이터베이스에서 데이터를 읽을때 유용하다.
  • -
  • queryId: 여러개의 테이블에서 데이터를 읽어야 하고 서로 다른 쿼리를 사용한다면 - 서로다른 네임스페이스를 가진 매퍼 파일을 사용하는게 좋을수 있다. - 쿼리를 알아볼때, 매퍼 파일의 네임스페이스를 잊지 말아야 한다.
  • -
  • parameterValues: 이 맵을 사용해서 추가로 파라미터를 전달할 수 있다. - 위 예제는 jobExecutionContext에서 값들을 가져오는 SpEL표현식을 사용하는 맵을 사용하고 있다. - 맵의 키는 매퍼파일에서 마이바티스가 사용할 것이다. (예: yesterday#{yesterday,jdbcType=TIMESTAMP} 로 사용될수 있다.). - 맵과 reader 모두 jobExecutionContext에서 SpEL표현식을 사용하기 위해 step 스코프를 사용한다. - 마이바티스의 타입핸들러가 제대로 설정이 되었다면 JodaTime날짜를 맵을 사용해서 파라미터로 넘길수 있다.
  • -
  • pageSize: 배치가 청크크기가 지정된 형태로 처리가 되면 reader에 이 값을 전달하는게 적절하다.
  • -
- - - - -

- 이 빈은 cursor 를 사용하여 데이터베이스에서 레코드를 읽는 ItemReader 이다. -

- -

- 중요 이 빈을 사용하려면 최소한 MyBatis 3.4.0 이나 그 이상이어야 한다. -

- -

- setQueryId 속성으로 지정된 쿼리를 실행하여 selectCursor() 메서드를 사용하여 요청 된 데이터를 검색한다. - read() 메서드가 호출 될 때마다 요소가 더 이상 남아 있지 않을 때까지 cursor 의 다음 요소를 반환한다. -

- -

- reader 는 별도의 connection 을 사용하므로 select 문은 step processing 일부로 생성된 트랜잭션에 속하지 않는다. -

- -

cursor 를 사용할 때 다음과 같이 일반 쿼리를 실행할 수 있다.

- - SELECT id, name, job FROM employees ORDER BY id ASC -]]> - -

아래는 샘플 설정이다.

- - - - -
]]> - - reader() { - return new MyBatisCursorItemReaderBuilder() - .sqlSessionFactory(sqlSessionFactory()) - .queryId("com.my.name.space.batch.EmployeeMapper.getEmployee") - .build(); -}]]> - - - - - -

모든 아이템을 배치로 구문을 일괄실행하기 위해 SqlSessionTemplate에서 배치로 작업을 처리하는 ItemWriter이다. - SqlSessionFactoryBATCH 실행자로 설정할 필요가 있다.

- -

사용자는 write() 메서드가 호출될때 실행될 매핑구문 아이디를 제공해야 한다. - write() 메서드는 트랜잭션내에서 호출되는 것으로 예상된다.

- -

다음의 코드는 샘플설정이다.

- - - - -
]]> - - writer() { - return new MyBatisBatchItemWriterBuilder() - .sqlSessionFactory(sqlSessionFactory()) - .statementId("com.my.name.space.batch.EmployeeMapper.updateEmployee") - .build(); -}]]> - - -

Converting a item that read using ItemReader to an any parameter object:

- -

- By default behavior, the MyBatisBatchItemWriter passes a item that read using ItemReader - (or convert by ItemProcessor) to the MyBatis(SqlSession#update()) as the parameter object. - If you want to customize a parameter object that passes to the MyBatis, you can realize to use the itemToParameterConverter option. - For example using itemToParameterConverter option, you can passes any objects other than the item object to the MyBatis. - Follows below a sample: -

- -

- At first, you create a custom converter class (or factory method). The following sample uses a factory method. -

- - Converter> createItemToParameterMapConverter(String operationBy, LocalDateTime operationAt) { - return item -> { - Map parameter = new HashMap<>(); - parameter.put("item", item); - parameter.put("operationBy", operationBy); - parameter.put("operationAt", operationAt); - return parameter; - }; -}]]> - -

- At next, you write a sql mapping. -

- - - insert into persons (first_name, last_name, operation_by, operation_at) - values(#{item.firstName}, #{item.lastName}, #{operationBy}, #{operationAt}) -]]> - -

- At last, you configure the MyBatisBatchItemWriter. -

- - writer() throws Exception { - return new MyBatisBatchItemWriterBuilder() - .sqlSessionFactory(sqlSessionFactory()) - .statementId("org.mybatis.spring.sample.mapper.PersonMapper.createPerson") - .itemToParameterConverter(createItemToParameterMapConverter("batch_java_config_user", LocalDateTime.now())) - .build(); -}]]> - - - - - - - - - - - - -]]> - - -

여러개의 테이블에 데이터를 쓰려면 한꺼번에 처리할 수 있도록 만든 writer(몇가지 규칙을 가지고)를 사용하자.

- -

이 기능은 마이바티스 3.2이상에서만 사용할 수 있다. 이전의 버전에서는 예상과 다르게 동작하는데 그 내용은 - 이슈를 참고하면 된다.

- -

배치가 관계를 가지는 데이터나 여러개의 데이터베이스를 다루는 것처럼 복잡한 데이터를 작성할때 필요하다면 - insert구문이 한개에 테이블에만 데이터를 넣을수 있다는 사실만 피하면 가능하기도 하다. - 이런 복잡한 데이터를 처리하기 위해 writer가 작성하는 아이템(Item)을 준비해야 한다. - 다음의 기술을 사용하면 단순한 관계를 가진 데이터나 관계가 없는 테이블을 처리하는 아이템에서 사용할 수 있다.

- -

이러한 방법으로 스프링 배치 아이템은 모든 레코드를 다룰것이다. - 여기에는 1:1 관계를 가지는 InteractionMetadata, - 관계가 없는 두개의 로우는 VisitorInteractionCustomerInteraction이 있다. - 이 각각의 객체는 다음과 같이 볼수 있다.

- - - -

그리고 스프링 설정에는 각각의 레코드를 처리하기위해 특별히 설정된 - 전용(delegates) writer를 사용하는 CompositeItemWriter가 있다.

- - - - - - - - - - - - -
]]> - - interactionsItemWriter() { - CompositeItemWriter compositeItemWriter = new CompositeItemWriter(); - List> writers = new ArrayList<>(4); - writers.add(visitorInteractionsWriter()); - writers.add(customerInteractionsWriter()); - writers.add(interactionMetadataWriter()); - writers.add(interactionWriter()); - compositeItemWriter.setDelegates(writers); - return compositeItemWriter; -}]]> - -

각각의 전용(delegate) writer는 필요할 만큼 설정할 수 있다. - 예를들면 InteractionInteractionMetadata를 위한 writer가 있다.

- - -]]> - -

reader와 동일하게 statementId는 네임스페이스를 가진 구문을 가리킬수 있다.

- -

매퍼 파일에서 구문은 다음과 같은 방법으로 각각의 레코드를 위해 만들어져있다.

- - - - - - -]]> - -

먼저 insertInteractionMetadata가 호출될것이고 - update구문은 jdbc드라이버에 의해(keyPropertykeyColumn) 생성된 아이디들을 리턴하기 위해 설정되었다. - InteractionMetadata 객체가 이 쿼리에 의해 업데이트되면 다음의 쿼리는 - insertInteraction를 통해 상위객체인 Interaction를 작성하기 위해 사용될수 있다.

- -

방금 언급한 내용에 관련하여 JDBC드라이버가 똑같이 동작하지 않을수 있다. - 이 글을 쓰는 시점에 H2 드라이버 1.3.168버전(org.h2.jdbc.JdbcStatement#getGeneratedKeys를 보라)만 배치모드에서 마지막 인덱스를 리턴한다. - 반면에 MySQL 드라이버는 기대한 것과 동일하게 동작하고 모든 아이디를 리턴한다.

- - - - diff --git a/src/site/ko/xdoc/boot.xml b/src/site/ko/xdoc/boot.xml deleted file mode 100644 index 8684637274..0000000000 --- a/src/site/ko/xdoc/boot.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - MyBatis-Spring | Spring Boot - Eduardo Macarron - - - -
-

- 자세한 내용은 MyBatis Spring-boot-starter - 하위 프로젝트 문서를 참조하십시오. -

-
- -
diff --git a/src/site/ko/xdoc/factorybean.xml b/src/site/ko/xdoc/factorybean.xml deleted file mode 100644 index cc3d839a59..0000000000 --- a/src/site/ko/xdoc/factorybean.xml +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - 마이바티스 스프링 연동모듈 | SqlSessionFactoryBean - Hunter Presnall - Eduardo Macarron - 이동국(한국어 번역) - - - -
-

마이바티스만 사용하면, SqlSessionFactorySqlSessionFactoryBuilder를 사용해서 생성한다. - 마이바티스 스프링 연동모듈에서는, SqlSessionFactoryBean가 대신 사용된다.

- - -

팩토리 빈을 생성하기 위해, 스프링 XML설정파일에 다음설정을 추가하자.

- - -]]> -

SqlSessionFactoryBean 은 스프링의 FactoryBean 인터페이스를 구현(see the Spring documentation(Core Technologies -Customizing instantiation logic with a FactoryBean-))한다는 점을 알아야 한다. - 이 설정은 스프링이 SqlSessionFactoryBean 자체를 생성하는 것이 아니라 팩토리에서 getObject() 메서드를 호출한 결과를 리턴한다는 것을 의미한다. - 이 경우, 스프링은 애플리케이션 시작 시점에 SqlSessionFactory를 빌드하고 sqlSessionFactory 라는 이름으로 저장한다. - 자바에서 코드로 표현하면 아래와 같다.

- - - -

일반적인 마이바티스 스프링 사용법에서는, SqlSessionFactoryBean이나 관련된 SqlSessionFactory를 직접 사용할 필요가 없다. - 대신 세션 팩토리가 MapperFactoryBeanSqlSessionDaoSupport를 확장하는 다른 DAO에 주입될것이다.

-
- - - -

SqlSessionFactory는 JDBC DataSource의 필수 프로퍼티가 필요하다. - 어떤 DataSource라도 상관없고 다른 스프링 데이터베이스 연결처럼 설정되어야만 한다.

- -

하나의 공통적인 프로퍼티는 마이바티스 XML설정파일의 위치를 지정하기 위해 사용되는 configLocation이다. - 이 프로퍼티를 설정하는 것은 디폴트 설정을 가진 마이바티스 설정을 변경해야 할 경우 뿐이다. - 대개는 <settings><typeAliases> 섹션을 변경하는 경우이다.

- -

설정파일이 마이바티스 설정을 완전히 다룰 필요는 없다. - 어떤 환경, 어떤 데이터소스 그리고 마이바티스 트랜잭션 관리자가 무시될수도 있다. - SqlSessionFactoryBean 는 필요에 따라 이 값들을 설정하여 자체적인 MyBatis Environment 를 만든다.

- -

설정파일이 필요한 다른 이유는 마이바티스 XML파일이 매퍼 클래스와 동일한 클래스패스에 있지 않은 경우이다. - 이 설정을 사용하면 두가지 옵션이 있다. - 첫번째는 마이바티스 설정파일에 <mappers> 섹션을 사용해서 XML파일의 클래스패스를 지정하는 것이다. - 두번째는 팩토리 빈의 mapperLocations 프로퍼티를 사용하는 것이다.

- -

mapperLocations 프로퍼티는 매퍼에 관련된 자원의 위치를 나열한다. - 이 프로퍼티는 마이바티스의 XML매퍼 파일들의 위치를 지정하기 위해 사용될 수 있다. - 디렉터리 아래 모든 파일을 로드하기 위해 앤트(Ant) 스타일의 패턴을 사용할수도 있고 가장 상위 위치를 지정하는 것으로 재귀적으로 하위 경로를 찾도록 할수도 있다. - 예를 들어보면 다음과 같다.

- - - - -]]> - -

이 설정은 sample.config.mappers 패키지 아래와 그 하위 패키지를 모두 검색해서 마이바티스 매퍼 XML파일을 모두 로드할 것이다.

- -

컨테이너 관리 트랜잭션을 사용하는 환경에서 필요한 하나의 프로퍼티는 transactionFactoryClass 이다. - 이에 관련해서는 트랜잭션을 다루는 장에서 볼수 있다.

- -

- 만약 multi-db 기능을 사용한다면 다음과 같이 databaseIdProvider 속성을 설정해야 한다. -

- - - - - sqlserver - db2 - oracle - mysql - - - - - - - - -]]> - -

- NOTE - 1.3.0 버전 부터 configuration 속성이 추가되었다. - 다음과 같이 MyBatis XML 설정 파일없이 Configuration 인스턴스를 직접 지정할 수 있습니다. -

- - - - - - - - -]]> - -
-
- -
diff --git a/src/site/ko/xdoc/getting-started.xml.vm b/src/site/ko/xdoc/getting-started.xml.vm deleted file mode 100644 index 2596988331..0000000000 --- a/src/site/ko/xdoc/getting-started.xml.vm +++ /dev/null @@ -1,118 +0,0 @@ - - - - - - 마이바티스 스프링 연동모듈 | 시작하기 - Hunter Presnall - Eduardo Macarron - 이동국(한국어 번역) - - - -
-

이 장은 마이바티스 스프링 연동모듈을 설치하고 셋팅하는 방법에 대해 간단히 보여준다. - 그리고 트랜잭션을 사용하는 간단한 애플리케이션을 만드는 방법까지 다룰 것이다.

- - -

마이바티스 스프링 연동모듈을 사용하기 위해서, 클래스패스에 mybatis-spring-${project.version}.jar를 포함시켜야 한다.

-

메이븐을 사용하고 있다면 pom.xml에 다음처럼 의존성을 추가하면 된다.

- - org.mybatis - mybatis-spring - ${project.version} -]]> -
- - -

마이바티스를 스프링과 함께 사용하려면 스프링의 애플리케이션 컨텍스트에 적어도 두개를 정의해줄 필요가 있다. - 두가지는 SqlSessionFactory와 한개 이상의 매퍼 인터페이스이다.

- -

마이바티스 스프링 연동모듈에서, SqlSessionFactoryBeanSqlSessionFactory를 만들기 위해 사용된다. - 팩토리 빈을 설정하기 위해, 스프링 설정파일에 다음 설정을 추가하자. -

- - - -]]> - - - -

SqlSessionFactoryDataSource를 필요로 하는 것을 알아둘 필요가 있다. - 어떤 DataSource도 상관없지만 다른 스프링의 데이터베이스 연결과 동일하게 설정되어야 한다.

- -

매퍼 인터페이스가 다음처럼 정의되었다고 가정해보자.

- - -

UserMapper인터페이스는 다음처럼 MapperFactoryBean을 사용해서 스프링에 추가된다.

- - - -]]> - -

매퍼는 반드시 구현체 클래스가 아닌 인터페이스로 정의되어야 한다. - 예를들어, 애노테이션이 SQL을 명시하기 위해 사용되지만 마이바티스 매퍼 XML파일 또한 사용될 수 있다.

- -

한번만 설정하면, 다른 스프링 빈에 주입하는 같은 방법으로 비즈니스/서비스 객체에 매퍼를 직접 주입할 수 있다. - MapperFactoryBeanSqlSession을 생성하고 닫는 작업을 잘 다룬다. - 실행중인 스프링 트랜잭션이 있다면, 트랜잭션이 완료되는 시점에 커밋이나 롤백이 될 것이다. - 마지막으로 예외가 발생하면 스프링의 DataAccessException예외가 발생한다.

- -

- 자바로 설정하면 다음과 같다. -

- - - -

마이바티스의 데이터 관련 메서드는 호출하는 것은 한줄이면 된다.

- -
-
- -
diff --git a/src/site/ko/xdoc/index.xml b/src/site/ko/xdoc/index.xml deleted file mode 100644 index 635a642b81..0000000000 --- a/src/site/ko/xdoc/index.xml +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - 마이바티스 스프링 연동모듈 | 소개 - Hunter Presnall - Eduardo Macarron - 이동국(한국어 번역) - - - -
- -

마이바티스 스프링 연동모듈은 마이바티스와 스프링을 편하고 간단하게 연동한다. - 이 모듈은 마이바티스로 하여금 스프링 트랜잭션에 쉽게 연동되도록 처리한다. - 게다가 마이바티스 매퍼와 SqlSession을 다루고 다른 빈에 주입시켜준다. - 마이바티스 예외를 스프링의 DataAccessException로 변환하기도 하고 마이바티스, 스프링 또는 마이바티스 스프링 연동모듈에 의존성을 없애기도 한다.

-
- - -

스프링 2.x은 아이바티스 2.x만을 지원한다. - 스프링 3.x에서 마이바티스 3.x를 지원하기 위한 시도가 진행중이다. - (스프링의 이슈관리 시스템인 이슈 를 보라.) - 불행하게도 스프링 3의 개발이 마이바티스 3.0의 정식릴리즈전에 개발이 완료되었다. - 그래서 스프링팀은 릴리즈가 안된 마이바티스 코드를 함께 릴리즈하는 것을 원하지 않았고 실제적인 스프링 지원을 기다릴수밖에 없었다. - 스프링의 마이바티스 지원에 대한 관심으로 인해, - 마이바티스 커뮤니티는 재결합하는 형태로 결정을 내고 대신 마이바티스의 하위 프로젝트 형태로 스프링 연동 프로젝트를 추가한다.

-
- - -

마이바티스 스프링 연동을 시작하기 전에, 마이바티스와 스프링의 용어를 맞추는 일이 굉장히 중요했다. - 이 문서는 배경지식이나 기본적인 셋업방법 그리고 마이바티스와 스프링의 설정에 대한 튜토리얼등은 제공하지 않는다.

-

- MyBatis-Spring requires following versions: -

- - - - - - - - - - - - - - - - - - - - - - - - - - -
- MyBatis-Spring - - MyBatis - - Spring Framework - - Spring Batch - - Java -
- 2.0 - - 3.5+ - - 5.0+ - - 4.0+ - - Java 8+ -
- 1.3 - - 3.4+ - - 3.2.2+ - - 2.1+ - - Java 6+ -
-
- - -

이 프로젝트가 실제로 만들어지게 도와준 모든 특별한 분들에게 정말 감사한다. - 알파벳 순서로 보면, 코딩및 테스트 그리고 문서화를 담당했던 Eduardo Macarron, Hunter Presnall, Putthiphong Boonphong; - 그외 다양한 프로젝트 기여자인 Andrius Juozapaitis, Giovanni Cuccu, Mike Lanyon, Raj Nagappan, Tomas Pinos; - 그리고 마이바티스에 하위 프로젝트로 가져올수 있도록 많은 것을 찾아준 Simone Tripodi 에게 감사한다. ;) - 이들이 없었다면 이 프로젝트는 존재하지 않았을 것이다.

-
- - -

만약에 어떤 방법으로든 이 문서의 취약점이 발견되거나 기능에 대한 문서화가 빠진 부분이 보인다면, - 가장 좋은 방법은 먼저 공부해서 자신만의 문서를 작성하는 것이다. -

-

이 문서의 원본은 xdoc포맷이며 프로젝트의 Git에서 찾을 수 있다. - repository 를 fork 하고, 업데이트하고 pull request 를 보내주십시오. -

-

당신처럼 이 문서를 읽는 사람들에게 이 문서의 최고의 저자가 될수 있다!

-
- - -

사용자들은 다음의 번역문서별로 마이바티스 스프링 연동모듈에 대해 알수 있다.

- -

위 번역문서에는 없지만 자국의 언어로 문서로 보고 싶다면, 자국의 언어로 된 문서를 만들어서 우리에게 보내달라.

-
- - -

번역자 : 이동국(fromm0@gmail.com, http://ldg.pe.kr, https://www.facebook.com/dongguk.lee.3)

-
-
- - -
diff --git a/src/site/ko/xdoc/mappers.xml b/src/site/ko/xdoc/mappers.xml deleted file mode 100644 index 32296b7086..0000000000 --- a/src/site/ko/xdoc/mappers.xml +++ /dev/null @@ -1,227 +0,0 @@ - - - - - - 마이바티스 스프링 연동모듈 | 매퍼 주입 - Hunter Presnall - Eduardo Macarron - 이동국(한국어 번역) - - - -
-

SqlSessionDaoSupportSqlSessionTemplate 를 직접적으로 사용하는 데이터 접근 객체(DAO)를 생성하기 보다, - 마이바티스 스프링 연동모듈은 다른 빈에 직접 주입할 수 있는 쓰레드에 안전한 매퍼를 생성할 수 있다.

- - - -]]> - -

한번 주입하고나면 매퍼는 애플리케이션 로직에서 사용할수 있는 준비가 된다.

- -

이 코드를 보면 SqlSession이나 마이바티스 객체가 보이지 않는다. - 게다가 세션을 생성하거나 열고 닫을필요도 없어보인다. - 마이바티스 스프링 연동모듈이 알아서 처리할 것이다.

- - -

매퍼를 등록하는 방법은 기존의 전통적인 XML설정법을 사용하거나 새로운 3.0 이후의 자바설정(일명 @Configuration)을 사용하느냐에 따라 다르다.

- -

XML설정 사용

- -

매퍼는 다음처럼 XML설정파일에 MapperFactoryBean을 두는 것으로 스프링에 등록된다.

- - - -]]> - -

UserMapper가 매퍼 인터페이스와 같은 경로의 클래스패스에 마이바티스 XML매퍼 파일을 가지고 있다면 MapperFactoryBean이 자동으로 파싱할것이다. - 매퍼 XML파일을 다른 클래스패스에 두는게 아니라면 마이바티스 설정파일에 매퍼를 지정할 필요가 없다. - 좀더 세부적인 정보는 SqlSessionFactoryBeanconfigLocation 프로퍼티를 살펴보자.

- -

MapperFactoryBeanSqlSessionFactorySqlSessionTemplate가 필요하다. - sqlSessionFactorysqlSessionTemplate 프로퍼티를 셋팅하면 된다. - 둘다 셋팅하면 SqlSessionFactory가 무시된다. - 세션 팩토리 셋은 SqlSessionTemplate이 필요하고 MapperFactoryBean는 팩토리를 사용할것이다.

- -

자바설정 사용

- - userMapper() throws Exception { - MapperFactoryBean factoryBean = new MapperFactoryBean<>(UserMapper.class); - factoryBean.setSqlSessionFactory(sqlSessionFactory()); - return factoryBean; -}]]> - -
- - -

하나씩 매퍼를 모두 등록할 필요가 없다. - 대신 클래스패스를 지정해서 마이바티스 스프링 연동모듈의 자동스캔기능을 사용할 수 있다.

- -

자동스캔을 사용하는데는 3가지 방법이 있다.

-
    -
  • <mybatis:scan/> 엘리먼트 사용
  • -
  • @MapperScan 애노테이션 사용
  • -
  • 스프링 XML파일을 사용해서 MapperScannerConfigurer를 등록
  • -
- -

<mybatis:scan/>@MapperScan 모두 마이바티스 스프링 연동모듈 1.2.0에서 추가된 기능이다. - @MapperScan 은 스프링 버전이 3.1이상이어야 한다.

- -

- Since 2.0.2, mapper scanning feature support a option (lazy-initialization) - that control lazy initialization enabled/disabled of mapper bean. - The motivation for adding this option is supporting a lazy initialization control feature supported by Spring Boot 2.2. - The default of this option is false (= not use lazy initialization). - If developer want to use lazy initialization for mapper bean, it should be set to the true expressly. -

-

- IMPORTANT If use the lazy initialization feature, - the developer need to understand following limitations. If any of following conditions are matches, - usually the lazy initialization feature cannot use on your application. -

-
    -
  • When refers to the statement of other mapper using ]]>(@One) and ]]>(@Many)
  • -
  • When includes to the fragment of other mapper using ]]>
  • -
  • When refers to the cache of other mapper using ]]>(@CacheNamespaceRef)
  • -
  • When refers to the result mapping of other mapper using ]]>(@ResultMap)
  • -
- -

- NOTE However, It become possible to use it by simultaneously initializing dependent beans using @DependsOn(Spring's feature) as follow: -

- - - -

- Since 2.0.6, the develop become can specified scope of mapper using mapper scanning feature option(default-scope) - and scope annotation(@Scope, @RefreshScope, etc ...). - The motivation for adding this option is supporting the refresh scope provided by the Spring Cloud. - The default of this option is empty (= equiv to specify the singleton scope). - The default-scope apply to the mapper bean(MapperFactoryBean) when scope of scanned bean definition - is singleton(default scope) and create a scoped proxy bean for scanned mapper when final scope is not singleton. -

- -

<mybatis:scan/>

- -

<mybatis:scan/> XML엘리먼트는 스프링에서 제공하는 <context:component-scan/> 엘리먼트와 매우 유사한 방법으로 매퍼를 검색할 것이다.

- -

샘플 XML설정을 아래에서 볼수 있다.

- - - - - - - -]]> - -

base-package 속성은 매퍼 인터페이스 파일이 있는 가장 상위 패키지를 지정하면 된다. - 세미콜론이나 콤마를 구분자로 사용해서 한개 이상의 패키지를 셋팅할 수 있다. - 매퍼는 지정된 패키지에서 재귀적으로 하위 패키지를 모두 검색할 것이다.

- -

<mybatis:scan/>이 자동으로 주입할 수 있는 MapperFactoryBean를 생성하기 때문에 - SqlSessionFactorySqlSessionTemplate 를 명시할 필요가 없다. - 하지만 한개 이상의 DataSource를 사용한다면 자동주입이 생각한데로 동작하지 않을수도 있다. - 이 경우 사용할 빈 이름을 지정하기 위해 factory-reftemplate-ref 속성을 사용할수 있다.

- -

<mybatis:scan/>은 마커(marker) 인터페이스나 애노테이션을 명시해서 생성되는 매퍼를 필터링할수도 있다. - annotation 프로퍼티는 검색할 애노테이션을 지정한다. - marker-interface 프로퍼티는 검색할 상위 인터페이스를 지정한다. - 이 두개의 프로퍼티를 모두 지정하면, 매퍼는 두 조건을 모두 만족하는 인터페이스만을 추가한다. - 디폴트로 이 두가지 프로퍼티는 모두 null이다. - 그래서 base-package프로퍼티에 설정된 패키지 아래 모든 인터페이스가 매퍼로 로드될 것이다.

- -

발견된 매퍼는 자동검색된 컴포넌트를 위한 스프링의 디폴트 명명규칙 전략(see the Spring reference document(Core Technologies -Naming autodetected components-))을 사용해서 빈이름이 명명된다. - 빈 이름을 정하는 애노테이션이 없다면 매퍼의 이름에서 첫글자를 소문자로 변환한 형태로 빈 이름을 사용할 것이다. - @Component 나 JSR-330의 @Named 애노테이션이 있다면 애노테이션에 정의한 이름을 그대로 사용할 것이다. - annotation 프로퍼티를 org.springframework.stereotype.Component, - javax.inject.Named(자바SE 1.6을 사용한다면) 또는 개발자가 스스로 작성한 애노테이션으로 셋팅할 수 있다. - 그러면 애노테이션은 마커와 이름을 제공하는 역할로 동작할 것이다.

- -

- 중요 <context:component-scan/> 가 매퍼를 검색해서 등록을 하지 못할수도 있다. - 매퍼는 인터페이스고 스프링에 빈으로 등록하기 위해서는 각각의 인터페이스를 찾기 위해 스캐너가 MapperFactoryBean 를 생성하는 방법을 알아야만 한다.

- -

@MapperScan

- -

@Configuration 라고 불리는 스프링의 자바설정을 사용한다면 <mybatis:scan/>보다는 - @MapperScan를 사용하길 선호할것이다.

- -

@MapperScan 애노테이션은 다음처럼 사용된다.

- - - -

애노테이션은 앞서 본 <mybatis:scan/> 에서 설명하는 것과 동일하게 동작한다. - markerInterfaceannotationClass 프로퍼티를 사용해서 마커 인터페이스와 애노테이션 클래스를 명시하게 한다. - sqlSessionFactorysqlSessionTemplate 프로퍼티를 사용해서 - SqlSessionFactorySqlSessionTemplate을 제공할 수도 있다.

- -

- NOTE Since 2.0.4, If basePackageClasses or basePackages are not defined, scanning will occur from the package of the class that declares this annotation. -

- -

MapperScannerConfigurer

- -

MapperScannerConfigurer는 평범한 빈처럼 XML애플리케이션 컨텍스트에 포함된 BeanDefinitionRegistryPostProcessor 이다. - MapperScannerConfigurer를 셋업하기 위해 다음의 스프링 설정을 추가하자.

- - -]]> - -

sqlSessionFactorysqlSessionTemplate를 지정할 필요가 있다면 빈참조가 아닌 빈이름이 필요하다. - value 프로퍼티는 빈 이름을 지정하고 ref 는 빈 참조를 지정하기 때문에 value 프로퍼티를 사용하자.

- ]]> - -

중요 sqlSessionFactoryBeansqlSessionTemplateBean 프로퍼티는 - 마이바티스 스프링 연동모듈 1.0.2 버전 이상에서만 사용이 가능하다. 하지만 MapperScannerConfigurer는 잦은 에러를 발생시키는 - PropertyPlaceholderConfigurer보다 앞서 실행되기 때문에 이 프로퍼티들은 사용하지 말길 바란다(deprecated). - 대신 새롭게 추가된 프로퍼티인 sqlSessionFactoryBeanNamesqlSessionTemplateBeanName 를 사용하도록 권한다.

-
-
- -
diff --git a/src/site/ko/xdoc/sample.xml b/src/site/ko/xdoc/sample.xml deleted file mode 100644 index 7debe92347..0000000000 --- a/src/site/ko/xdoc/sample.xml +++ /dev/null @@ -1,168 +0,0 @@ - - - - - - MyBatis-Spring | Sample Code - Eduardo Macarron - - - -
- -

- 중요 - 전체 웹 애플리케이션 서버에서 Spring을 사용하는 방법을 알고 싶다면 JPetstore 6 demo 를 참조하십시오. -

- -

- MyBatis-Spring repository 에서 샘플 코드를 확인할 수 있다. -

-

- 모든 샘플은 JUnit5 에서 실행할 수 있다. -

-

- 샘플 코드는 트랜잭션 서비스가 data access layer 에서 도메인 개체를 가져 오는 일반적인 디자인을 보여준다. -

-

- 다음 FooService.java 는 서비스처럼 작동한다. -

- -

- 이것은 트랜잭션 빈이다. 따라서 어떤 메서드든 실행이 되면 트랜잭션이 시작되고 예외가 발생하지 않았을 때 커밋된다. - 트랜잭션은 @Transactional annotation 을 통해 설정할 수 있다. - 이것은 필수가 아니다. Spring이 제공하는 다른 방법을 사용하여 트랜잭션을 구분할 수 있다. -

-

- 이 서비스는 MyBatis로 이루어진 DAO layer 를 호출한다. - 이 layer는 런타임시 MyBatis에 의해 작성되고 Spring에 의해 서비스에 주입되는 동적 프록시와 함께 사용되는 UserMapper.java 인터페이스로 구성된다. -

- -

- 단순함을 위해서 DAO가 인터페이스와 그 구현체로 만들어진 DAO 시나리오를 위해 UserMapper.java 인터페이스를 사용했지만, - 이 경우 대신 UserDao.java라는 인터페이스를 사용하는 것이 더 적절하다. -

-

- 매퍼 인터페이스를 찾고 Spring에 등록하고 서비스 빈에 주입하는 여러 가지 방법을 살펴본다. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
시나리오
샘플 테스트설명
- SampleMapperTest.java - - UserMapper 구현체를 동적으로 빌드 할 MapperFactoryBean에 기반한 기본 구성을 보여준다. -
- SampleScannerTest.java - - MapperScannerConfigurer 를 사용하여 어떻게 프로젝트의 모든 매퍼들을 자동으로 검색되도록 하는 방법을 보여준다. -
- SampleSqlSessionTest.java - - Spring에서 관리하는 SqlSession을 사용하여 DAO를 코딩하고 자체적인 구현체인 UserDaoImpl.java 를 제공하는 방법을 보여준다. -
- SampleEnableTest - - 스프링의 @Configuration@MapperScann annotation을 함께 사용하여 매퍼를 자동으로 검색하는 방법을 보여준다. -
- SampleNamespaceTest - - 커스텀 MyBatis XML 네임스페이스를 사용하는 방법을 보여준다. -
- SampleJavaConfigTest.java - - 스프링의 @Configuration을 사용하여 MyBatis 빈들을 수동적으로 생성하는 방법을 보여준다. -
- SampleJobJavaConfigTest.java - - Java Configuration을 이용하여 Spring Batch에서 어떻게 ItemReaderItemWriter를 사용하는지 보여준다. -
- SampleJobXmlConfigTest.java - - XML Configuration을 이용하여 Spring Batch에서 어떻게 ItemReaderItemWriter를 사용하는지 보여준다. -
-

- MyBatis-Spring이 실제로 어떻게 다르게 작동하는지 보려면 applicationContext.xml 파일을 살펴보십시오. -

- -
- -
- diff --git a/src/site/ko/xdoc/sqlsession.xml b/src/site/ko/xdoc/sqlsession.xml deleted file mode 100644 index 23c92828a7..0000000000 --- a/src/site/ko/xdoc/sqlsession.xml +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - 마이바티스 스프링 연동모듈 | SqlSession 사용 - Hunter Presnall - Eduardo Macarron - 이동국(한국어 번역) - - - -
-

마이바티스에서는 SqlSession를 생성하기 위해 SqlSessionFactory를 사용한다. - 세션을 한번 생성하면 매핑구문을 실행하거나 커밋 또는 롤백을 하기 위해 세션을 사용할수 있다. - 마지막으로 더 이상 필요하지 않은 상태가 되면 세션을 닫는다. - 마이바티스 스프링 연동모듈을 사용하면 SqlSessionFactory를 직접 사용할 필요가 없다. - 왜냐하면, 스프링 트랜잭션 설정에 따라 자동으로 커밋 혹은 롤백을 수행하고 닫혀지는, 쓰레드에 안전한 SqlSession 개체가 스프링 빈에 주입될 수 있기 때문이다.

- - -

SqlSessionTemplate은 마이바티스 스프링 연동모듈의 핵심이다. - SqlSessionTemplateSqlSession을 구현하고 코드에서 SqlSession를 대체하는 역할을 한다. - SqlSessionTemplate 은 쓰레드에 안전하고 여러개의 DAO나 매퍼에서 공유할수 있다.

- -

getMapper()에 의해 리턴된 매퍼가 가진 메서드를 포함해서 SQL을 처리하는 마이바티스 메서드를 호출할때 - SqlSessionTemplateSqlSession이 현재의 스프링 트랜잭션에서 사용될수 있도록 보장한다. - 추가적으로 SqlSessionTemplate은 필요한 시점에 세션을 닫고, 커밋하거나 롤백하는 것을 포함한 세션의 생명주기를 관리한다. - 또한 마이바티스 예외를 스프링의 DataAccessException로 변환하는 작업또한 처리한다.

- -

SqlSessionTemplate은 마이바티스의 디폴트 구현체인 DefaultSqlSession 대신 항상 사용된다. - 왜냐하면 템플릿은 스프링 트랜잭션의 일부처럼 사용될 수 있고 여러개 주입된 매퍼 클래스에 의해 사용되도록 쓰레드에 안전하다. - 동일한 애플리케이션에서 두개의 클래스간의 전환은 데이터 무결성 이슈를 야기할수 있다.

- -

SqlSessionTemplate은 생성자 인자로 SqlSessionFactory를 사용해서 생성될 수 있다.

- - -]]> - - - -

이 빈은 DAO빈에 직접 주입될 수 있다. 다음처럼 빈 설정에서 SqlSession 프로퍼티를 설정하면 된다.

- -

그리고 다음처럼 SqlSessionTemplate 를 주입하자.

- - -]]> - -

SqlSessionTemplate은 인자로 ExecutorType를 가지는 생성자를 가지고 있다. - 이 인자는 예를들면 스프링 설정 XML을 다음처럼 설정해서 배치형태의 SqlSession를 만들수도 있다.

- - - -]]> - - - -

DAO의 코드를 다음처럼 작성했다면 모든 구문은 배치형태로 실행이 될 것이다.

- users) { - for (User user : users) { - sqlSession.insert("org.mybatis.spring.sample.mapper.UserMapper.insertUser", user); - } -}]]> - -

이러한 설정형태는 SqlSessionFactory의 디폴트 형태가 아닌 다른형태로 메서드를 실행해야 할때만 사용할 필요가 있다.

- -

이러한 형태에 대해 굳이 경로를 하자면 메서드를 호출할때 ExecutorType이 다르면 이미 시작된 트랜잭션을 사용하지 못할것이다. - 다른 실행자(executor) 타입을 사용할때는 SqlSessionTemplate의 메서드를 구분된 트랜잭션(PROPAGATION_REQUIRES_NEW를 사용하는)이나 트랜잭션 외부에서 호출하는지 확실히해야 한다.

-
- - -

SqlSessionDaoSupportSqlSession을 제공하는 추상클래스이다. - getSqlSession()메서드를 호출해서 다음처럼 SQL을 처리하는 마이바티스 메서드를 호출하기 위해 사용할 SqlSessionTemplate을 얻을 수 있다.

- -

대개 MapperFactoryBean은 추가적인 코드가 필요없기 때문에 이 클래스를 선호한다. - 하지만 DAO에서 마이바티스가 필요하지 않고 구현된 클래스가 필요하지 않을때만 유용하다.

- -

SqlSessionDaoSupportsqlSessionFactorysqlSessionTemplate 프로퍼티를 셋팅할 필요가 있다. - 두개의 프로퍼티를 모두 셋팅하면 sqlSessionFactory는 무시된다.

- -

SqlSessionDaoSupport의 하위클래스인 UserDaoImpl가 있다고 하면 스프링에서는 다음처럼 설정될 수 있다.

- - -]]> -
-
- -
diff --git a/src/site/ko/xdoc/transactions.xml b/src/site/ko/xdoc/transactions.xml deleted file mode 100644 index 0efb7ee971..0000000000 --- a/src/site/ko/xdoc/transactions.xml +++ /dev/null @@ -1,134 +0,0 @@ - - - - - - 마이바티스 스프링 연동모듈 | 트랜잭션 - Hunter Presnall - Eduardo Macarron - 이동국(한국어 번역) - - - -
-

마이바티스 스프링 연동모듈을 사용하는 중요한 이유중 하나는 마이바티스가 스프링 트랜잭션에 자연스럽게 연동될수 있다는 것이다. - 마이바티스에 종속되는 새로운 트랜잭션 관리를 만드는 것보다는 마이바티스 스프링 연동모듈이 스프링의 DataSourceTransactionManager과 융합되는 것이 좋다.

-

스프링 트랜잭션 관리자를 한번 설정하면, 대개의 경우처럼 스프링에서 트랜잭션을 설정할 수 있다. - @Transactional 애노테이션과 AOP스타일의 설정 모두 지원한다. - 하나의 SqlSession객체가 생성되고 트랜잭션이 동작하는 동안 지속적으로 사용될것이다. - 세션은 트랜잭션이 완료되면 적절히 커밋이 되거나 롤백될것이다.

-

마이바티스 스프링 연동모듈은 한번 셋업되면 트랜잭션을 투명하게 관리한다. - DAO클래스에 어떠한 추가적인 코드를 넣을 필요가 없다.

- - -

스프링 트랜잭션을 가능하게 하려면, 스프링 설정파일에 DataSourceTransactionManager를 생성하자.

- - -]]> - - - -

명시된 DataSource는 스프링을 사용할때 일반적으로 사용한다면 어떠한 JDBC DataSource도 될수 있다. - JNDI룩업을 통해 얻어진 DataSource뿐 아니라 커넥션 풀링 기능도 포함한다.

-

트랜잭션 관리자에 명시된 DataSourceSqlSessionFactoryBean을 생성할때 사용된 것과 반드시 동일한 것이어야 하는 것만 꼭 기억하자. - 그렇지 않으면 트랜잭션 관리가 제대로 되지 않을것이다.

-
- - -

만약에 JEE컨테이너를 사용하고 스프링을 컨테이너 관리 트랜잭션(container managed transactions, CMT)에 두려한다면, - 스프링은 JtaTransactionManager나 그 하위 클래스로 설정되어야 한다. - 이러한 설정을 가장 쉽게 하는 방법은 스프링의 트랜잭션 네임스페이스 or JtaTransactionManagerFactoryBean 를 사용하는 것이다.

- - ]]> - - - -

이 설정에서, 마이바티스는 CMT와 함께 설정된 스프링 트랜잭션 리소스처럼 동작할 것이다. - 스프링은 이미 설정된 트랜잭션을 사용해서 SqlSession을 이미 동작중인 트랜잭션에 넣을 것이다. - 시작된 트랜잭션이 없고 트랜잭션이 필요한 경우라면 스프링은 새로운 컨테이너 관리 트랜잭션을 시작할 것이다.

-

CMT는 사용하지만 스프링 트랜잭션 관리를 원하지 않는다면 어떠한 스프링 트랜잭션 관리자를 설정해서도 안되고 - 마이바티스 ManagedTransactionFactory를 사용하기 위해 SqlSessionFactoryBean를 설정해야만 한다.

- - - - - -]]> - - - -
- - -

마이바티스 SqlSession은 트랜잭션을 제어하는 메서드를 제공한다. - 하지만 마이바티스 스프링 연동모듈은 빈을 스프링이 관리하는 SqlSession이나 스프링이 관리하는 매퍼에 주입한다. - 이 말은 스프링이 항상 트랜잭션을 관리한다는 뜻이다.

-

스프링이 관리하는 SqlSession에서는 SqlSession.commit(), SqlSession.rollback() - 또는 SqlSession.close() 메서드를 호출할수가 없다. - 그럼에도 불구하고 이 메서드들을 사용하면 UnsupportedOperationException 예외가 발생한다. - 이러한 메서드는 주입된 매퍼 클래스에서는 사용할 수 없다.

-

JDBC연결의 자동커밋 설정을 어떻게 하더라도 스프링 트랜잭션 밖의 SqlSession 데이터 메서드나 매퍼 메서드의 실행은 자동으로 커밋된다.

-

트래잭션을 수동으로 제어하고자 한다면 the Spring reference document(Data Access -Programmatic transaction management-) 을 참고하자. - 다음의 코드는 스프링 레퍼런스 에서 언급된 내용으로 PlatformTransactionManager를 사용해서 수동으로 트랜잭션을 다루는 방법을 보여준다.

- - - -

- You can omit to call the commit and rollback method using the TransactionTemplate. -

- - { - userMapper.insertUser(user); - return null; -});]]> - -

이 코드는 매퍼를 사용하지만 SqlSession를 사용해도 잘 동작한다.

-
-
- -
diff --git a/src/site/ko/xdoc/using-api.xml b/src/site/ko/xdoc/using-api.xml deleted file mode 100644 index 760c6030c5..0000000000 --- a/src/site/ko/xdoc/using-api.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - 마이바티스 스프링 연동모듈 | 마이바티스 API 사용 - Hunter Presnall - Eduardo Macarron - 이동국(한국어 번역) - - - -
-

MyBatis-Spring 연동 모듈을 사용해도 계속해서 MyBatis API를 직접 사용할 수 있다. - SqlSessionFactoryBean을 사용해서 스프링에서 SqlSessionFactory를 생성하고 팩토리를 사용하면 된다.

- - -

이 방법은 신중히 사용하자. 왜냐하면 잘못사용하면 런타임 에러나 데이터 문제등을 야기할수 있기 때문이다. - API를 직접 사용할때는 다음의 규칙들에 유의해야 한다.

-
    -
  • -

    스프링 트랜잭션에 속하지 않고 별도의 트랜잭션에서 동작한다.

    -
  • -
  • -

    SqlSession이 스프링 트랜잭션 관리자가 사용하는 DataSource를 사용하고 - 이미 트랜잭션이 동작하고 있다면 이 코드는 예외를 발생시킬 것이다.

    -
  • -
  • -

    마이바티스의 DefaultSqlSession은 쓰레드에 안전하지 않다. - 빈에 이 객체를 주입하면 아마도 에러를 발생시킬 수 있다.

    -
  • -
  • -

    DefaultSqlSession을 사용해서 생성한 매퍼 또한 쓰레드에 안전하지 않다. - 이렇게 만든 매퍼를 빈에 주입하면 에러를 발생시킬 수 있다.

    -
  • -
  • -

    SqlSession항상 마지막에 close() 메서드를 호출해야 한다.

    -
  • -
-
- -
diff --git a/src/site/markdown/README.md b/src/site/markdown/README.md new file mode 100644 index 0000000000..74036dbd21 --- /dev/null +++ b/src/site/markdown/README.md @@ -0,0 +1,18 @@ +# Table of contents + +This page is for rendering index on GitHub. + +> **NOTE:** +> +> Since the link destination is specified on the assumption that it is converted to html with maven-site-plugin, there is an anchor that is broken in the rendering on GitHub. + +* [Introduction](./index.md) +* [Getting Started](./getting-started.md) +* [SqlSessionFactoryBean](./factorybean.md) +* [Transactions](./transactions.md) +* [Using an SqlSession](./sqlsession.md) +* [Injecting Mappers](./mappers.md) +* [Spring Boot](./boot.md) +* [Using the MyBatis API](./using-api.md) +* [Spring Batch](./batch.md) +* [Sample Code](./sample.md) diff --git a/src/site/markdown/batch.md b/src/site/markdown/batch.md new file mode 100644 index 0000000000..a6ad50418c --- /dev/null +++ b/src/site/markdown/batch.md @@ -0,0 +1,359 @@ + +# Spring Batch + +As of version 1.1.0 MyBatis-Spring provides three beans for building Spring Batch applications: the `MyBatisPagingItemReader`, the `MyBatisCursorItemReader` and the `MyBatisBatchItemWriter`. +Also, As of version 2.0.0 provides three builder classes for supporting the Java Configuration: the `MyBatisPagingItemReaderBuilder`, the `MyBatisCursorItemReaderBuilder` and the `MyBatisBatchItemWriterBuilder`. + +NOTE +This is about [Spring Batch](http://static.springsource.org/spring-batch/) and not about MyBatis batch SqlSessions. For information about batch sessions go to section [Using an SqlSession](sqlsession.html). + +## MyBatisPagingItemReader + +This bean is an `ItemReader` that reads records from a database in a paging fashion. + +It executes the query specified as the `setQueryId` property to retrieve requested data. +The query is executed using paged requests of a size specified in `setPageSize` property. +Additional pages are requested when needed as `read()` method is called, returning an object corresponding to current position. + +Some standard query parameters are provided by the reader and the SQL in the named query must use some or all of these parameters (depending on the SQL variant) to construct a result set of the required size. +The parameters are: + +* `_page`: the page number to be read (starting at 0) +* `_pagesize`: the size of the pages, i.e. the number of rows to return +* `_skiprows`: the product of `_page` and `_pagesize` + +And they could be mapped as the follow in a select statement: + +```xml + +``` + +Follows below a sample configuration snippet: + +```xml + + + + +``` + +```java +@Configuration +public class BatchAppConfig { + @Bean + public MyBatisPagingItemReader reader() { + return new MyBatisPagingItemReaderBuilder() + .sqlSessionFactory(sqlSessionFactory()) + .queryId("com.my.name.space.batch.EmployeeMapper.getEmployee") + .build(); + } +} +``` + +**Explaining a more complex example:** + +```xml + +``` +```xml + + + + + + +``` + +```java +@Configuration +public class BatchAppConfig { + @StepScope + @Bean + public MyBatisPagingItemReader dateBasedCriteriaReader( + @Value("#{@datesParameters}") Map datesParameters) throws Exception { + return new MyBatisPagingItemReaderBuilder() + .sqlSessionFactory(batchReadingSessionFactory()) + .queryId("com.my.name.space.batch.ExampleMapper.queryUserInteractionsOnSpecificTimeSlot") + .parameterValues(datesParameters) + .pageSize(200) + .build(); + } + + @StepScope + @Bean + public Map datesParameters( + @Value("#{jobExecutionContext['EXTRACTION_START_DATE']}") LocalDate yesterday, + @Value("#{jobExecutionContext['TODAY_DATE']}") LocalDate today, + @Value("#{jobExecutionContext['FIRST_DAY_OF_THE_MONTH_DATE']}") LocalDate firstDayOfTheMonth, + @Value("#{jobExecutionContext['FIRST_DAY_OF_THE_PREVIOUS_MONTH_DATE']}") LocalDate firstDayOfThePreviousMonth) { + Map map = new HashMap<>(); + map.put("yesterday", yesterday); + map.put("today", today); + map.put("first_day_of_the_month", firstDayOfTheMonth); + map.put("first_day_of_the_previous_month", firstDayOfThePreviousMonth); + return map; + } +} +``` + +The previous example makes use of a few different things: + +* `sqlSessionFactory`: You can specify your own sessionFactory to the reader, it might be useful if you want to read from several databases. + +* `queryId`: If the base code have several tables or databases to read from, and that you have different queries, it might be interesting to use different mapper files with different namespaces. + so when referring to the query, don't forget about the namespace of the mapper file. + +* `parameterValues`: You can pass additional parameters via this map, the example above uses a map that is build by spring using a SpEL expression taking values from the `jobExecutionContext`. + The keys of the map will be used by MyBatis in the mapper file (ex: *yesterday* could be used as `#{yesterday,jdbcType=TIMESTAMP}`). + Note that the map and the reader are both built in the `step` scope in order to be able to use the Spring EL expression with the `jobExecutionContext`. + Also if MyBatis type handlers are correctly configured you can pass custom instances like the parameters of this map that are JodaTime dates. + +* `pageSize`: If the batch flow is configured with chunk size, it is relevant to pass this information to the reader as well, which is done via this property. + +## MyBatisCursorItemReader + +This bean is an `ItemReader` that reads records from a database using a cursor. + +NOTE +To use this bean you need at least MyBatis 3.4.0 or a newer version. + +It executes the query specified as the `setQueryId` property to retrieve requested data by using the method `selectCursor()`. +Each time a `read()` method is called it will return the next element of the cursor until no more elements are left. + +The reader will use a separate connection so the select statement does no participate in any transactions created as part of the step processing. + +When using the cursor you can just execute a regular query: + +```xml + +``` + +Follows below a sample configuration snippet: + +```xml + + + + +``` + +```java +@Configuration +public class BatchAppConfig { + @Bean + public MyBatisCursorItemReader reader() { + return new MyBatisCursorItemReaderBuilder() + .sqlSessionFactory(sqlSessionFactory()) + .queryId("com.my.name.space.batch.EmployeeMapper.getEmployee") + .build(); + } +} +``` + +## MyBatisBatchItemWriter + +It is an `ItemWriter` that uses the batching features from `SqlSessionTemplate` to execute a batch of statements for all items provided. +The `SqlSessionFactory` needs to be configured with a `BATCH` executor. + +When `write()` is called it executes the mapped statement indicated in the property `statementId`. It is expected that `write()` is called inside a transaction. + +Follows below a sample configuration snippet: + +```xml + + + + +``` + +```java +@Configuration +public class BatchAppConfig { + @Bean + public MyBatisBatchItemWriter writer() { + return new MyBatisBatchItemWriterBuilder() + .sqlSessionFactory(sqlSessionFactory()) + .statementId("com.my.name.space.batch.EmployeeMapper.updateEmployee") + .build(); + } +} +``` + +**Converting a item that read using ItemReader to an any parameter object:** + +By default behavior, the `MyBatisBatchItemWriter` passes a item that read using `ItemReader` (or convert by `ItemProcessor`) to the MyBatis(`SqlSession#update()`) as the parameter object. +If you want to customize a parameter object that passes to the MyBatis, you can realize to use the `itemToParameterConverter` option. +For example using `itemToParameterConverter` option, you can passes any objects other than the item object to the MyBatis. +Follows below a sample: + +At first, you create a custom converter class (or factory method). The following sample uses a factory method. + +```java +public class ItemToParameterMapConverters { + public static Converter> createItemToParameterMapConverter(String operationBy, LocalDateTime operationAt) { + return item -> { + Map parameter = new HashMap<>(); + parameter.put("item", item); + parameter.put("operationBy", operationBy); + parameter.put("operationAt", operationAt); + return parameter; + }; + } +} +``` + +At next, you write a sql mapping. + +```xml + +``` + +At last, you configure the MyBatisBatchItemWriter. + +```java +@Configuration +public class BatchAppConfig { + @Bean + public MyBatisBatchItemWriter writer() throws Exception { + return new MyBatisBatchItemWriterBuilder() + .sqlSessionFactory(sqlSessionFactory()) + .statementId("org.mybatis.spring.sample.mapper.PersonMapper.createPerson") + .itemToParameterConverter(createItemToParameterMapConverter("batch_java_config_user", LocalDateTime.now())) + .build(); + } +} +``` + +```xml + + + + + + + + + + +``` + +**Writing to different tables using composite writers (with some caveats):** + +This technique can only be used with MyBatis 3.2+, as there was an [issue](http://code.google.com/p/mybatis/issues/detail?id=741) in previous versions that made the writer misbehave. + +If the batch needs to write complex data, like records with associations, or even to different databases, then it is possible to work around the fact that insert statements only insert in one table. +In order to make it happen the batch have to prepare the *Item* to be written by the writer. +However depending on the constraints, opportunities or insight on the processed data it might be interesting to use the following technique. +The following trick can work on items with simple associations or just with unrelated tables. + +In a processor craft the Spring Batch Item in such way it will *hold* all the different records. +Suppose for each Item there is an *Interaction* that have one association *InteractionMetadata*, +and two non associated rows *VisitorInteraction* and *CustomerInteraction*, the holder object will look like: + +```java +public class InteractionRecordToWriteInMultipleTables { + private final VisitorInteraction visitorInteraction; + private final CustomerInteraction customerInteraction; + private final Interaction interaction; + // ... +} +``` +```java +public class Interaction { + private final InteractionMetadata interactionMetadata; +} +``` + +Then in the spring configuration there will be a `CompositeItemWriter` that will use delegate writers specifically configured for each kind of records. +Note that as the *InteractionMetadata* is an association in the example it will need to be written first so that Interaction can have the updated key. + +```xml + + + + + + + + + + + + +``` + +```java +@Configuration +public class BatchAppConfig { + @Bean + public CompositeItemWriter interactionsItemWriter() { + CompositeItemWriter compositeItemWriter = new CompositeItemWriter(); + List> writers = new ArrayList<>(4); + writers.add(visitorInteractionsWriter()); + writers.add(customerInteractionsWriter()); + writers.add(interactionMetadataWriter()); + writers.add(interactionWriter()); + compositeItemWriter.setDelegates(writers); + return compositeItemWriter; + } +} +``` + +Then each delegate writer will be configured as needed; for example for *Interaction* and *InteractionMetadata*: + +```xml + +``` +```xml + +``` + +Same as the reader the `statementId` can refer to the statement with the prefixed namespace. + +Now in the mapper file the statement have to be crafted for each kind of records in the following way: + +```xml + + + +``` +```xml + + + +``` + +What's happening is that first the `insertInteractionMetadata` will be called, and the update statement is configured to return the ids created by the jdbc driver (`keyProperty` and `keyColumn`). +As the `InteractionMetadata` object were updated by this query the next query can be used to write the parent object `Interaction` via `insertInteraction`. + +***However note that JDBC drivers don't behave the same in this regard. At the time of this writing the H2 driver 1.3.168 will only return the latest index even in BATCH mode (see `org.h2.jdbc.JdbcStatement#getGeneratedKeys`), +while the MySQL JDBC driver will behave as expected and return all the IDs.*** diff --git a/src/site/markdown/boot.md b/src/site/markdown/boot.md new file mode 100644 index 0000000000..678db5d753 --- /dev/null +++ b/src/site/markdown/boot.md @@ -0,0 +1,4 @@ + +# Using Spring Boot + +Please see the [MyBatis Spring-boot-starter](http://www.mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure) sub project docs for details. diff --git a/src/site/markdown/factorybean.md b/src/site/markdown/factorybean.md new file mode 100644 index 0000000000..cf403649f8 --- /dev/null +++ b/src/site/markdown/factorybean.md @@ -0,0 +1,100 @@ + +# SqlSessionFactoryBean + +In base MyBatis, the `SqlSessionFactory` is built using `SqlSessionFactoryBuilder`. In MyBatis-Spring, `SqlSessionFactoryBean` is used instead. + +## Setup + +To create the factory bean, put the following in the Spring XML configuration file: + +```xml + + + +``` +Note that `SqlSessionFactoryBean` implements Spring's `FactoryBean` interface see [the Spring documentation(Core Technologies -Customizing instantiation logic with a FactoryBean-)](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-extension-factorybean)). +This means that the bean Spring ultimately creates is **not** the `SqlSessionFactoryBean` itself, but what the factory returns as a result of the `getObject()` call on the factory. +In this case, Spring will build an `SqlSessionFactory` for you at application startup and store it with the name `sqlSessionFactory`. +In Java, the equivalent code would be: + +```java +@Configuration +public class MyBatisConfig { + @Bean + public SqlSessionFactory sqlSessionFactory() { + SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); + factoryBean.setDataSource(dataSource()); + return factoryBean.getObject(); + } +} +``` + +In normal MyBatis-Spring usage, you will not need to use `SqlSessionFactoryBean` or the corresponding `SqlSessionFactory` directly. +Instead, the session factory will be injected into `MapperFactoryBean`s or other DAOs that extend `SqlSessionDaoSupport`. + +## Properties + +`SqlSessionFactory` has a single required property, the JDBC `DataSource`. This can be any `DataSource` and should be configured just like any other Spring database connection. + +One common property is `configLocation` which is used to specify the location of the MyBatis XML configuration file. +One case where this is needed is if the base MyBatis configuration needs to be changed. Usually this will be `` or `` sections. + +Note that this config file does **not** need to be a complete MyBatis config. Specifically, any environments, data sources and MyBatis transaction managers will be **ignored**. +`SqlSessionFactoryBean` creates its own, custom MyBatis `Environment` with these values set as required. + +Another reason to require a config file is if the MyBatis mapper XML files are not in the same classpath location as the mapper classes. With this configuration, there are two options. +This first is to manually specify the classpath of the XML files using a `` section in the MyBatis config file. A second option is to use the `mapperLocations` property of the factory bean. + +The `mapperLocations` property takes a list of resource locations. This property can be used to specify the location of MyBatis XML mapper files. +The value can contain Ant-style patterns to load all files in a directory or to recursively search all paths from a base location. + +For example: + +```xml + + + + +``` + +This will load all the MyBatis mapper XML files in the `sample.config.mappers` package and its sub-packages from the classpath. + +One property that may be required in an environment with container managed transactions is `transactionFactoryClass`. Please see the relevant section in the Transactions chapter. + +In case you are using the multi-db feature you will need to set the `databaseIdProvider` property: + +```xml + + + + sqlserver + db2 + oracle + mysql + + + +``` +```xml + + + + + +``` + +NOTE +Since 1.3.0, `configuration` property has been added. It can be specified a `Configuration` instance directly without MyBatis XML configuration file. + +For example: + +```xml + + + + + + + + +``` diff --git a/src/site/markdown/getting-started.md b/src/site/markdown/getting-started.md new file mode 100644 index 0000000000..c33f7f393d --- /dev/null +++ b/src/site/markdown/getting-started.md @@ -0,0 +1,100 @@ + +# Getting Started + +This chapter will show you in a few steps how to install and setup MyBatis-Spring and how to build a simple transactional application. + +## Installation + +To use the MyBatis-Spring module, you just need to include the `mybatis-spring-${project.version}.jar` file and its dependencies in the classpath. + +If you are using Maven just add the following dependency to your pom.xml: + +```xml + + org.mybatis + mybatis-spring + ${project.version} + +``` + +## Quick Setup + +To use MyBatis with Spring you need at least two things defined in the Spring application context: +an `SqlSessionFactory` and at least one mapper interface. + +In MyBatis-Spring, an `SqlSessionFactoryBean` is used to create an `SqlSessionFactory`. To configure the factory bean, put the following in the Spring configuration file: + +```xml + + + +``` + +```java +@Configuration +public class MyBatisConfig { + @Bean + public SqlSessionFactory sqlSessionFactory() throws Exception { + SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); + factoryBean.setDataSource(dataSource()); + return factoryBean.getObject(); + } +} +``` + +Notice that the `SqlSessionFactory` requires a `DataSource`. This can be any `DataSource` and should be configured just like any other Spring database connection. + +Assume you have a mapper interface defined like the following: + +```java +public interface UserMapper { + @Select("SELECT * FROM users WHERE id = #{userId}") + User getUser(@Param("userId") String userId); +} +``` + +This interface is added to Spring using a `MapperFactoryBean` like the following: + +```xml + + + + +``` + +Note that the mapper class specified **must** be an interface, not an actual implementation class. In this example, annotations are used to specify the SQL, but a MyBatis mapper XML file could also be used. + +Once configured, you can inject mappers directly into your business/service objects in the same way you inject any other Spring bean. +The `MapperFactoryBean` handles creating an `SqlSession` as well as closing it. +If there is a Spring transaction in progress, the session will also be committed or rolled back when the transaction completes. +Finally, any exceptions will be translated into Spring `DataAccessException`s. + +If you use the Java Configuration: + +```java +@Configuration +public class MyBatisConfig { + @Bean + public UserMapper userMapper() throws Exception { + SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory()); + return sqlSessionTemplate.getMapper(UserMapper.class); + } +} +``` + +Calling MyBatis data methods is now only one line of code: + +```java +public class FooServiceImpl implements FooService { + + private final UserMapper userMapper; + + public FooServiceImpl(UserMapper userMapper) { + this.userMapper = userMapper; + } + + public User doSomeBusinessStuff(String userId) { + return this.userMapper.getUser(userId); + } +} +``` diff --git a/src/site/markdown/index.md b/src/site/markdown/index.md new file mode 100644 index 0000000000..c7b577c2ff --- /dev/null +++ b/src/site/markdown/index.md @@ -0,0 +1,54 @@ + +# Introduction + +## What is MyBatis-Spring? + +MyBatis-Spring integrates MyBatis seamlessly with Spring. +This library allows MyBatis to participate in Spring transactions, takes care of building MyBatis mappers and `SqlSession`s and inject them into other beans, translates MyBatis exceptions into Spring `DataAccessException`s, and finally, it lets you build your application code free of dependencies on MyBatis, Spring or MyBatis-Spring. + +## Motivation + +Spring version 2 only supports iBATIS version 2. An attempt was made to add MyBatis 3 support into Spring 3 (see the Spring Jira [issue](https://jira.springsource.org/browse/SPR-5991). +Unfortunately, Spring 3 development ended before MyBatis 3 was officially released. Because the Spring team did not want to release with code based on a non-released version of MyBatis, official Spring support would have to wait. +Given the interest in Spring support for MyBatis, the MyBatis community decided it was time to reunite the interested contributors and add Spring integration as a community sub-project of MyBatis instead. + +## Requirements + +Before starting with MyBatis-Spring integration, it is very important that you are familiar with both MyBatis and Spring terminology. +This document does not attempt to provide background information or basic setup and configuration tutorials for either MyBatis or Spring. + +MyBatis-Spring requires following versions: + +| MyBatis-Spring | MyBatis | Spring Framework | Spring Batch | Java | +| --- | --- | --- | --- | --- | +| **2.0** | 3.5+ | 5.0+ | 4.0+ | Java 8+ | +| **1.3** | 3.4+ | 3.2.2+ | 2.1+ | Java 6+ | + +## Acknowledgements + +A special thanks goes to all the special people who made this project a reality (in alphabetical order): Eduardo Macarron, Hunter Presnall and Putthiphong Boonphong for the coding, +testing and documentation; Andrius Juozapaitis, Giovanni Cuccu, Mike Lanyon, Raj Nagappan and Tomas Pinos for their contributions; and Simone Tripodi for finding everyone and bringing them all back to the project under MyBatis ;) +Without them, this project wouldn't exist. + +## Help make this documentation better… + +If you find this documentation lacking in any way, or missing documentation for a feature, then the best thing to do is learn about it and then write the documentation yourself! + +Sources of this manual are available in markdown format at [project's Git](https://github.com/mybatis/spring/tree/master/src/site) Fork the repository, update them and send a pull request. + +You’re the best author of this documentation, people like you have to read it! + +## Translations + +Users can read about MyBatis-Spring in the following translations: + + + +Do you want to read about MyBatis in your own native language? Fill an issue providing patches with your mother tongue documentation! + diff --git a/src/site/markdown/mappers.md b/src/site/markdown/mappers.md new file mode 100644 index 0000000000..7153f7385d --- /dev/null +++ b/src/site/markdown/mappers.md @@ -0,0 +1,182 @@ + +# Injecting Mappers + +Rather than code data access objects (DAOs) manually using `SqlSessionDaoSupport` or `SqlSessionTemplate`, Mybatis-Spring can create a thread safe mapper that you can inject directly into other beans: + +```xml + + + +``` + +Once injected, the mapper is ready to be used in application logic: + +```java +public class FooServiceImpl implements FooService { + + private final UserMapper userMapper; + + public FooServiceImpl(UserMapper userMapper) { + this.userMapper = userMapper; + } + + public User doSomeBusinessStuff(String userId) { + return this.userMapper.getUser(userId); + } +} +``` + +Notice that there are no `SqlSession` or MyBatis references in this code. Nor is there any need to create, open or close the session, MyBatis-Spring will take care of that. + + +## Registering a mapper + +The way you register a mapper depends on whether you are using a classic XML configuration or the new 3.0+ Java Config (a.k.a. `@Configuration`). + +### With XML Config + +A mapper is registered to Spring by including a `MapperFactoryBean` in your XML config file like follows: + +```xml + + + + +``` + +If the UserMapper has a corresponding MyBatis XML mapper file in the same classpath location as the mapper interface, it will be parsed automatically by the `MapperFactoryBean`. +There is no need to specify the mapper in a MyBatis configuration file unless the mapper XML files are in a different classpath location. See the `SqlSessionFactoryBean`'s `[configLocation](factorybean.html)` property for more information. + +Note that `MapperFactoryBean` requires either an `SqlSessionFactory` or an `SqlSessionTemplate`. These can be set through the respective `sqlSessionFactory` and `sqlSessionTemplate` properties. +If both properties are set, the `SqlSessionFactory` is ignored. Since the `SqlSessionTemplate` is required to have a session factory set, that factory will be used by `MapperFactoryBean`. + +### With Java Config + +```java +@Configuration +public class MyBatisConfig { + @Bean + public MapperFactoryBean userMapper() throws Exception { + MapperFactoryBean factoryBean = new MapperFactoryBean<>(UserMapper.class); + factoryBean.setSqlSessionFactory(sqlSessionFactory()); + return factoryBean; + } +} +``` + + +## Scanning for mappers + +There is no need to register all your mappers one by one. Instead, you can let MyBatis-Spring scan your classpath for them. + +There are three different ways to do it: + +* Using the `` element. +* Using the annotation `@MapperScan` +* Using a classic Spring xml file and registering the `MapperScannerConfigurer` + +Both `` and `@MapperScan` are features introduced in MyBatis-Spring 1.2.0. `@MapperScan` requires Spring 3.1+. + +Since 2.0.2, mapper scanning feature support an option (`lazy-initialization`) that control lazy initialization enabled/disabled of mapper bean. +The motivation for adding this option is supporting a lazy initialization control feature supported by Spring Boot 2.2. The default of this option is `false` (= not use lazy initialization). +If developer want to use lazy initialization for mapper bean, it should be set to the `true` expressly. + +IMPORTANT +If use the lazy initialization feature, the developer need to understand following limitations. If any of following conditions are matches, usually the lazy initialization feature cannot use on your application. + +* When refers to the statement of **other mapper** using ``(`@One`) and ``(`@Many`) +* When includes to the fragment of **other mapper** using `` +* When refers to the cache of **other mapper** using ``(`@CacheNamespaceRef`) +* When refers to the result mapping of **other mapper** using `]]> - -

Follows below a sample configuration snippet:

- - - - -
]]> - - reader() { - return new MyBatisPagingItemReaderBuilder() - .sqlSessionFactory(sqlSessionFactory()) - .queryId("com.my.name.space.batch.EmployeeMapper.getEmployee") - .build(); -}]]> - -

Explaining a more complex example:

- - - - - - - - -]]> - - dateBasedCriteriaReader( - @Value("#{@datesParameters}") Map datesParameters) throws Exception { - return new MyBatisPagingItemReaderBuilder() - .sqlSessionFactory(batchReadingSessionFactory()) - .queryId("com.my.name.space.batch.ExampleMapper.queryUserInteractionsOnSpecificTimeSlot") - .parameterValues(datesParameters) - .pageSize(200) - .build(); -} - -@StepScope -@Bean -public Map datesParameters( - @Value("#{jobExecutionContext['EXTRACTION_START_DATE']}") LocalDate yesterday, - @Value("#{jobExecutionContext['TODAY_DATE']}") LocalDate today, - @Value("#{jobExecutionContext['FIRST_DAY_OF_THE_MONTH_DATE']}") LocalDate firstDayOfTheMonth, - @Value("#{jobExecutionContext['FIRST_DAY_OF_THE_PREVIOUS_MONTH_DATE']}") LocalDate firstDayOfThePreviousMonth) { - Map map = new HashMap<>(); - map.put("yesterday", yesterday); - map.put("today", today); - map.put("first_day_of_the_month", firstDayOfTheMonth); - map.put("first_day_of_the_previous_month", firstDayOfThePreviousMonth); - return map; -}]]> - -

- The previous example makes use of a few different things: -

- -
    -
  • sqlSessionFactory: You can specify your own sessionFactory to the reader, it might be - useful if you want to read from several databases.
  • -
  • queryId: If the base code have several tables or databases to read from, and that you have different - queries, it might be interesting to use different mapper files with different namespaces. - so when referring to the query, don't forget about the namespace of the mapper file.
  • -
  • parameterValues: You can pass additional parameters via this map, the example above uses - a map that is build by spring using a SpEL expression taking values from the jobExecutionContext. - The keys of the map will be used by MyBatis in the mapper file (ex: - yesterday could be used as #{yesterday,jdbcType=TIMESTAMP}). - Note that the map and the reader are both built in the step scope in order to be able to use - the Spring EL expression with the jobExecutionContext. Also if MyBatis type handlers - are correctly configured you can pass custom instances like the parameters of this map that are JodaTime - dates.
  • -
  • pageSize: If the batch flow is configured with chunk size, it is relevant to pass this - information to the reader as well, which is done via this property.
  • -
- - - - -

- This bean is an ItemReader that reads records from a database using a cursor. -

- -

- NOTE To use this bean you need at least MyBatis 3.4.0 or a newer version. -

- -

- It executes the query specified as the setQueryId property to retrieve requested data - by using the method selectCursor(). - Each time a read() method is called it will return the next element of the cursor until no more - elements are left. -

- -

- The reader will use a separate connection so the select statement does no participate in any transactions created - as part of the step processing. -

- -

When using the cursor you can just execute a regular query:

- - SELECT id, name, job FROM employees ORDER BY id ASC -]]> - -

Follows below a sample configuration snippet:

- - - - -
]]> - - reader() { - return new MyBatisCursorItemReaderBuilder() - .sqlSessionFactory(sqlSessionFactory()) - .queryId("com.my.name.space.batch.EmployeeMapper.getEmployee") - .build(); -}]]> - - - - - -

- It is an ItemWriter that uses the batching features from SqlSessionTemplate - to execute a batch of statements for all items provided. - The SqlSessionFactory needs to be configured with a BATCH executor. -

- -

- When write() is called it executes the mapped statement indicated in the property statementId. - It is expected that write() is called inside a transaction.
-

- -

Follows below a sample configuration snippet:

- - - - -
]]> - - writer() { - return new MyBatisBatchItemWriterBuilder() - .sqlSessionFactory(sqlSessionFactory()) - .statementId("com.my.name.space.batch.EmployeeMapper.updateEmployee") - .build(); -}]]> - -

Converting a item that read using ItemReader to an any parameter object:

- -

- By default behavior, the MyBatisBatchItemWriter passes a item that read using ItemReader - (or convert by ItemProcessor) to the MyBatis(SqlSession#update()) as the parameter object. - If you want to customize a parameter object that passes to the MyBatis, you can realize to use the itemToParameterConverter option. - For example using itemToParameterConverter option, you can passes any objects other than the item object to the MyBatis. - Follows below a sample: -

- -

- At first, you create a custom converter class (or factory method). The following sample uses a factory method. -

- - Converter> createItemToParameterMapConverter(String operationBy, LocalDateTime operationAt) { - return item -> { - Map parameter = new HashMap<>(); - parameter.put("item", item); - parameter.put("operationBy", operationBy); - parameter.put("operationAt", operationAt); - return parameter; - }; -}]]> - -

- At next, you write a sql mapping. -

- - - insert into persons (first_name, last_name, operation_by, operation_at) - values(#{item.firstName}, #{item.lastName}, #{operationBy}, #{operationAt}) -]]> - -

- At last, you configure the MyBatisBatchItemWriter. -

- - writer() throws Exception { - return new MyBatisBatchItemWriterBuilder() - .sqlSessionFactory(sqlSessionFactory()) - .statementId("org.mybatis.spring.sample.mapper.PersonMapper.createPerson") - .itemToParameterConverter(createItemToParameterMapConverter("batch_java_config_user", LocalDateTime.now())) - .build(); -}]]> - - - - - - - - - - - - -]]> - -

Writing to different tables using composite writers (with some caveats):

- -

This technique can only be used with MyBatis 3.2+, as there was an - issue in previous - versions that made the writer misbehave. -

- -

If the batch needs to write complex data, like records with associations, or even to different databases, then - it is possible to work around the fact that insert statements only insert in one table. In order to make it - happen the batch have to prepare the Item to be written by the writer. However depending on the - constraints, opportunities or insight on the processed data it might be interesting to use the following technique. - The following trick can work on items with simple associations or just with unrelated tables. -

- -

In a processor craft the Spring Batch Item in such way it will hold all the different records. - Suppose for each Item there is an Interaction that have one association - InteractionMetadata, and two non associated rows VisitorInteraction and - CustomerInteraction, the holder object will look like: -

- - - -

Then in the spring configuration there will be a CompositeItemWriter that will use delegate - writers specifically configured for each kind of records. Note that as the InteractionMetadata is - an association in the example it will need to be written first so that Interaction can have the updated key. -

- - - - - - - - - - - - -
]]> - - interactionsItemWriter() { - CompositeItemWriter compositeItemWriter = new CompositeItemWriter(); - List> writers = new ArrayList<>(4); - writers.add(visitorInteractionsWriter()); - writers.add(customerInteractionsWriter()); - writers.add(interactionMetadataWriter()); - writers.add(interactionWriter()); - compositeItemWriter.setDelegates(writers); - return compositeItemWriter; -}]]> - -

Then each delegate writer will be configured as needed; for example for Interaction and - InteractionMetadata: -

- - -]]> - -

Same as the reader the statementId can refer to the statement with the prefixed namespace.

- -

Now in the mapper file the statement have to be crafted for each kind of records in the following way:

- - - - - - -]]> - -

What's happening is that first the insertInteractionMetadata will be called, and the update - statement is configured to return the ids created by the jdbc driver (keyProperty and keyColumn). - As the InteractionMetadata object were updated by this query the next query can be used to write the parent - object Interaction via insertInteraction. -

- -

However note that JDBC drivers don't behave the same in this regard. At the time of this writing - the H2 driver 1.3.168 will only return the latest index even in BATCH mode (see org.h2.jdbc.JdbcStatement#getGeneratedKeys), - while the MySQL JDBC driver will behave as expected and return all the IDs. -

- - - - diff --git a/src/site/xdoc/boot.xml b/src/site/xdoc/boot.xml deleted file mode 100644 index fd430114c4..0000000000 --- a/src/site/xdoc/boot.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - MyBatis-Spring | Spring Boot - Eduardo Macarron - - - -
-

- Please see the MyBatis Spring-boot-starter - subproject docs for details. -

-
- -
diff --git a/src/site/xdoc/factorybean.xml b/src/site/xdoc/factorybean.xml deleted file mode 100644 index 16c3f98444..0000000000 --- a/src/site/xdoc/factorybean.xml +++ /dev/null @@ -1,224 +0,0 @@ - - - - - - MyBatis-Spring | SqlSessionFactoryBean - Hunter Presnall - Eduardo Macarron - - - -
-

- In base MyBatis, the SqlSessionFactory is built using - SqlSessionFactoryBuilder. In MyBatis-Spring, - SqlSessionFactoryBean is used instead. -

- - -

- To create the factory bean, put the following in the Spring XML - configuration file: -

- - -]]> -

- Note that - SqlSessionFactoryBean - implements Spring's - FactoryBean - interface (see the Spring documentation(Core Technologies -Customizing instantiation logic with a FactoryBean-)). - This means that the bean Spring ultimately creates is - not - the - SqlSessionFactoryBean - itself, but what the - factory returns as a result of the - getObject() - call on - the factory. In this case, Spring will build an - SqlSessionFactory - for you at application startup and - store it with the name - sqlSessionFactory - . In Java, the - equivalent code would be: -

- - - -

- In normal MyBatis-Spring usage, you will not need to use - SqlSessionFactoryBean - or the corresponding - SqlSessionFactory - directly. Instead, the session - factory will be injected into - MapperFactoryBeans or - other DAOs that extend - SqlSessionDaoSupport - . -

-
- - - -

- SqlSessionFactory - has a single required property, the - JDBC - DataSource - . This can be any - DataSource - and should be configured just - like any other Spring database - connection. -

- -

- One common property is - configLocation - which is used to - specify the location of the MyBatis XML - configuration file. One case - where this is needed is if the base - MyBatis configuration needs to be - changed. Usually this will be - <settings> - or - <typeAliases> - sections. -

- -

- Note that this config file does - not - need to be a - complete MyBatis config. Specifically, any environments, - data sources - and MyBatis transaction managers will be - ignored - . - SqlSessionFactoryBean - creates its own, custom MyBatis - Environment - with these values set as required. -

- -

- Another reason to require a config file is if the MyBatis mapper XML - files are not in the same classpath location as the mapper classes. - With - this configuration, there are two options. This first is to - manually - specify the classpath of the XML files using a - <mappers> - section in the MyBatis config - file. A second option is to use the - mapperLocations - property of the factory bean. -

- -

- The - mapperLocations - property takes a list of resource - locations. This property can be - used to specify the location of MyBatis - XML mapper files. The value - can contain Ant-style patterns to load all - files in a directory or to - recursively search all paths from a base - location. For example: -

- - - - -]]> - -

- This will load all the MyBatis mapper XML files in the - sample.config.mappers package and its sub-packages from the - classpath. -

- -

- One property that may be required in an environment with container - managed transactions is - transactionFactoryClass - . - Please see the relevant section in the - Transactions chapter. -

- -

- In case you are using the multi-db feature you will need to set the databaseIdProvider property: -

- - - - - sqlserver - db2 - oracle - mysql - - - - - - - - -]]> - -

- NOTE - Since 1.3.0, configuration property has been added. - It can be specified a Configuration instance directly without MyBatis XML configuration file. - For example: -

- - - - - - - - -]]> - -
-
- -
diff --git a/src/site/xdoc/getting-started.xml.vm b/src/site/xdoc/getting-started.xml.vm deleted file mode 100644 index c3bc9569ca..0000000000 --- a/src/site/xdoc/getting-started.xml.vm +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - MyBatis-Spring | Getting Started - Hunter Presnall - Eduardo Macarron - - - -
-

- This chapter will show you in a few steps how to install and setup - MyBatis-Spring and how to build - a simple transactional application. -

- - -

- To use the MyBatis-Spring module, you just need to include the - mybatis-spring-${project.version}.jar - file and its dependencies in the classpath. -

-

- If you are using Maven just add the following dependency - to your - pom.xml: -

- - org.mybatis - mybatis-spring - ${project.version} -]]> -
- - -

- To use MyBatis with Spring you need at least two things defined in - the - Spring application context: an - SqlSessionFactory - and - at least one mapper interface. -

- -

- In MyBatis-Spring, an - SqlSessionFactoryBean - is used to - create an - SqlSessionFactory - . To configure the - factory bean, put the following in the Spring - configuration file: -

- - - -]]> - - - -

- Notice that the - SqlSessionFactory - requires a - DataSource - . This can be any - DataSource - and should be configured just like any other Spring database - connection. -

- -

- Assume you have a mapper interface defined like the following: -

- - -

- This interface is added to Spring using a - MapperFactoryBean - like the following: -

- - - -]]> - -

- Note that the mapper class specified - must - be an - interface, not an actual implementation class. In this example, - annotations are used to specify the SQL, but a MyBatis mapper XML - file - could also be used. -

- -

- Once configured, you can inject mappers directly into your - business/service objects in the same way you inject any other Spring - bean. The MapperFactoryBean - handles creating an SqlSession - as well as closing it. If there is a Spring transaction in - progress, - the session will also be committed or rolled back when the - transaction completes. Finally, any exceptions will be translated - into Spring DataAccessExceptions. -

- -

- If you use the Java Configuration: -

- - - -

- Calling MyBatis data methods is now only one line of code: -

- -
-
- -
diff --git a/src/site/xdoc/index.xml b/src/site/xdoc/index.xml deleted file mode 100644 index c74c1048d5..0000000000 --- a/src/site/xdoc/index.xml +++ /dev/null @@ -1,169 +0,0 @@ - - - - - - MyBatis-Spring | Introduction - Hunter Presnall - Eduardo Macarron - - - -
- -

- MyBatis-Spring integrates MyBatis seamlessly with Spring. - This library allows MyBatis to participate in Spring transactions, takes care of - building MyBatis mappers and SqlSessions and inject them into other beans, - translates MyBatis exceptions into Spring DataAccessExceptions, - and finally, it lets you build your application code free of - dependencies on MyBatis, Spring or MyBatis-Spring. -

-
- - -

- Spring version 2 only supports iBATIS version 2. An attempt was made to - add MyBatis 3 support into Spring 3 (see the Spring Jira - issue). - Unfortunately, Spring 3 development ended before MyBatis 3 was - officially released. Because the Spring team did not want to release with - code based on a non-released version of MyBatis, official Spring support - would have to wait. Given the interest in Spring support for MyBatis, - the MyBatis community decided it was time to reunite the interested contributors - and add Spring integration as a community sub-project of MyBatis instead. -

-
- - -

- Before starting with MyBatis-Spring integration, it is very important - that you are familiar with both MyBatis and Spring terminology. This - document does not attempt to provide background information or basic - setup and configuration tutorials for either MyBatis or Spring. -

-

- MyBatis-Spring requires following versions: -

- - - - - - - - - - - - - - - - - - - - - - - - - - -
- MyBatis-Spring - - MyBatis - - Spring Framework - - Spring Batch - - Java -
- 2.0 - - 3.5+ - - 5.0+ - - 4.0+ - - Java 8+ -
- 1.3 - - 3.4+ - - 3.2.2+ - - 2.1+ - - Java 6+ -
-
- - -

- A special thanks goes to all the special people who made this project - a reality (in alphabetical order): Eduardo Macarron, Hunter Presnall - and Putthiphong Boonphong for the coding, testing and documentation; - Andrius Juozapaitis, Giovanni Cuccu, Mike Lanyon, Raj Nagappan and Tomas Pinos - for their contributions; and Simone Tripodi for finding everyone and - bringing them all back to the project under MyBatis ;) Without them, - this project wouldn't exist. -

-
- - -

- If you find this documentation lacking in any way, or missing - documentation for a feature, then the best thing to do is learn - about it and then write the documentation yourself! -

-

- Sources of this manual are available in xdoc format at - project's Git - Fork the repository, update them and send a pull request. -

-

- You’re the best author of this documentation, people like you have - to read it! -

-
- - -

Users can read about MyBatis-Spring in the following translations:

- -

Do you want to read about MyBatis in your own native language? Fill an issue providing patches with your - mother tongue documentation!

-
-
- - -
diff --git a/src/site/xdoc/mappers.xml b/src/site/xdoc/mappers.xml deleted file mode 100644 index 6287690314..0000000000 --- a/src/site/xdoc/mappers.xml +++ /dev/null @@ -1,295 +0,0 @@ - - - - - - MyBatis-Spring | Injecting Mappers - Hunter Presnall - Eduardo Macarron - - - -
-

- Rather than code data access objects (DAOs) manually using - SqlSessionDaoSupport or - SqlSessionTemplate, Mybatis-Spring can create a - thread safe mapper that you can inject directly into other beans: -

- - - -]]> - -

- Once injected, the mapper is ready to be used in application logic: -

- -

- Notice that there are no SqlSession or MyBatis - references in this code. Nor is there any need to create, open or close - the session, MyBatis-Spring will take care of that. -

- - -

- The way you register a mapper depends on whether you are using a classic XML configuration - or the new 3.0+ Java Config (a.k.a. @Configuration).

- -

With XML Config

- -

- A mapper is registered to Spring by including a MapperFactoryBean in your XML - config file like follows: -

- - - -]]> - -

- If the UserMapper has a corresponding MyBatis XML mapper file - in the same classpath location as the mapper interface, it will be - parsed automatically by the MapperFactoryBean. There - is no need to specify the mapper in a MyBatis configuration file unless - the mapper XML files are in a different classpath location. See the - SqlSessionFactoryBean's - configLocation - property for more information. -

- -

- Note that MapperFactoryBean requires either an - SqlSessionFactory or an SqlSessionTemplate. - These can be set through the respective sqlSessionFactory and - sqlSessionTemplate properties. - If both properties are set, the SqlSessionFactory is ignored. - Since the SqlSessionTemplate is required to have a session - factory set, that factory will be used by MapperFactoryBean. -

- -

With Java Config

- - userMapper() throws Exception { - MapperFactoryBean factoryBean = new MapperFactoryBean<>(UserMapper.class); - factoryBean.setSqlSessionFactory(sqlSessionFactory()); - return factoryBean; -}]]> -
- - -

- There is no need to register all your mappers one by one. - Instead, you can let MyBatis-Spring scan your classpath for them. -

- -

- There are three different ways to do it: -

-
    -
  • Using the <mybatis:scan/> element.
  • -
  • Using the annotation @MapperScan
  • -
  • Using a classic Spring xml file and registering the MapperScannerConfigurer
  • -
- -

Both <mybatis:scan/> and @MapperScan are features introduced in MyBatis-Spring 1.2.0. - @MapperScan requires Spring 3.1+.

- -

- Since 2.0.2, mapper scanning feature support a option (lazy-initialization) - that control lazy initialization enabled/disabled of mapper bean. - The motivation for adding this option is supporting a lazy initialization control feature supported by Spring Boot 2.2. - The default of this option is false (= not use lazy initialization). - If developer want to use lazy initialization for mapper bean, it should be set to the true expressly. -

-

- IMPORTANT If use the lazy initialization feature, - the developer need to understand following limitations. If any of following conditions are matches, - usually the lazy initialization feature cannot use on your application. -

-
    -
  • When refers to the statement of other mapper using ]]>(@One) and ]]>(@Many)
  • -
  • When includes to the fragment of other mapper using ]]>
  • -
  • When refers to the cache of other mapper using ]]>(@CacheNamespaceRef)
  • -
  • When refers to the result mapping of other mapper using ]]>(@ResultMap)
  • -
- -

- NOTE However, It become possible to use it by simultaneously initializing dependent beans using @DependsOn(Spring's feature) as follow: -

- - - -

- Since 2.0.6, the develop become can specified scope of mapper using mapper scanning feature option(default-scope) - and scope annotation(@Scope, @RefreshScope, etc ...). - The motivation for adding this option is supporting the refresh scope provided by the Spring Cloud. - The default of this option is empty (= equiv to specify the singleton scope). - The default-scope apply to the mapper bean(MapperFactoryBean) when scope of scanned bean definition - is singleton(default scope) and create a scoped proxy bean for scanned mapper when final scope is not singleton. -

- -

<mybatis:scan/>

- -

- The <mybatis:scan/> XML element will search for mappers - in a very similar way than the Spring built-in element <context:component-scan/> - searches for beans. -

- -

Follows below a sample XML configuration:

- - - - - - - -]]> - -

- The base-package attribute lets you set the base package - for your mapper interface files. You can set more than one package by - using a semicolon or comma as a separator. Mappers will be searched for - recursively starting in the specified package(s). -

- -

- Notice that there is no need to specify a SqlSessionFactory or - SqlSessionTemplate as an attribute in the <mybatis:scan/> - element because it will create MapperFactoryBeans that can be autowired. - But if you are using more than one DataSource autowire may not work for you. - In this case you can use the factory-ref or - template-ref attributes to set the right bean name to use. -

- -

- <mybatis:scan/> supports filtering the mappers - created by either specifying a marker interface or an annotation. The - annotation property specifies an annotation to - search for. The marker-interface attribute specifies a - parent interface to search for. If both properties are specified, mappers - are added for interfaces that match either criteria. - By default, these two properties are null, so all interfaces in the given - base package(s) will be loaded as mappers. -

- -

- Discovered mappers will be named using Spring default naming strategy for - autodetected components (see the Spring reference document(Core Technologies -Naming autodetected components-)). - That is, if no annotation is found, it will use the uncapitalized non-qualified class - name of the mapper. But if either a @Component or a JSR-330 @Named annotation is - found it will get the name from the annotation. - Notice that you can set the annotation attribute - to org.springframework.stereotype.Component, - javax.inject.Named (if you have JSE 6) or to your own annotation - (that must be itself annotated) so the annotation will work both as a marker - and as a name provider. -

- -

- NOTE <context:component-scan/> - won't be able to scan and register mappers. Mappers are interfaces and, in order to register them to - Spring, the scanner must know how to create a MapperFactoryBean for each interface - it finds. -

- -

@MapperScan

- -

- If you are using the Spring Java Configuration (a.k.a @Configuration) you would - prefer to use the @MapperScan rather than the - <mybatis:scan/>. -

- -

The @MapperScan annotation is used as follows:

- - - -

The annotation works in the same exact way than <mybatis:scan/> we - saw in the previous section. It also lets you specify a marker interface or an annotation class - through its properties markerInterface and annotationClass. - You can also provide an specific SqlSessionFactory or SqlSessionTemplate - by using its properties sqlSessionFactory and sqlSessionTemplate. -

- -

- NOTE Since 2.0.4, If basePackageClasses or basePackages are not defined, scanning will occur from the package of the class that declares this annotation. -

- -

MapperScannerConfigurer

- -

- The MapperScannerConfigurer is a BeanDefinitionRegistryPostProcessor that - can be included in a classic xml application context as a normal bean. - To set up a MapperScannerConfigurer add the following to the Spring configuration: -

- - -]]> - -

- If you need to specify an specific sqlSessionFactory or sqlSessionTemplate - note that bean names are required, - not bean references, thus the value attribute is used instead of the - usual ref: -

- ]]> - -

- NOTE sqlSessionFactoryBean and - sqlSessionTemplateBean properties were the only option available up to MyBatis-Spring 1.0.2 - but given that the MapperScannerConfigurer runs earlier in the startup - process that PropertyPlaceholderConfigurer there were frequent errors. - For that purpose that properties have been deprecated and the new properties - sqlSessionFactoryBeanName and sqlSessionTemplateBeanName - are recommended. -

-
-
- -
diff --git a/src/site/xdoc/sample.xml b/src/site/xdoc/sample.xml deleted file mode 100644 index df1846ac85..0000000000 --- a/src/site/xdoc/sample.xml +++ /dev/null @@ -1,177 +0,0 @@ - - - - - - MyBatis-Spring | Sample Code - Eduardo Macarron - - - -
- -

- NOTE - See JPetstore 6 demo to know about how to use Spring with a full web application server. -

- -

- You can check out sample code from the MyBatis-Spring repo: -

-

- Any of the samples can be run with JUnit 5. -

-

- The sample code shows a typical design where a transactional service gets domain objects from a data access layer. -

-

- FooService.java acts as the service: -

- -

- It is a transactional bean, so when the method is called, the transaction is started - and the transaction is committed when the method ends without throwing an uncaught exception. - Notice that transactional behaviour is configured with the - @Transactional - attribute. This is not required; any other way provided by Spring can be used to demarcate - your transactions. -

-

- This service calls a data access layer built with MyBatis. This layer - consists on a just an interface UserMapper.java - that will be used with a dynamic proxy built by MyBatis at - runtime and injected into the service by Spring. -

- -

- Note that, for the sake of simplicity we used the interface UserMapper.java for the DAO scenario - where a DAO is built with an interface and a implementation though in this case it would have been more - adequate to use an interface called UserDao.java instead. -

-

- We will see different ways to find the mapper interface, register it to Spring and inject it into the service bean: -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Scenarios
Sample testDescription
- SampleMapperTest.java - - Shows you the base configuration based on a MapperFactoryBean - that will dynamically build an implementation for UserMapper -
- SampleScannerTest.java - - Shows how to use the MapperScannerConfigurer so all the mappers in a project are autodiscovered. -
- SampleSqlSessionTest.java - - Shows how to hand code a DAO using a Spring managed SqlSession - and providing your own implementation UserDaoImpl.java. -
- SampleEnableTest - - Shows how to use Spring's @Configuration with the @MapperScann annotation so - mappers are autodiscovered. -
- SampleNamespaceTest - - Shows how to use the custom MyBatis XML namespace. -
- SampleJavaConfigTest.java - - Shows how to use Spring's @Configuration to create MyBatis beans manually. -
- SampleJobJavaConfigTest.java - - Shows how to use ItemReader and ItemWriter on Spring Batch using Java Configuration. -
- SampleJobXmlConfigTest.java - - Shows how to use ItemReader and ItemWriter on Spring Batch using XML Configuration. -
-

- Please take a look at the different applicationContext.xml files to see MyBatis-Spring in action. -

- -
- -
- diff --git a/src/site/xdoc/sqlsession.xml b/src/site/xdoc/sqlsession.xml deleted file mode 100644 index 3b36295554..0000000000 --- a/src/site/xdoc/sqlsession.xml +++ /dev/null @@ -1,187 +0,0 @@ - - - - - - MyBatis-Spring | Using an SqlSession - Hunter Presnall - Eduardo Macarron - - - -
-

- In MyBatis you use the SqlSessionFactory to create an - SqlSession. Once you have a session, you use it to - execute your mapped statements, commit or rollback connections and - finally, when it is no longer needed, you close the session. With - MyBatis-Spring you don't need to use SqlSessionFactory - directly because your beans can be injected with a thread safe - SqlSession that automatically commits, rollbacks and - closes the session based on Spring's transaction configuration. -

- - -

- SqlSessionTemplate is the heart of MyBatis-Spring. - It implements SqlSession and is meant to be a drop-in replacement - for any existing use of SqlSession in your code. - SqlSessionTemplate is thread safe and can be shared - by multiple DAOs or mappers. -

- -

- When calling SQL methods, including any method from Mappers returned by - getMapper(), SqlSessionTemplate - will ensure that the SqlSession used is the one - associated with the current Spring transaction. In addition, it manages - the session life-cycle, including closing, committing or rolling back the - session as necessary. It will also translate MyBatis exceptions - into Spring DataAccessExceptions. -

- -

- SqlSessionTemplate should always - be used instead of default MyBatis implementation DefaultSqlSession - because the template can participate in Spring transactions and is thread safe for use by - multiple injected mapper classes. Switching between the two classes in the - same application can cause data integrity issues. -

- -

- A SqlSessionTemplate can be constructed - using an SqlSessionFactory as a constructor argument. -

- - -]]> - - - -

- This bean can now be injected directly in your DAO beans. You need a - SqlSession property in your bean like the following -

- -

- And inject the SqlSessionTemplate as follows -

- - -]]> - -

- SqlSessionTemplate has also a constructor that takes - an ExecutorType as an argument. This allows you to - construct, for example, a batch SqlSession by using - the following in Spring's configuration file: -

- - - -]]> - - - -

- Now all your statements will be batched so the following could be coded - in a DAO -

- users) { - for (User user : users) { - sqlSession.insert("org.mybatis.spring.sample.mapper.UserMapper.insertUser", user); - } -}]]> - -

- Note that this configuration style only needs to be used if the desired - execution method differs from the default set for the - SqlSessionFactory. -

- -

- The caveat to this form is that - there cannot be an existing transaction running with - a different ExecutorType when this method is called. Either ensure that - calls to SqlSessionTemplates with different executor - types run in a separate transaction (e.g. with PROPAGATION_REQUIRES_NEW) or - completely outside of a transaction. -

-
- - -

- SqlSessionDaoSupport is an abstract support class that - provides you with a SqlSession. Calling - getSqlSession() you will get a SqlSessionTemplate - which can then be used to execute SQL methods, like the following: -

- -

- Usually MapperFactoryBean is preferred to this class, - since it requires no extra code. But, this class is useful if you need - to do other non-MyBatis work in your DAO and concrete classes are - required. -

- -

- SqlSessionDaoSupport requires either an - sqlSessionFactory or an sqlSessionTemplate - property to be set. - If both properties are set, the sqlSessionFactory is ignored. -

- -

- Assuming a class UserDaoImpl that subclasses - SqlSessionDaoSupport, it can be configured in Spring - like the following: -

- - -]]> -
-
- -
diff --git a/src/site/xdoc/transactions.xml b/src/site/xdoc/transactions.xml deleted file mode 100644 index 12f358f780..0000000000 --- a/src/site/xdoc/transactions.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - MyBatis-Spring | Transactions - Hunter Presnall - Eduardo Macarron - - - -
-

- One of the primary reasons for using MyBatis-Spring is that it allows - MyBatis to participate in Spring transactions. Rather than create a new - transaction manager specific to MyBatis, MyBatis-Spring leverages the - existing DataSourceTransactionManager in Spring. -

-

- Once a Spring transaction manager is configured, you can configure - transactions in Spring as you normally would. Both - @Transactional annotations and AOP style - configurations are supported. A single SqlSession - object will be created and used for the duration of the transaction. This - session will be committed or rolled back as appropriate when then - transaction completes. -

-

- MyBatis-Spring will transparently manage transactions once they are set up. - There is no need for additional code in your DAO classes. -

- - -

- To enable Spring transaction processing, simply create a - DataSourceTransactionManager in your Spring - configuration file: -

- - - -]]> - - - -

- The DataSource specified can be any JDBC - DataSource you would normally - use with Spring. This includes connection pools as well as DataSources - obtained through JNDI lookups. -

-

- Note that the DataSource specified for the transaction - manager must be the same one that is used to create - the SqlSessionFactoryBean or transaction management will - not work. -

-
- - -

- If you are using a JEE container and would like Spring to participate in - container managed transactions (CMT), then Spring should be configured - with a JtaTransactionManager or one of its container - specific subclasses. The easiest way to do this is to use the Spring - transaction namespace or the JtaTransactionManagerFactoryBean: -

- ]]> - - - -

- In this configuration, MyBatis will behave like any other Spring - transactional resource configured with CMT. Spring will automatically use - any existing container transaction and attach an SqlSession to it. If no - transaction is started and one is needed based on the transaction - configuration, Spring will start a new container managed transaction. -

-

- Note that if you want to use CMT and do not want to - use Spring transaction management, you must not - configure any Spring transaction manager and you must - also configure the SqlSessionFactoryBean to use the base - MyBatis ManagedTransactionFactory: -

- - - - - -]]> - - -
- - -

- MyBatis SqlSession provides you with specific methods to handle - transactions programmatically. But when using MyBatis-Spring your beans will be - injected with a Spring managed SqlSession or a Spring managed mapper. - That means that Spring will always handle your transactions. -

-

- You cannot call SqlSession.commit(), SqlSession.rollback() - or SqlSession.close() over a Spring managed SqlSession. - If you try to do so, a UnsupportedOperationException exception - will be thrown. Note these methods are not exposed in injected mapper classes. -

-

- Regardless of your JDBC connection's autocommit setting, any execution of a - SqlSession data method or any call to a mapper - method outside a Spring transaction will be automatically committed. -

-

- If you want to control your transactions programmatically please refer to - the Spring reference document(Data Access -Programmatic transaction management-). - This code shows how to handle a transaction manually using the PlatformTransactionManager. -

- - -

- You can omit to call the commit and rollback method using the TransactionTemplate. -

- - { - userMapper.insertUser(user); - return null; -});]]> - -

- Notice that this code uses a mapper, but it will also work with a SqlSession. -

-
-
- -
diff --git a/src/site/xdoc/using-api.xml b/src/site/xdoc/using-api.xml deleted file mode 100644 index d56943590d..0000000000 --- a/src/site/xdoc/using-api.xml +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - MyBatis-Spring | Using the MyBatis API - Hunter Presnall - Eduardo Macarron - - - -
-

- With MyBatis-Spring, you can continue to directly use the MyBatis API. - Simply create an SqlSessionFactory in Spring using - SqlSessionFactoryBean and use the factory in your code. -

- - -

- Use this option with care because wrong usage may produce runtime errors or - worse, data integrity problems. Be aware of the following caveats with direct API usage: -

-
    -
  • -

    - It will not participate in any Spring transactions. -

    -
  • -
  • -

    - If the SqlSession is using a DataSource - that is also being used by a Spring transaction manager and there is currently - a transaction in progress, this code will throw an exception. -

    -
  • -
  • -

    - MyBatis' DefaultSqlSession is not thread safe. If you - inject it in your beans you will get errors. -

    -
  • -
  • -

    - Mappers created using DefaultSqlSession are not thread safe either. - If you inject them it in your beans you will get errors. -

    -
  • -
  • -

    - You must make sure that your SqlSessions - are always closed in a finally block. -

    -
  • -
-
- -
diff --git a/src/site/zh/markdown/README.md b/src/site/zh/markdown/README.md new file mode 100644 index 0000000000..823195bba3 --- /dev/null +++ b/src/site/zh/markdown/README.md @@ -0,0 +1,18 @@ +# 目录 + +此页面用于在GitHub上呈现索引。 + +> **NOTE:** +> +> 由于链接目标是在使用maven-site-plugin转换为html的假设下指定的,因此在GitHub上的呈现中有一个锚点已损坏。 + +* [简介](./index.md) +* [入门](./getting-started.md) +* [SqlSessionFactoryBean](./factorybean.md) +* [事务](./transactions.md) +* [使用 SqlSession](./sqlsession.md) +* [注入映射器](./mappers.md) +* [Spring Boot](./boot.md) +* [使用 MyBatis API](./using-api.md) +* [Spring Batch](./batch.md) +* [示例代码](./sample.md) diff --git a/src/site/zh/markdown/batch.md b/src/site/zh/markdown/batch.md new file mode 100644 index 0000000000..891ed531cb --- /dev/null +++ b/src/site/zh/markdown/batch.md @@ -0,0 +1,343 @@ + +# 使用 Spring Batch + +MyBatis-Spring 1.1.0 发布以后,提供了三个 bean 以供构建 Spring Batch 应用程序:`MyBatisPagingItemReader`、`MyBatisCursorItemReader` 和 `MyBatisBatchItemWriter`。 +而在 2.0.0 中,还提供了三个建造器(builder)类来对 Java 配置提供支持:`MyBatisPagingItemReaderBuilder`、`MyBatisCursorItemReaderBuilder` 和 `MyBatisBatchItemWriterBuilder`。 + +提示 +本章是关于 [Spring Batch](http://static.springsource.org/spring-batch/) 的,而不是关于 MyBatis 的批量 `SqlSession`。要查找关于批量 session 的更多信息,请参考 [使用 SqlSession](sqlsession.html) 一章。 + +## MyBatisPagingItemReader + +这个 bean 是一个 `ItemReader`,能够从数据库中分页地读取记录。 + +它执行 `setQueryId` 属性指定的查询来获取请求的数据。这个查询使用 `setPageSize` 属性指定了分页请求的大小,并被执行。其它的页面将在必要时被请求(例如调用 `read()` 方法时),返回对应位置上的对象。 + +reader 还提供了一些标准的请求参数。在命名查询的 SQL 中,必须使用部分或全部的参数(视乎 SQL 方言而定)来构造指定大小的结果集。这些参数是: + +* `_page`: 欲读取的页码(从 0 开始) +* `_pagesize`: 每一页的大小,也就是返回的行数 +* `_skiprows`: `_page` 和 `_pagesize` 的乘积 + +它们可以被映射成如下的 select 语句: + +```xml + +``` + +配合如下的配置样例: + +```xml + + + + +``` + +```java +@Configuration +public class BatchAppConfig { + @Bean + public MyBatisPagingItemReader reader() { + return new MyBatisPagingItemReaderBuilder() + .sqlSessionFactory(sqlSessionFactory()) + .queryId("com.my.name.space.batch.EmployeeMapper.getEmployee") + .build(); + } +} +``` + +**让我们通过一个更复杂一点的例子来阐明一切:** + +```xml + +``` +```xml + + + + + + +``` + +```java +@Configuration +public class BatchAppConfig { + @StepScope + @Bean + public MyBatisPagingItemReader dateBasedCriteriaReader( + @Value("#{@datesParameters}") Map datesParameters) throws Exception { + return new MyBatisPagingItemReaderBuilder() + .sqlSessionFactory(batchReadingSessionFactory()) + .queryId("com.my.name.space.batch.ExampleMapper.queryUserInteractionsOnSpecificTimeSlot") + .parameterValues(datesParameters) + .pageSize(200) + .build(); + } + + @StepScope + @Bean + public Map datesParameters( + @Value("#{jobExecutionContext['EXTRACTION_START_DATE']}") LocalDate yesterday, + @Value("#{jobExecutionContext['TODAY_DATE']}") LocalDate today, + @Value("#{jobExecutionContext['FIRST_DAY_OF_THE_MONTH_DATE']}") LocalDate firstDayOfTheMonth, + @Value("#{jobExecutionContext['FIRST_DAY_OF_THE_PREVIOUS_MONTH_DATE']}") LocalDate firstDayOfThePreviousMonth) { + Map map = new HashMap<>(); + map.put("yesterday", yesterday); + map.put("today", today); + map.put("first_day_of_the_month", firstDayOfTheMonth); + map.put("first_day_of_the_previous_month", firstDayOfThePreviousMonth); + return map; + } +} +``` + +上面的样例使用了几个东西: + +* `sqlSessionFactory:可以为 reader 指定你自定义的 sessionFactory,当你想从多个数据库中读取数据时尤其有用 +* `queryId`:指定在检索记录时要执行的查询的 ID,可以指定短的 ID 或是带命名空间的完整 ID。一般来说,你的应用可能从多个表或数据库中读取数据,因此会配置多个查询,可能会使用到在不同命名空间中的不同映射器。因此最好提供映射器文件的命名空间以便准确指定你想使用的查询 ID。 +* `parameterValues`:可以通过这个 map 传递多个附加的参数,上面的例子中就使用了一个由 Spring 构建的 map,并使用 SpEL 表达式从 `jobExecutionContext` 中获取信息。 + 而 map 的键将在映射器文件中被 MyBatis 使用(例如:*yesterday* 可以通过 `#{yesterday,jdbcType=TIMESTAMP}` 来读取)。注意,map 和 reader 都构建于 `step` 作用域,这样才能够在 Spring 表达式语言中使用 `jobExecutionContext`。 + 另外,如果正确配置了 MyBatis 的类型处理器,你可以将自定义的实例像参数那样传递到 map 中,比如将参数类型换成 JodaTime。 +* `pageSize`:如果批处理流配置了块大小(chunk size),需要通过此属性将块大小告知 reader。 + +## MyBatisCursorItemReader + +这个 bean 是一个 `ItemReader` ,能够通过游标从数据库中读取记录。 + +提示 +为了使用这个 bean,你需要使用 MyBatis 3.4.0 或更新的版本。 + +它执行 `setQueryId` 属性指定的查询来获取请求的数据(通过 `selectCursor()`方法)。每次调用 `read()` 方法时,将会返回游标指向的下个元素,直到没有剩余的元素了。 + +这个 reader 将会使用一个单独的数据库连接,因此 select 语句将不会参与到 step 处理中创建的任何事务。 + +当使用游标时,只需要执行普通的查询: + +```xml + +``` + +搭配以下的配置样例: + +```xml + + + + +``` +```java +@Configuration +public class BatchAppConfig { + @Bean + public MyBatisCursorItemReader reader() { + return new MyBatisCursorItemReaderBuilder() + .sqlSessionFactory(sqlSessionFactory()) + .queryId("com.my.name.space.batch.EmployeeMapper.getEmployee") + .build(); + } +} +``` + +## MyBatisBatchItemWriter + +这是一个 `ItemWriter`,通过利用 `SqlSessionTemplate` 中的批量处理功能来对给定的所有记录执行多个语句。`SqlSessionFactory` 需要被配置为 `BATCH` 执行类型。 + +当调用 `write()` 时,将会执行 `statementId` 属性中指定的映射语句。一般情况下,`write()` 应该在一个事务中进行调用。 + +下面是一个配置样例: + +```xml + + + + +``` + +```java +@Configuration +public class BatchAppConfig { + @Bean + public MyBatisBatchItemWriter writer() { + return new MyBatisBatchItemWriterBuilder() + .sqlSessionFactory(sqlSessionFactory()) + .statementId("com.my.name.space.batch.EmployeeMapper.updateEmployee") + .build(); + } +} +``` + +**将 ItemReader 读取的记录转换为任意的参数对象:** + +默认情况下,`MyBatisBatchItemWriter` 会将 `ItemReader` 读取的对象(或 `ItemProcessor` 转换过的对象) 以参数对象的形式传递给 MyBatis(`SqlSession#update()`)。 +如果你想自定义传递给 MyBatis 的参数对象,可以使用 `itemToParameterConverter` 选项。使用该选项后,可以传递任意对象给 MyBatis。 +举个例子: + +首先,创建一个自定义的转换器类(或工厂方法)。以下例子使用了工厂方法。 + +```java +public class ItemToParameterMapConverters { + public static Converter> createItemToParameterMapConverter(String operationBy, LocalDateTime operationAt) { + return item -> { + Map parameter = new HashMap<>(); + parameter.put("item", item); + parameter.put("operationBy", operationBy); + parameter.put("operationAt", operationAt); + return parameter; + }; + } +} +``` + +接下来,编写 SQL 映射。 + +```xml + +``` + +最后,配置 `MyBatisBatchItemWriter`。 + +```java +@Configuration +public class BatchAppConfig { + @Bean + public MyBatisBatchItemWriter writer() throws Exception { + return new MyBatisBatchItemWriterBuilder() + .sqlSessionFactory(sqlSessionFactory()) + .statementId("org.mybatis.spring.sample.mapper.PersonMapper.createPerson") + .itemToParameterConverter(createItemToParameterMapConverter("batch_java_config_user", LocalDateTime.now())) + .build(); + } +} +``` + +```xml + + + + + + + + + + +``` + +**使用复合 writer 对多个表进行写入(但带有问题):** + +这个小技巧只能在 MyBatis 3.2+ 以上的版本中使用,因为之前的版本中含有导致 writer 行为不正确的 [问题](http://code.google.com/p/mybatis/issues/detail?id=741)。 + +如果批量处理时需要写入复杂的数据,例如含有关联的记录,甚至是向多个数据库写入数据,你可能就需要一种办法来绕开 insert 语句只能插入到一个表中的限制。为了绕过此限制,批处理必须准备好要通过 writer 写入的*项*。 +然而,基于对被处理的数据的观察,可以尝试使用下面的方法来解决此问题。下面的方法能够工作于具有简单关联或不相关的多个表的项。 + +在这种方法中,处理 Spring Batch 项的处理器中将会*持有*各种不同的记录。假设每个项都有一个与 *InteractionMetadata* 相关联的 *Interaction*,并且还有两个不相关的行 *VisitorInteraction* 和 *CustomerInteraction*,这时候持有器(holder)看起来像这样: + +```java +public class InteractionRecordToWriteInMultipleTables { + private final VisitorInteraction visitorInteraction; + private final CustomerInteraction customerInteraction; + private final Interaction interaction; + // ... +} +``` +```java +public class Interaction { + private final InteractionMetadata interactionMetadata; +} +``` + +在 Spring 配置中要配置一个 `CompositeItemWriter`,它将会将写入操作委托到特定种类的 writer 上面去。注意 *InteractionMetadata* 在例子里面是一个关联,它需要首先被写入,这样 Interaction 才能获得更新之后的键。 + +```xml + + + + + + + + + + + + +``` + +```java +@Configuration +public class BatchAppConfig { + @Bean + public CompositeItemWriter interactionsItemWriter() { + CompositeItemWriter compositeItemWriter = new CompositeItemWriter(); + List> writers = new ArrayList<>(4); + writers.add(visitorInteractionsWriter()); + writers.add(customerInteractionsWriter()); + writers.add(interactionMetadataWriter()); + writers.add(interactionWriter()); + compositeItemWriter.setDelegates(writers); + return compositeItemWriter; + } +} +``` + +接下来需要配置每一个被委托的 writer;例如 *Interaction* 和 *InteractionMetadata* 对应的 writer。 + +```xml + +``` +```xml + +``` + +和 reader 中的一样,通过 `statementId` 属性指定对应命名空间前缀的查询。 + +而在映射器配置文件中,应该根据每种特定的记录编写特定的语句,如下所示: + +```xml + + + +``` +```xml + + + +``` + +执行的时候会怎么样呢?首先,`insertInteractionMetadata` 将会被调用,update 语句被设置为返回由 JDBC 驱动返回的主键(参考 `keyProperty` 和 `keyColumn`)。 +由于 `InteractionMetadata` 的对象被此查询更新了,下一个查询将可以通过 `insertInteraction` 开展父对象 `Interaction` 的写入工作。 + +***然而要注意,JDBC 驱动在这方面的行为并不总是与此相一致。在编写文档时,H2 的数据库驱动 1.3.168 甚至只在 BATCH 模式下返回最后的索引值(参考 `org.h2.jdbc.JdbcStatement#getGeneratedKeys`), +而 MySQL 的 JDBC 驱动则工作良好并返回所有 ID。*** diff --git a/src/site/zh/markdown/boot.md b/src/site/zh/markdown/boot.md new file mode 100644 index 0000000000..187cd06688 --- /dev/null +++ b/src/site/zh/markdown/boot.md @@ -0,0 +1,4 @@ + +# 搭配 Spring Boot + +请查看 [MyBatis Spring-boot-starter](http://www.mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure) 子项目获取更多信息。 diff --git a/src/site/zh/markdown/factorybean.md b/src/site/zh/markdown/factorybean.md new file mode 100644 index 0000000000..80dd1f51d4 --- /dev/null +++ b/src/site/zh/markdown/factorybean.md @@ -0,0 +1,94 @@ + +# SqlSessionFactoryBean + +在基础的 MyBatis 用法中,是通过 `SqlSessionFactoryBuilder` 来创建 `SqlSessionFactory` 的。而在 MyBatis-Spring 中,则使用 `SqlSessionFactoryBean` 来创建。 + +## 设置 + +要创建工厂 bean,将下面的代码放到 Spring 的 XML 配置文件中: + +```xml + + + +``` + +需要注意的是 `SqlSessionFactoryBean` 实现了 Spring 的 `FactoryBean` 接口(参见 Spring 官方文档 3.8 节 [通过工厂 bean 自定义实例化逻辑](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-extension-factorybean) )。 +这意味着由 Spring 最终创建的 bean **并不是** `SqlSessionFactoryBean` 本身,而是工厂类(`SqlSessionFactoryBean`)的 getObject() 方法的返回结果。这种情况下,Spring 将会在应用启动时为你创建 `SqlSessionFactory`,并使用 `sqlSessionFactory` 这个名字存储起来。 + +等效的 Java 代码如下: + +```java +@Configuration +public class MyBatisConfig { + @Bean + public SqlSessionFactory sqlSessionFactory() { + SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); + factoryBean.setDataSource(dataSource()); + return factoryBean.getObject(); + } +} +``` + +通常,在 MyBatis-Spring 中,你不需要直接使用 `SqlSessionFactoryBean` 或对应的 `SqlSessionFactory`。 +相反,session 的工厂 bean 将会被注入到 `MapperFactoryBean` 或其它继承于 `SqlSessionDaoSupport` 的 DAO(Data Access Object,数据访问对象)中。 + +## 属性 + +`SqlSessionFactory` 有一个唯一的必要属性:用于 JDBC 的 `DataSource`。这可以是任意的 `DataSource` 对象,它的配置方法和其它 Spring 数据库连接是一样的。 + +一个常用的属性是 `configLocation`,它用来指定 MyBatis 的 XML 配置文件路径。它在需要修改 MyBatis 的基础配置非常有用。通常,基础配置指的是 `` 或 `` 元素。 + +需要注意的是,这个配置文件并不需要是一个完整的 MyBatis 配置。确切地说,任何环境配置(``),数据源(``)和 MyBatis 的事务管理器(``)都会被**忽略**。 +`SqlSessionFactoryBean` 会创建它自有的 MyBatis 环境配置(`Environment`),并按要求设置自定义环境的值。 + +如果 MyBatis 在映射器类对应的路径下找不到与之相对应的映射器 XML 文件,那么也需要配置文件。这时有两种解决办法:第一种是手动在 MyBatis 的 XML 配置文件中的 `` 部分中指定 XML 文件的类路径;第二种是设置工厂 bean 的 `mapperLocations` 属性。 + +`mapperLocations` 属性接受多个资源位置。这个属性可以用来指定 MyBatis 的映射器 XML 配置文件的位置。属性的值是一个 Ant 风格的字符串,可以指定加载一个目录中的所有文件,或者从一个目录开始递归搜索所有目录。比如: + +```xml + + + + +``` + +这会从类路径下加载所有在 `sample.config.mappers` 包和它的子包中的 MyBatis 映射器 XML 配置文件。 + +在容器管理事务的时候,你可能需要的一个属性是 `transactionFactoryClass`。请参考事务一章的相关章节。 + +如果你使用了多个数据库,那么需要设置 `databaseIdProvider` 属性: + +```xml + + + + sqlserver + db2 + oracle + mysql + + + +``` +```xml + + + + + +``` + +提示 +自 1.3.0 版本开始,新增的 `configuration` 属性能够在没有对应的 MyBatis XML 配置文件的情况下,直接设置 `Configuration` 实例。例如: + +```xml + + + + + + + + +``` diff --git a/src/site/zh/markdown/getting-started.md b/src/site/zh/markdown/getting-started.md new file mode 100644 index 0000000000..69b7b84e40 --- /dev/null +++ b/src/site/zh/markdown/getting-started.md @@ -0,0 +1,97 @@ + +# 入门 + +本章将会以简略的步骤告诉你如何安装和配置 MyBatis-Spring,并构建一个简单的具备事务管理功能的数据访问应用程序。 + +## 安装 + +要使用 MyBatis-Spring 模块,只需要在类路径下包含 `mybatis-spring-${project.version}.jar` 文件和相关依赖即可。 + +如果使用 Maven 作为构建工具,仅需要在 pom.xml 中加入以下代码即可: + +```xml + + org.mybatis + mybatis-spring + ${project.version} + +``` + +## 快速上手 + +要和 Spring 一起使用 MyBatis,需要在 Spring 应用上下文中定义至少两样东西:一个 `SqlSessionFactory` 和至少一个数据映射器类。 + +在 MyBatis-Spring 中,可使用 `SqlSessionFactoryBean`来创建 `SqlSessionFactory`。 要配置这个工厂 bean,只需要把下面代码放在 Spring 的 XML 配置文件中: + +```xml + + + +``` + +```java +@Configuration +public class MyBatisConfig { + @Bean + public SqlSessionFactory sqlSessionFactory() throws Exception { + SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); + factoryBean.setDataSource(dataSource()); + return factoryBean.getObject(); + } +} +``` + +注意:`SqlSessionFactory` 需要一个 `DataSource`(数据源)。这可以是任意的 `DataSource`,只需要和配置其它 Spring 数据库连接一样配置它就可以了。 + +假设你定义了一个如下的 mapper 接口: + +```java +public interface UserMapper { + @Select("SELECT * FROM users WHERE id = #{userId}") + User getUser(@Param("userId") String userId); +} +``` + +那么可以通过 `MapperFactoryBean` 将接口加入到 Spring 中: + +```xml + + + + +``` + +需要注意的是:所指定的映射器类必须是一个接口,而不是具体的实现类。在这个示例中,通过注解来指定 SQL 语句,但是也可以使用 MyBatis 映射器的 XML 配置文件。 + +配置好之后,你就可以像 Spring 中普通的 bean 注入方法那样,将映射器注入到你的业务或服务对象中。`MapperFactoryBean` 将会负责 `SqlSession` 的创建和关闭。 +如果使用了 Spring 的事务功能,那么当事务完成时,session 将会被提交或回滚。最终任何异常都会被转换成 Spring 的 `DataAccessException` 异常。 + +使用 Java 代码来配置的方式如下: + +```java +@Configuration +public class MyBatisConfig { + @Bean + public UserMapper userMapper() throws Exception { + SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory()); + return sqlSessionTemplate.getMapper(UserMapper.class); + } +} +``` + +要调用 MyBatis 的数据方法,只需一行代码: + +```java +public class FooServiceImpl implements FooService { + + private final UserMapper userMapper; + + public FooServiceImpl(UserMapper userMapper) { + this.userMapper = userMapper; + } + + public User doSomeBusinessStuff(String userId) { + return this.userMapper.getUser(userId); + } +} +``` diff --git a/src/site/zh/markdown/index.md b/src/site/zh/markdown/index.md new file mode 100644 index 0000000000..74bc896278 --- /dev/null +++ b/src/site/zh/markdown/index.md @@ -0,0 +1,51 @@ + +# 简介 + +## 什么是 MyBatis-Spring? + +MyBatis-Spring 会帮助你将 MyBatis 代码无缝地整合到 Spring 中。它将允许 MyBatis 参与到 Spring 的事务管理之中,创建映射器 mapper 和 `SqlSession` 并注入到 bean 中,以及将 Mybatis 的异常转换为 Spring 的 `DataAccessException`。 +最终,可以做到应用代码不依赖于 MyBatis,Spring 或 MyBatis-Spring。 + +## 动机 + +Spring 2.0 只支持 iBatis 2.0。那么,我们就想将 MyBatis3 的支持添加到 Spring 3.0 中(参见 Spring Jira 中的 [问题](https://jira.springsource.org/browse/SPR-5991) )。不幸的是,Spring 3.0 的开发在 MyBatis 3.0 官方发布前就结束了。 +由于 Spring 开发团队不想发布一个基于未发布版的 MyBatis 的整合支持,如果要获得 Spring 官方的支持,只能等待下一次的发布了。基于在 Spring 中对 MyBatis 提供支持的兴趣,MyBatis 社区认为,应该开始召集有兴趣参与其中的贡献者们,将对 Spring 的集成作为 MyBatis 的一个社区子项目。 + +## 知识基础 + +在开始使用 MyBatis-Spring 之前,你需要先熟悉 Spring 和 MyBatis 这两个框架和有关它们的术语。这很重要——因为本手册中不会提供二者的基本内容,安装和配置教程。 + +MyBatis-Spring 需要以下版本: + +| MyBatis-Spring | MyBatis | Spring Framework | Spring Batch | Java | +| --- | --- | --- | --- | --- | +| **2.0** | 3.5+ | 5.0+ | 4.0+ | Java 8+ | +| **1.3** | 3.4+ | 3.2.2+ | 2.1+ | Java 6+ | + +## 致谢 + +特别感谢那些使本项目变为现实的人们(按字母顺序排序): Eduardo Macarron, Hunter Presnall 和 Putthiphong Boonphong 负责本项目的代码实现,测试和编写文档工作; +Andrius Juozapaitis, Giovanni Cuccu, Raj Nagappan 和 Tomas Pinos 的贡献; +而 Simone Tripodi 发现了这些人并邀请他们参与到这一个 MyBatis 子项目之中。没有他们的努力,这个项目只能沦为空谈。 + +## 帮助改进文档... + +如果你发现文档有任何的缺失,或者缺少某一个功能点的说明,最好的解决办法是先自己学习,并且为缺失的部份补上相应的文档。 + +手册的 markdown 出自 [项目的 Git 仓库](https://github.com/mybatis/spring/tree/master/src/site) 。Fork 仓库,更新它并提交 Pull Request 吧。 + +还有其它像你一样的人都需要阅读这份文档,而你,就是这份文档最好的作者。 + +## 文档的翻译版本 + +可以阅读以下 MyBatis-Spring 文档的翻译版本: + + + +想用自己的母语阅读这篇文档吗?那就用你的母语翻译它吧! diff --git a/src/site/zh/markdown/mappers.md b/src/site/zh/markdown/mappers.md new file mode 100644 index 0000000000..2be7d90375 --- /dev/null +++ b/src/site/zh/markdown/mappers.md @@ -0,0 +1,183 @@ + +# 注入映射器 + +与其在数据访问对象(DAO)中手工编写使用 `SqlSessionDaoSupport` 或 `SqlSessionTemplate` 的代码,还不如让 Mybatis-Spring 为你创建一个线程安全的映射器,这样你就可以直接注入到其它的 bean 中了: + +```xml + + + +``` + +注入完毕后,映射器就可以在你的应用逻辑代码中使用了: + +```java +public class FooServiceImpl implements FooService { + + private final UserMapper userMapper; + + public FooServiceImpl(UserMapper userMapper) { + this.userMapper = userMapper; + } + + public User doSomeBusinessStuff(String userId) { + return this.userMapper.getUser(userId); + } +} +``` + +注意代码中并没有任何的对 `SqlSession` 或 MyBatis 的引用。你也不需要担心创建、打开、关闭 session,MyBatis-Spring 将为你打理好一切。 + + +## 注册映射器 + +注册映射器的方法根据你的配置方法,即经典的 XML 配置或新的 3.0 以上版本的 Java 配置(也就是常说的 `@Configuration`),而有所不同。 + +### XML 配置 + +在你的 XML 中加入 `MapperFactoryBean` 以便将映射器注册到 Spring 中。就像下面一样: + +```xml + + + + +``` + +如果映射器接口 UserMapper 在相同的类路径下有对应的 MyBatis XML 映射器配置文件,将会被 `MapperFactoryBean` 自动解析。不需要在 MyBatis 配置文件中显式配置映射器,除非映射器配置文件与接口类不在同一个类路径下。 +参考 `SqlSessionFactoryBean` 的 [`configLocation`](factorybean.html) 属性以获取更多信息。 + +注意 `MapperFactoryBean` 需要配置一个 `SqlSessionFactory` 或 `SqlSessionTemplate`。它们可以分别通过 `sqlSessionFactory` 和 `sqlSessionTemplate` 属性来进行设置。 +如果两者都被设置,`SqlSessionFactory` 将被忽略。由于 `SqlSessionTemplate` 已经设置了一个 session 工厂,`MapperFactoryBean` 将使用那个工厂。 + +### Java 配置 + +```java +@Configuration +public class MyBatisConfig { + @Bean + public MapperFactoryBean userMapper() throws Exception { + MapperFactoryBean factoryBean = new MapperFactoryBean<>(UserMapper.class); + factoryBean.setSqlSessionFactory(sqlSessionFactory()); + return factoryBean; + } +} +``` + + +## 发现映射器 + +不需要一个个地注册你的所有映射器。你可以让 MyBatis-Spring 对类路径进行扫描来发现它们。 + + +有几种办法来发现映射器: + +* 使用 `` 元素 +* 使用 `@MapperScan` 注解 +* 在经典 Spring XML 配置文件中注册一个 `MapperScannerConfigurer` + +`` 和 `@MapperScan` 都在 MyBatis-Spring 1.2.0 中被引入。`@MapperScan` 需要你使用 Spring 3.1+。 + +Since 2.0.2, mapper scanning feature support a option (`lazy-initialization`) that control lazy initialization enabled/disabled of mapper bean. +The motivation for adding this option is supporting a lazy initialization control feature supported by Spring Boot 2.2. The default of this option is `false` (= not use lazy initialization). +If developer want to use lazy initialization for mapper bean, it should be set to the `true` expressly. + +IMPORTANT +If use the lazy initialization feature, the developer need to understand following limitations. +If any of following conditions are matches, usually the lazy initialization feature cannot use on your application. + +* When refers to the statement of **other mapper** using ``(`@One`) and ``(`@Many`) +* When includes to the fragment of **other mapper** using `` +* When refers to the cache of **other mapper** using ``(`@CacheNamespaceRef`) +* When refers to the result mapping of **other mapper** using `]]> - -

配合如下的配置样例:

- - - - -
]]> - - reader() { - return new MyBatisPagingItemReaderBuilder() - .sqlSessionFactory(sqlSessionFactory()) - .queryId("com.my.name.space.batch.EmployeeMapper.getEmployee") - .build(); -}]]> - -

让我们通过一个更复杂一点的例子来阐明一切:

- - - - - - - - -]]> - - dateBasedCriteriaReader( - @Value("#{@datesParameters}") Map datesParameters) throws Exception { - return new MyBatisPagingItemReaderBuilder() - .sqlSessionFactory(batchReadingSessionFactory()) - .queryId("com.my.name.space.batch.ExampleMapper.queryUserInteractionsOnSpecificTimeSlot") - .parameterValues(datesParameters) - .pageSize(200) - .build(); -} - -@StepScope -@Bean -public Map datesParameters( - @Value("#{jobExecutionContext['EXTRACTION_START_DATE']}") LocalDate yesterday, - @Value("#{jobExecutionContext['TODAY_DATE']}") LocalDate today, - @Value("#{jobExecutionContext['FIRST_DAY_OF_THE_MONTH_DATE']}") LocalDate firstDayOfTheMonth, - @Value("#{jobExecutionContext['FIRST_DAY_OF_THE_PREVIOUS_MONTH_DATE']}") LocalDate firstDayOfThePreviousMonth) { - Map map = new HashMap<>(); - map.put("yesterday", yesterday); - map.put("today", today); - map.put("first_day_of_the_month", firstDayOfTheMonth); - map.put("first_day_of_the_previous_month", firstDayOfThePreviousMonth); - return map; -}]]> - -

- 上面的样例使用了几个东西: -

- -
    -
  • sqlSessionFactory:可以为 reader 指定你自定义的 sessionFactory,当你想从多个数据库中读取数据时尤其有用
  • -
  • queryId:指定在检索记录时要执行的查询的 ID,可以指定短的 ID 或是带命名空间的完整 ID。一般来说,你的应用可能从多个表或数据库中读取数据,因此会配置多个查询,可能会使用到在不同命名空间中的不同映射器。因此最好提供映射器文件的命名空间以便准确指定你想使用的查询 ID。
  • -
  • parameterValues:可以通过这个 map 传递多个附加的参数,上面的例子中就使用了一个由 Spring 构建的 map,并使用 SpEL 表达式从 jobExecutionContext 中获取信息。而 map 的键将在映射器文件中被 MyBatis 使用(例如:yesterday 可以通过 #{yesterday,jdbcType=TIMESTAMP} 来读取)。注意,map 和 reader 都构建于 step 作用域,这样才能够在 Spring 表达式语言中使用 jobExecutionContext。另外,如果正确配置了 MyBatis 的类型处理器,你可以将自定义的实例像参数那样传递到 map 中,比如将参数类型换成 JodaTime。
  • -
  • pageSize:如果批处理流配置了块大小(chunk size),需要通过此属性将块大小告知 reader。
  • -
- - - - -

- 这个 bean 是一个 ItemReader ,能够通过游标从数据库中读取记录。 -

- -

- 提示 为了使用这个 bean,你需要使用 MyBatis 3.4.0 或更新的版本。 -

- -

- 它执行 setQueryId 属性指定的查询来获取请求的数据(通过 selectCursor()方法)。每次调用 read() 方法时,将会返回游标指向的下个元素,直到没有剩余的元素了。 -

- -

- 这个 reader 将会使用一个单独的数据库连接,因此 select 语句将不会参与到 step 处理中创建的任何事务。 -

- -

当使用游标时,只需要执行普通的查询:

- - SELECT id, name, job FROM employees ORDER BY id ASC -]]> - -

搭配以下的配置样例:

- - - - -
]]> - - reader() { - return new MyBatisCursorItemReaderBuilder() - .sqlSessionFactory(sqlSessionFactory()) - .queryId("com.my.name.space.batch.EmployeeMapper.getEmployee") - .build(); -}]]> - - - - - -

- 这是一个 ItemWriter,通过利用 SqlSessionTemplate - 中的批量处理功能来对给定的所有记录执行多个语句。SqlSessionFactory - 需要被配置为 BATCH 执行类型。 -

- -

- 当调用 write() 时,将会执行 statementId - 属性中指定的映射语句。一般情况下,write() - 应该在一个事务中进行调用。
-

- -

下面是一个配置样例:

- - - - -
]]> - - writer() { - return new MyBatisBatchItemWriterBuilder() - .sqlSessionFactory(sqlSessionFactory()) - .statementId("com.my.name.space.batch.EmployeeMapper.updateEmployee") - .build(); -}]]> - - -

将 ItemReader 读取的记录转换为任意的参数对象:

- -

- 默认情况下,MyBatisBatchItemWriter 会将 ItemReader - 读取的对象(或 ItemProcessor 转换过的对象) 以参数对象的形式传递给 - MyBatis(SqlSession#update())。 - 如果你想自定义传递给 MyBatis 的参数对象,可以使用 itemToParameterConverter 选项。 - 使用该选项后,可以传递任意对象给 MyBatis。 - 举个例子: -

- -

- 首先,创建一个自定义的转换器类(或工厂方法)。以下例子使用了工厂方法。 -

- - Converter> createItemToParameterMapConverter(String operationBy, LocalDateTime operationAt) { - return item -> { - Map parameter = new HashMap<>(); - parameter.put("item", item); - parameter.put("operationBy", operationBy); - parameter.put("operationAt", operationAt); - return parameter; - }; -}]]> - -

- 接下来,编写 SQL 映射。 -

- - - insert into persons (first_name, last_name, operation_by, operation_at) - values(#{item.firstName}, #{item.lastName}, #{operationBy}, #{operationAt}) -]]> - -

- 最后,配置 MyBatisBatchItemWriter。 -

- - writer() throws Exception { - return new MyBatisBatchItemWriterBuilder() - .sqlSessionFactory(sqlSessionFactory()) - .statementId("org.mybatis.spring.sample.mapper.PersonMapper.createPerson") - .itemToParameterConverter(createItemToParameterMapConverter("batch_java_config_user", LocalDateTime.now())) - .build(); -}]]> - - - - - - - - - - - - -]]> - - -

使用复合 writer 对多个表进行写入(但带有问题):

- -

- 这个小技巧只能在 MyBatis 3.2+ 以上的版本中使用,因为之前的版本中含有导致 writer 行为不正确的问题。 -

- -

- 如果批量处理时需要写入复杂的数据,例如含有关联的记录,甚至是向多个数据库写入数据,你可能就需要一种办法来绕开 insert 语句只能插入到一个表中的限制。为了绕过此限制,批处理必须准备好要通过 writer 写入的。然而,基于对被处理的数据的观察,可以尝试使用下面的方法来解决此问题。下面的方法能够工作于具有简单关联或不相关的多个表的项。 -

- -

- 在这种方法中,处理 Spring Batch 项的处理器中将会持有各种不同的记录。假设每个项都有一个与 InteractionMetadata 相关联的 Interaction,并且还有两个不相关的行 VisitorInteraction 和 - CustomerInteraction,这时候持有器(holder)看起来像这样: -

- - - -

- 在 Spring 配置中要配置一个 CompositeItemWriter,它将会将写入操作委托到特定种类的 writer 上面去。注意 InteractionMetadata 在例子里面是一个关联,它需要首先被写入,这样 Interaction 才能获得更新之后的键。 -

- - - - - - - - - - - - -
]]> - - interactionsItemWriter() { - CompositeItemWriter compositeItemWriter = new CompositeItemWriter(); - List> writers = new ArrayList<>(4); - writers.add(visitorInteractionsWriter()); - writers.add(customerInteractionsWriter()); - writers.add(interactionMetadataWriter()); - writers.add(interactionWriter()); - compositeItemWriter.setDelegates(writers); - return compositeItemWriter; -}]]> - -

- 接下来需要配置每一个被委托的 writer;例如 InteractionInteractionMetadata 对应的 writer。 -

- - -]]> - -

和 reader 中的一样,通过 statementId 属性指定对应命名空间前缀的查询。

- -

而在映射器配置文件中,应该根据每种特定的记录编写特定的语句,如下所示:

- - - - - - -]]> - -

- 执行的时候会怎么样呢?首先,insertInteractionMetadata 将会被调用,update 语句被设置为返回由 JDBC 驱动返回的主键(参考 keyPropertykeyColumn)。由于 InteractionMetadata 的对象被此查询更新了,下一个查询将可以通过 insertInteraction 开展父对象 Interaction 的写入工作。 -

- -

- 然而要注意,JDBC 驱动在这方面的行为并不总是与此相一致。在编写文档时,H2 的数据库驱动 1.3.168 甚至只在 BATCH 模式下返回最后的索引值(参考 org.h2.jdbc.JdbcStatement#getGeneratedKeys),而 MySQL 的 JDBC 驱动则工作良好并返回所有 ID。 - -

- - - - diff --git a/src/site/zh/xdoc/boot.xml b/src/site/zh/xdoc/boot.xml deleted file mode 100644 index b493aee651..0000000000 --- a/src/site/zh/xdoc/boot.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - MyBatis-Spring | 搭配 Spring Boot - Eduardo Macarron - - - -
-

- 请查看 MyBatis Spring-boot-starter - 子项目获取更多信息。 -

-
- -
diff --git a/src/site/zh/xdoc/factorybean.xml b/src/site/zh/xdoc/factorybean.xml deleted file mode 100644 index ec33d4492a..0000000000 --- a/src/site/zh/xdoc/factorybean.xml +++ /dev/null @@ -1,140 +0,0 @@ - - - - - - MyBatis-Spring | SqlSessionFactoryBean - Hunter Presnall - Eduardo Macarron - Nan Lei - - - -
-

- 在基础的 MyBatis 用法中,是通过 SqlSessionFactoryBuilder 来创建 SqlSessionFactory 的。 - 而在 MyBatis-Spring 中,则使用 SqlSessionFactoryBean 来创建。 -

- - -

- 要创建工厂 bean,将下面的代码放到 Spring 的 XML 配置文件中: -

- - -]]> - -

- 需要注意的是 SqlSessionFactoryBean 实现了 Spring 的 FactoryBean 接口(参见 Spring 官方文档 3.8 节 通过工厂 bean 自定义实例化逻辑)。这意味着由 Spring 最终创建的 bean 并不是 SqlSessionFactoryBean 本身,而是工厂类(SqlSessionFactoryBean)的 getObject() 方法的返回结果。这种情况下,Spring 将会在应用启动时为你创建 SqlSessionFactory,并使用 sqlSessionFactory 这个名字存储起来。 -

-

- 等效的 Java 代码如下: -

- - - -

- 通常,在 MyBatis-Spring 中,你不需要直接使用 SqlSessionFactoryBean 或对应的 SqlSessionFactory。相反,session 的工厂 bean 将会被注入到 MapperFactoryBean 或其它继承于 SqlSessionDaoSupport 的 DAO(Data Access Object,数据访问对象)中。 -

-
- - - -

- SqlSessionFactory 有一个唯一的必要属性:用于 JDBC 的 DataSource。这可以是任意的 DataSource 对象,它的配置方法和其它 Spring 数据库连接是一样的。 -

- -

- 一个常用的属性是 configLocation,它用来指定 MyBatis 的 XML 配置文件路径。它在需要修改 MyBatis 的基础配置非常有用。通常,基础配置指的是 <settings><typeAliases> 元素。 -

- -

- 需要注意的是,这个配置文件并不需要是一个完整的 MyBatis 配置。确切地说,任何环境配置(<environments>),数据源(<DataSource>)和 MyBatis 的事务管理器(<transactionManager>)都会被忽略SqlSessionFactoryBean 会创建它自有的 MyBatis 环境配置(Environment),并按要求设置自定义环境的值。 -

- -

- 如果 MyBatis 在映射器类对应的路径下找不到与之相对应的映射器 XML 文件,那么也需要配置文件。这时有两种解决办法:第一种是手动在 MyBatis 的 XML 配置文件中的 <mappers> 部分中指定 XML 文件的类路径;第二种是设置工厂 bean 的 mapperLocations 属性。 -

- -

- mapperLocations 属性接受多个资源位置。这个属性可以用来指定 MyBatis 的映射器 XML 配置文件的位置。属性的值是一个 Ant 风格的字符串,可以指定加载一个目录中的所有文件,或者从一个目录开始递归搜索所有目录。比如: -

- - - - -]]> - -

- 这会从类路径下加载所有在 sample.config.mappers 包和它的子包中的 MyBatis 映射器 XML 配置文件。 -

- -

- 在容器管理事务的时候,你可能需要的一个属性是 transactionFactoryClass。请参考事务一章的相关章节。 -

- -

- 如果你使用了多个数据库,那么需要设置 databaseIdProvider 属性: -

- - - - - sqlserver - db2 - oracle - mysql - - - - - - - - -]]> - -

- 提示 自 1.3.0 版本开始,新增的 configuration 属性能够在没有对应的 MyBatis XML 配置文件的情况下,直接设置 Configuration 实例。例如: -

- - - - - - - - -]]> - -
-
- -
diff --git a/src/site/zh/xdoc/getting-started.xml.vm b/src/site/zh/xdoc/getting-started.xml.vm deleted file mode 100644 index 7ced8e3011..0000000000 --- a/src/site/zh/xdoc/getting-started.xml.vm +++ /dev/null @@ -1,133 +0,0 @@ - - - - - - MyBatis-Spring | 入门 - Hunter Presnall - Eduardo Macarron - Nan Lei - - - -
-

- 本章将会以简略的步骤告诉你如何安装和配置 MyBatis-Spring,并构建一个简单的具备事务管理功能的数据访问应用程序。 -

- - -

- 要使用 MyBatis-Spring 模块,只需要在类路径下包含 mybatis-spring-${project.version}.jar 文件和相关依赖即可。 -

-

- 如果使用 Maven 作为构建工具,仅需要在 pom.xml 中加入以下代码即可: -

- - org.mybatis - mybatis-spring - ${project.version} -]]> -
- - -

- 要和 Spring 一起使用 MyBatis,需要在 Spring 应用上下文中定义至少两样东西:一个 SqlSessionFactory 和至少一个数据映射器类。 -

- -

- 在 MyBatis-Spring 中,可使用 SqlSessionFactoryBean来创建 SqlSessionFactory。 - 要配置这个工厂 bean,只需要把下面代码放在 Spring 的 XML 配置文件中: -

- - - -]]> - - - -

- 注意:SqlSessionFactory 需要一个 DataSource(数据源)。 - 这可以是任意的 DataSource,只需要和配置其它 Spring 数据库连接一样配置它就可以了。 -

- -

- 假设你定义了一个如下的 mapper 接口: -

- - -

- 那么可以通过 MapperFactoryBean 将接口加入到 Spring 中: -

- - - - -]]> - -

- 需要注意的是:所指定的映射器类必须是一个接口,而不是具体的实现类。在这个示例中,通过注解来指定 SQL 语句,但是也可以使用 MyBatis 映射器的 XML 配置文件。 -

- -

- 配置好之后,你就可以像 Spring 中普通的 bean 注入方法那样,将映射器注入到你的业务或服务对象中。MapperFactoryBean 将会负责 SqlSession 的创建和关闭。如果使用了 Spring 的事务功能,那么当事务完成时,session 将会被提交或回滚。最终任何异常都会被转换成 Spring 的 DataAccessException 异常。 -

- -

- 使用 Java 代码来配置的方式如下: -

- - -

- 要调用 MyBatis 的数据方法,只需一行代码: -

- -
-
- -
diff --git a/src/site/zh/xdoc/index.xml b/src/site/zh/xdoc/index.xml deleted file mode 100644 index 8f25bf170e..0000000000 --- a/src/site/zh/xdoc/index.xml +++ /dev/null @@ -1,142 +0,0 @@ - - - - - - MyBatis-Spring | 简介 - Hunter Presnall - Eduardo Macarron - Nan Lei - - - -
- -

- MyBatis-Spring 会帮助你将 MyBatis 代码无缝地整合到 Spring 中。它将允许 MyBatis 参与到 Spring 的事务管理之中,创建映射器 mapper 和 SqlSession 并注入到 bean 中,以及将 Mybatis 的异常转换为 Spring 的 DataAccessException。最终,可以做到应用代码不依赖于 MyBatis,Spring 或 MyBatis-Spring。 -

-
- - -

- Spring 2.0 只支持 iBatis 2.0。那么,我们就想将 MyBatis3 的支持添加到 Spring 3.0 中(参见 Spring Jira 中的问题)。不幸的是,Spring 3.0 的开发在 MyBatis 3.0 官方发布前就结束了。由于 Spring 开发团队不想发布一个基于未发布版的 MyBatis 的整合支持,如果要获得 Spring 官方的支持,只能等待下一次的发布了。基于在 Spring 中对 MyBatis 提供支持的兴趣,MyBatis 社区认为,应该开始召集有兴趣参与其中的贡献者们,将对 Spring 的集成作为 MyBatis 的一个社区子项目。 -

-
- - -

- 在开始使用 MyBatis-Spring 之前,你需要先熟悉 Spring 和 MyBatis 这两个框架和有关它们的术语。这很重要——因为本手册中不会提供二者的基本内容,安装和配置教程。 -

-

- MyBatis-Spring 需要以下版本: -

- - - - - - - - - - - - - - - - - - - - - - - - - - -
- MyBatis-Spring - - MyBatis - - Spring 框架 - - Spring Batch - - Java -
- 2.0 - - 3.5+ - - 5.0+ - - 4.0+ - - Java 8+ -
- 1.3 - - 3.4+ - - 3.2.2+ - - 2.1+ - - Java 6+ -
-
- - -

- 特别感谢那些使本项目变为现实的人们(按字母顺序排序): Eduardo Macarron, Hunter Presnall 和 Putthiphong Boonphong 负责本项目的代码实现,测试和编写文档工作;Andrius Juozapaitis, Giovanni Cuccu, Raj Nagappan 和 Tomas Pinos 的贡献;而 Simone Tripodi 发现了这些人并邀请他们参与到这一个 MyBatis 子项目之中。没有他们的努力,这个项目只能沦为空谈。 -

-
- - -

- 如果你发现文档有任何的缺失,或者缺少某一个功能点的说明,最好的解决办法是先自己学习,并且为缺失的部份补上相应的文档。 -

-

- 手册的 xdoc 出自项目的 Git 仓库。Fork 仓库,更新它并提交 Pull Request 吧。 -

-

- 还有其它像你一样的人都需要阅读这份文档,而你,就是这份文档最好的作者。 -

-
- -

可以阅读以下 MyBatis-Spring 文档的翻译版本:

- -

想用自己的母语阅读这篇文档吗?那就用你的母语翻译它吧!

-
- -
- - -
diff --git a/src/site/zh/xdoc/mappers.xml b/src/site/zh/xdoc/mappers.xml deleted file mode 100644 index ee61574e14..0000000000 --- a/src/site/zh/xdoc/mappers.xml +++ /dev/null @@ -1,232 +0,0 @@ - - - - - - MyBatis-Spring | 注入映射器 - Hunter Presnall - Eduardo Macarron - Nan Lei - - - -
-

- 与其在数据访问对象(DAO)中手工编写使用 SqlSessionDaoSupportSqlSessionTemplate 的代码,还不如让 Mybatis-Spring 为你创建一个线程安全的映射器,这样你就可以直接注入到其它的 bean 中了: -

- - - -]]> - -

- 注入完毕后,映射器就可以在你的应用逻辑代码中使用了: -

- -

- 注意代码中并没有任何的对 SqlSession 或 MyBatis 的引用。你也不需要担心创建、打开、关闭 session,MyBatis-Spring 将为你打理好一切。 -

- - -

- 注册映射器的方法根据你的配置方法,即经典的 XML 配置或新的 3.0 以上版本的 Java 配置(也就是常说的 @Configuration),而有所不同。 -

- -

XML 配置

- -

- 在你的 XML 中加入 MapperFactoryBean 以便将映射器注册到 Spring 中。就像下面一样: -

- - - -]]> - -

- 如果映射器接口 UserMapper 在相同的类路径下有对应的 MyBatis XML 映射器配置文件,将会被 MapperFactoryBean 自动解析。不需要在 MyBatis 配置文件中显式配置映射器,除非映射器配置文件与接口类不在同一个类路径下。参考 SqlSessionFactoryBeanconfigLocation 属性以获取更多信息。 -

- -

- 注意 MapperFactoryBean 需要配置一个 SqlSessionFactorySqlSessionTemplate。它们可以分别通过 sqlSessionFactorysqlSessionTemplate 属性来进行设置。如果两者都被设置,SqlSessionFactory 将被忽略。由于 SqlSessionTemplate 已经设置了一个 session 工厂,MapperFactoryBean 将使用那个工厂。 -

- -

Java 配置

- - userMapper() throws Exception { - MapperFactoryBean factoryBean = new MapperFactoryBean<>(UserMapper.class); - factoryBean.setSqlSessionFactory(sqlSessionFactory()); - return factoryBean; -}]]> - -
- - -

- 不需要一个个地注册你的所有映射器。你可以让 MyBatis-Spring 对类路径进行扫描来发现它们。 -

- -

- 有几种办法来发现映射器: -

-
    -
  • 使用 <mybatis:scan/> 元素
  • -
  • 使用 @MapperScan 注解
  • -
  • 在经典 Spring XML 配置文件中注册一个 MapperScannerConfigurer
  • -
- -

<mybatis:scan/>@MapperScan 都在 MyBatis-Spring 1.2.0 中被引入。@MapperScan 需要你使用 Spring 3.1+。

- -

- Since 2.0.2, mapper scanning feature support a option (lazy-initialization) - that control lazy initialization enabled/disabled of mapper bean. - The motivation for adding this option is supporting a lazy initialization control feature supported by Spring Boot 2.2. - The default of this option is false (= not use lazy initialization). - If developer want to use lazy initialization for mapper bean, it should be set to the true expressly. -

-

- IMPORTANT If use the lazy initialization feature, - the developer need to understand following limitations. If any of following conditions are matches, - usually the lazy initialization feature cannot use on your application. -

-
    -
  • When refers to the statement of other mapper using ]]>(@One) and ]]>(@Many)
  • -
  • When includes to the fragment of other mapper using ]]>
  • -
  • When refers to the cache of other mapper using ]]>(@CacheNamespaceRef)
  • -
  • When refers to the result mapping of other mapper using ]]>(@ResultMap)
  • -
- -

- NOTE However, It become possible to use it by simultaneously initializing dependent beans using @DependsOn(Spring's feature) as follow: -

- - - -

- Since 2.0.6, the develop become can specified scope of mapper using mapper scanning feature option(default-scope) - and scope annotation(@Scope, @RefreshScope, etc ...). - The motivation for adding this option is supporting the refresh scope provided by the Spring Cloud. - The default of this option is empty (= equiv to specify the singleton scope). - The default-scope apply to the mapper bean(MapperFactoryBean) when scope of scanned bean definition - is singleton(default scope) and create a scoped proxy bean for scanned mapper when final scope is not singleton. -

- -

<mybatis:scan/>

- -

- <mybatis:scan/> 元素会发现映射器,它发现映射器的方法与 Spring 内建的 <context:component-scan/> 发现 bean 的方法非常类似。 -

- -

下面是一个 XML 配置样例:

- - - - - - - -]]> - -

- base-package 属性允许你设置映射器接口文件的基础包。通过使用逗号或分号分隔,你可以设置多个包。并且会在你所指定的包中递归搜索映射器。 -

- -

- 注意,不需要为 <mybatis:scan/> 指定 SqlSessionFactorySqlSessionTemplate,这是因为它将使用能够被自动注入的 MapperFactoryBean。但如果你正在使用多个数据源(DataSource),自动注入可能不适合你。在这种情况下,你可以使用 factory-reftemplate-ref 属性指定你想使用的 bean 名称。 -

- -

- <mybatis:scan/> 支持基于标记接口或注解的过滤操作。在 annotation 属性中,可以指定映射器应该具有的特定注解。而在 marker-interface 属性中,可以指定映射器应该继承的父接口。当这两个属性都被设置的时候,被发现的映射器会满足这两个条件。默认情况下,这两个属性为空,因此在基础包中的所有接口都会被作为映射器被发现。 -

- -

- 被发现的映射器会按照 Spring 对自动发现组件的默认命名策略进行命名(参考 the Spring reference document(Core Technologies -Naming autodetected components-))。也就是说,如果没有使用注解显式指定名称,将会使用映射器的首字母小写非全限定类名作为名称。但如果发现映射器具有 @Component 或 JSR-330 标准中 @Named 注解,会使用注解中的名称作为名称。提醒一下,你可以设置 annotation 属性为你自定义的注解,然后在你的注解上设置 org.springframework.stereotype.Componentjavax.inject.Named(需要使用 Java SE 6 以上)注解,这样你的注解既可以作为标记,也可以作为一个名字提供器来使用了。 -

- -

- 提示 <context:component-scan/> 无法发现并注册映射器。映射器的本质是接口,为了将它们注册到 Spring 中,发现器必须知道如何为找到的每个接口创建一个 MapperFactoryBean。 -

- -

@MapperScan

- -

- 当你正在使用 Spring 的基于 Java 的配置时(也就是 @Configuration),相比于使用 <mybatis:scan/>,你会更喜欢用 @MapperScan。 -

- -

@MapperScan 注解的使用方法如下:

- - - -

- 这个注解具有与之前见过的 <mybatis:scan/> 元素一样的工作方式。它也可以通过 markerInterfaceannotationClass 属性设置标记接口或注解类。通过配置 sqlSessionFactorysqlSessionTemplate 属性,你还能指定一个 SqlSessionFactorySqlSessionTemplate。 -

- -

- NOTE Since 2.0.4, If basePackageClasses or basePackages are not defined, scanning will occur from the package of the class that declares this annotation. -

- -

MapperScannerConfigurer

- -

- MapperScannerConfigurer 是一个 BeanDefinitionRegistryPostProcessor,这样就可以作为一个 bean,包含在经典的 XML 应用上下文中。为了配置 MapperScannerConfigurer,使用下面的 Spring 配置: -

- - -]]> - -

- 如果你需要指定 sqlSessionFactorysqlSessionTemplate,那你应该要指定的是 bean 名而不是 bean 的引用,因此要使用 value 属性而不是通常的 ref 属性: -

- ]]> - -

- 提示 在 MyBatis-Spring 1.0.2 之前,sqlSessionFactoryBean 和 - sqlSessionTemplateBean 属性是唯一可用的属性。但由于 MapperScannerConfigurer 在启动过程中比 PropertyPlaceholderConfigurer 运行得更早,经常会产生错误。基于这个原因,上述的属性已被废弃,现在建议使用 sqlSessionFactoryBeanNamesqlSessionTemplateBeanName 属性。 -

-
-
- -
diff --git a/src/site/zh/xdoc/sample.xml b/src/site/zh/xdoc/sample.xml deleted file mode 100644 index ba69cc0abf..0000000000 --- a/src/site/zh/xdoc/sample.xml +++ /dev/null @@ -1,164 +0,0 @@ - - - - - - MyBatis-Spring | 示例代码 - Eduardo Macarron - - - -
- -

- 提示 - 查看 JPetstore 6 demo 了解如何在完整的 Web 应用服务器上使用 Spring。 -

- -

- 您可以在 MyBatis-Spring 的代码仓库 中查看示例代码: -

-

- 所有示例都能在 JUnit 5 下运行。 -

-

- 示例代码演示了事务服务从数据访问层获取域对象的典型设计。 -

-

- FooService.java 作为服务: -

- -

- 它是一个事务 bean,所以当调用它的任何方法时,事务被启动,在方法结束且没有抛出任何未经检查的异常的时候事务将会被提交。注意,事务的行为可以通过 @Transactional 的属性进行配置。这不是必需的;你可以使用 Spring 提供的任何其他方式来划分你的事务范围。 -

-

- 此服务调用使用 MyBatis 构建的数据访问层.。该层只包含一个接口,UserMapper.java,这将被 MyBatis 构建的动态代理使用,在运行时通过 Spring 注入到服务之中。 -

- -

- 注意,为了简单起见,我们使用了接口 UserMapper.java。在使用 DAO 的场景中,一个 DAO 类应该分为一个接口和一个实现类。回到这个例子里,准确来说,这个接口应该叫 UserDao.java 。 -

-

- 我们将看到不同的方法来发现映射器接口,将其注册到 Spring 并将其注入到服务 bean 中: -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
测试场景
样例测试描述
- SampleMapperTest.java - - 演示基于 MapperFactoryBean 的基本配置,这将动态构建 UserMapper 的一个实现。 -
- SampleScannerTest.java - - 演示如何使用 MapperScannerConfigurer 来自动发现项目中所有的映射器。 -
- SampleSqlSessionTest.java - - 演示如何基于 Spring 管理的 SqlSession 手动编写 DAO,并在 UserDaoImpl.java 中提供你自己的实现。 -
- SampleEnableTest - - 演示如何使用 Spring 的 @Configuration@MapperScann 注解来自动发现 mappers. -
- SampleNamespaceTest - - 演示如何使用自定义 MyBatis XML 命名空间. -
- SampleJavaConfigTest.java - - 演示如何基于 Spring 的 @Configuration 来手工创建 MyBatis 的 bean。 -
- SampleJobJavaConfigTest.java - - 演示如何在 Java 配置中使用 Spring Batch 中的 ItemReaderItemWriter。 -
- SampleJobXmlConfigTest.java - - 演示如何在 XML 配置中使用 Spring Batch 中的 ItemReaderItemWriter。 -
-

- 查看不同的 applicationContext.xml 文件以了解 MyBatis-Spring 在实践中是如何运用的。 -

- -
- -
- diff --git a/src/site/zh/xdoc/sqlsession.xml b/src/site/zh/xdoc/sqlsession.xml deleted file mode 100644 index 475a96a935..0000000000 --- a/src/site/zh/xdoc/sqlsession.xml +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - MyBatis-Spring | 使用 SqlSession - Hunter Presnall - Eduardo Macarron - Nan Lei - - - -
-

- 在 MyBatis 中,你可以使用 SqlSessionFactory 来创建 SqlSession。一旦你获得一个 session 之后,你可以使用它来执行映射了的语句,提交或回滚连接,最后,当不再需要它的时候,你可以关闭 session。使用 MyBatis-Spring 之后,你不再需要直接使用 SqlSessionFactory 了,因为你的 bean 可以被注入一个线程安全的 SqlSession,它能基于 Spring 的事务配置来自动提交、回滚、关闭 session。 -

- - -

- SqlSessionTemplate 是 MyBatis-Spring 的核心。作为 SqlSession 的一个实现,这意味着可以使用它无缝代替你代码中已经在使用的 SqlSessionSqlSessionTemplate 是线程安全的,可以被多个 DAO 或映射器所共享使用。 -

- -

- 当调用 SQL 方法时(包括由 getMapper() 方法返回的映射器中的方法),SqlSessionTemplate 将会保证使用的 SqlSession 与当前 Spring 的事务相关。此外,它管理 session 的生命周期,包含必要的关闭、提交或回滚操作。另外,它也负责将 MyBatis 的异常翻译成 Spring 中的 DataAccessExceptions。 -

- -

- 由于模板可以参与到 Spring 的事务管理中,并且由于其是线程安全的,可以供多个映射器类使用,你应该总是SqlSessionTemplate 来替换 MyBatis 默认的 DefaultSqlSession 实现。在同一应用程序中的不同类之间混杂使用可能会引起数据一致性的问题。 -

- -

- 可以使用 SqlSessionFactory 作为构造方法的参数来创建 SqlSessionTemplate 对象。 -

- - -]]> - - - -

- 现在,这个 bean 就可以直接注入到你的 DAO bean 中了。你需要在你的 bean 中添加一个 SqlSession 属性,就像下面这样: -

- -

- 按下面这样,注入 SqlSessionTemplate: -

- - -]]> - -

- SqlSessionTemplate 还有一个接收 ExecutorType 参数的构造方法。这允许你使用如下 Spring 配置来批量创建对象,例如批量创建一些 SqlSession: -

- - - -]]> - - - -

- 现在所有的映射语句可以进行批量操作了,可以在 DAO 中编写如下的代码 -

- users) { - for (User user : users) { - sqlSession.insert("org.mybatis.spring.sample.mapper.UserMapper.insertUser", user); - } -}]]> - -

- 注意,只需要在希望语句执行的方法与 SqlSessionTemplate 中的默认设置不同时使用这种配置。 -

- -

- 这种配置的弊端在于,当调用这个方法时,不能存在使用不同 ExecutorType 的进行中的事务。要么确保对不同 ExecutorTypeSqlSessionTemplate 的调用处在不同的事务中,要么完全不使用事务。 -

-
- - -

- SqlSessionDaoSupport 是一个抽象的支持类,用来为你提供 SqlSession。调用 getSqlSession() 方法你会得到一个 SqlSessionTemplate,之后可以用于执行 SQL 方法,就像下面这样: -

- -

- 在这个类里面,通常更倾向于使用 MapperFactoryBean,因为它不需要额外的代码。但是,如果你需要在 DAO 中做其它非 MyBatis 的工作或需要一个非抽象的实现类,那么这个类就很有用了。 -

- -

- SqlSessionDaoSupport 需要通过属性设置一个 sqlSessionFactorySqlSessionTemplate。如果两个属性都被设置了,那么 SqlSessionFactory 将被忽略。 -

- -

- 假设类 UserMapperImplSqlSessionDaoSupport 的子类,可以编写如下的 Spring 配置来执行设置: -

- - -]]> -
-
- -
diff --git a/src/site/zh/xdoc/transactions.xml b/src/site/zh/xdoc/transactions.xml deleted file mode 100644 index 95d801251a..0000000000 --- a/src/site/zh/xdoc/transactions.xml +++ /dev/null @@ -1,142 +0,0 @@ - - - - - - MyBatis-Spring | 事务 - Hunter Presnall - Eduardo Macarron - Nan Lei - - - -
-

- 一个使用 MyBatis-Spring 的其中一个主要原因是它允许 MyBatis 参与到 Spring 的事务管理中。而不是给 MyBatis 创建一个新的专用事务管理器,MyBatis-Spring 借助了 Spring 中的 DataSourceTransactionManager 来实现事务管理。 -

-

- 一旦配置好了 Spring 的事务管理器,你就可以在 Spring 中按你平时的方式来配置事务。并且支持 @Transactional 注解和 AOP 风格的配置。在事务处理期间,一个单独的 SqlSession 对象将会被创建和使用。当事务完成时,这个 session 会以合适的方式提交或回滚。 -

-

- 事务配置好了以后,MyBatis-Spring 将会透明地管理事务。这样在你的 DAO 类中就不需要额外的代码了。 -

- - -

- 要开启 Spring 的事务处理功能,在 Spring 的配置文件中创建一个 DataSourceTransactionManager 对象: -

- - -]]> - - - -

- 传入的 DataSource 可以是任何能够与 Spring 兼容的 JDBC DataSource。包括连接池和通过 JNDI 查找获得的 DataSource。 -

-

- 注意:为事务管理器指定的 DataSource 必须和用来创建 SqlSessionFactoryBean 的是同一个数据源,否则事务管理器就无法工作了。 -

-
- - -

- 如果你正使用一个 JEE 容器而且想让 Spring 参与到容器管理事务(Container managed transactions,CMT)的过程中,那么 Spring 应该被设置为使用 JtaTransactionManager 或由容器指定的一个子类作为事务管理器。最简单的方式是使用 Spring 的事务命名空间或使用 JtaTransactionManagerFactoryBean: -

- ]]> - - - -

- 在这个配置中,MyBatis 将会和其它由容器管理事务配置的 Spring 事务资源一样。Spring 会自动使用任何一个存在的容器事务管理器,并注入一个 SqlSession。如果没有正在进行的事务,而基于事务配置需要一个新的事务的时候,Spring 会开启一个新的由容器管理的事务。 -

-

- 注意,如果你想使用由容器管理的事务,而不想使用 Spring 的事务管理,你就不能配置任何的 Spring 事务管理器。并必须配置 SqlSessionFactoryBean 以使用基本的 MyBatis 的 ManagedTransactionFactory: -

- - - - - -]]> - - - -
- - -

- MyBatis 的 SqlSession 提供几个方法来在代码中处理事务。但是当使用 MyBatis-Spring 时,你的 bean 将会注入由 Spring 管理的 SqlSession 或映射器。也就是说,Spring 总是为你处理了事务。 -

-

- 你不能在 Spring 管理的 SqlSession 上调用 SqlSession.commit()SqlSession.rollback()SqlSession.close() 方法。如果这样做了,就会抛出 UnsupportedOperationException 异常。在使用注入的映射器时,这些方法也不会暴露出来。 -

-

- 无论 JDBC 连接是否设置为自动提交,调用 SqlSession 数据方法或在 Spring 事务之外调用任何在映射器中方法,事务都将会自动被提交。 -

-

- 如果你想编程式地控制事务,请参考 the Spring reference document(Data Access -Programmatic transaction management-)。下面的代码展示了如何使用 PlatformTransactionManager 手工管理事务。 -

- - -

- 在使用 TransactionTemplate 的时候,可以省略对 commitrollback 方法的调用。 -

- - { - userMapper.insertUser(user); - return null; -});]]> - -

- 注意:虽然这段代码使用的是一个映射器,但换成 SqlSession 也是可以工作的。 -

-
-
- -
diff --git a/src/site/zh/xdoc/using-api.xml b/src/site/zh/xdoc/using-api.xml deleted file mode 100644 index f8b2f025e1..0000000000 --- a/src/site/zh/xdoc/using-api.xml +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - MyBatis-Spring | 使用 MyBatis API - Hunter Presnall - Eduardo Macarron - Nan Lei - - - -
-

- 使用 MyBatis-Spring,你可以继续直接使用 MyBatis 的 API。只需简单地使用 SqlSessionFactoryBean 在 Spring 中创建一个 SqlSessionFactory,然后按你的方式在代码中使用工厂即可。 -

- - -

- 小心使用此选项,错误地使用会产生运行时错误,更糟糕地,会产生数据一致性的问题。直接使用 API 时,注意以下弊端: -

-
    -
  • -

    - 它不会参与到 Spring 的事务管理之中。 -

    -
  • -
  • -

    - 如果 SqlSession 使用与 Spring 事务管理器使用的相同 DataSource,并且有进行中的事务,代码会抛出异常。 -

    -
  • -
  • -

    - MyBatis 的 DefaultSqlSession 是线程不安全的。如果在 bean 中注入了它,会发生错误。 -

    -
  • -
  • -

    - 使用 DefaultSqlSession 创建的映射器也不是线程安全的。如果你将它们注入到 bean 中,会发生错误。 -

    -
  • -
  • -

    - 你必须确保总是在 finally 块中来关闭 SqlSession。 -

    -
  • -
-
- -