基于注解的方式配置SSM

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35542218/article/details/80629607

首先创建一个MybatisConfiguration.java

package org.coolerwu.outsource.config;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;

/**
 * @author coolerwu on 2018/6/8.
 * @version 1.0
 * @time 23:40
 */
@Configuration
public class MybatisConfiguration {

    @Bean("dataSource")
    public DataSource dataSource() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/outsource?useSSL=false");
        dataSource.setUser("root");
        dataSource.setPassword("123456");
        return dataSource;
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:org/coolerwu/outsource/mapping/*.xml"));
        return sqlSessionFactoryBean.getObject();
    }

    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer() {
        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
        mapperScannerConfigurer.setBasePackage("org.coolerwu.outsource.mapping");
        mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
        return mapperScannerConfigurer;
    }

    @Bean
    public DataSourceTransactionManager dataSourceTransactionManager(@Qualifier("dataSource") DataSource dataSource) {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }
}

**注意:**在进行MapperScan扫描的时候,会出现这样两个个警告:

No MyBatis mapper was found in '[org.coolerwu.outsource]' package. Please check your configuration
Cannot enhance @Configuration bean definition 'mybatisConfigruation' since its singleton instance 
has been created too early. The typical cause is a non-static @Bean method with a 
BeanDefinitionRegistryPostProcessor return type: Consider declaring such methods as 'static'.

这是因为MapperScannerConfigurer是BeanFactoryPostProcessor的一个实现,如果配置类中出现BeanFactoryPostProcessor,会破坏默认的 post-processing 。
最简单的解决方式是使用 @MapperScan 注解代替 MapperScannerConfigurer 的 bean 配置。


关于@MapperScan的源代码:

/**
 *    Copyright 2010-2016 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.mybatis.spring.annotation;

import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.mybatis.spring.mapper.MapperFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.context.annotation.Import;

/**
 * Use this annotation to register MyBatis mapper interfaces when using Java
 * Config. It performs when same work as {@link MapperScannerConfigurer} via
 * {@link MapperScannerRegistrar}.
 *
 * <p>Configuration example:</p>
 * <pre class="code">
 * &#064;Configuration
 * &#064;MapperScan("org.mybatis.spring.sample.mapper")
 * public class AppConfig {
 *
 *   &#064;Bean
 *   public DataSource dataSource() {
 *     return new EmbeddedDatabaseBuilder()
 *              .addScript("schema.sql")
 *              .build();
 *   }
 *
 *   &#064;Bean
 *   public DataSourceTransactionManager transactionManager() {
 *     return new DataSourceTransactionManager(dataSource());
 *   }
 *
 *   &#064;Bean
 *   public SqlSessionFactory sqlSessionFactory() throws Exception {
 *     SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
 *     sessionFactory.setDataSource(dataSource());
 *     return sessionFactory.getObject();
 *   }
 * }
 * </pre>
 *
 * @author Michael Lanyon
 * @author Eduardo Macarron
 *
 * @since 1.2.0
 * @see MapperScannerRegistrar
 * @see MapperFactoryBean
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(MapperScannerRegistrar.class)
public @interface MapperScan {

  /**
   * Alias for the {@link #basePackages()} attribute. Allows for more concise
   * annotation declarations e.g.:
   * {@code @EnableMyBatisMapperScanner("org.my.pkg")} instead of {@code
   * @EnableMyBatisMapperScanner(basePackages= "org.my.pkg"})}.
   */
  String[] value() default {};

  /**
   * Base packages to scan for MyBatis interfaces. Note that only interfaces
   * with at least one method will be registered; concrete classes will be
   * ignored.
   */
  String[] basePackages() default {};

  /**
   * Type-safe alternative to {@link #basePackages()} for specifying the packages
   * to scan for annotated components. The package of each class specified will be scanned.
   * <p>Consider creating a special no-op marker class or interface in each package
   * that serves no purpose other than being referenced by this attribute.
   */
  Class<?>[] basePackageClasses() default {};

  /**
   * The {@link BeanNameGenerator} class to be used for naming detected components
   * within the Spring container.
   */
  Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

  /**
   * This property specifies the annotation that the scanner will search for.
   * <p>
   * The scanner will register all interfaces in the base package that also have
   * the specified annotation.
   * <p>
   * Note this can be combined with markerInterface.
   */
  Class<? extends Annotation> annotationClass() default Annotation.class;

  /**
   * This property specifies the parent that the scanner will search for.
   * <p>
   * The scanner will register all interfaces in the base package that also have
   * the specified interface class as a parent.
   * <p>
   * Note this can be combined with annotationClass.
   */
  Class<?> markerInterface() default Class.class;

  /**
   * Specifies which {@code SqlSessionTemplate} to use in the case that there is
   * more than one in the spring context. Usually this is only needed when you
   * have more than one datasource.
   */
  String sqlSessionTemplateRef() default "";

  /**
   * Specifies which {@code SqlSessionFactory} to use in the case that there is
   * more than one in the spring context. Usually this is only needed when you
   * have more than one datasource.
   */
  String sqlSessionFactoryRef() default "";

  /**
   * Specifies a custom MapperFactoryBean to return a mybatis proxy as spring bean.
   *
   */
  Class<? extends MapperFactoryBean> factoryBean() default MapperFactoryBean.class;

}

我们可以找到basePackages是指定包,sqlSessionFactoryRef是指定他的SqlSessionFactory,把他放在MybatisConfiguration.java类上面

@MapperScan(basePackages = "org.coolerwu.outsource.mapping", 
	sqlSessionFactoryRef = "sqlSessionFactory")    

完整的配置类注解代码如下:

package org.coolerwu.outsource.config;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;

/**
 * @author coolerwu on 2018/6/8.
 * @version 1.0
 * @time 23:40
 */
@Configuration
@MapperScan(basePackages = "org.coolerwu.outsource.mapping", sqlSessionFactoryRef = "sqlSessionFactory")
public class MybatisConfiguration {

    @Bean("dataSource")
    public DataSource dataSource() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/outsource?useSSL=false");
        dataSource.setUser("root");
        dataSource.setPassword("wulang");
        return dataSource;
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:org/coolerwu/outsource/mapping/*.xml"));
        return sqlSessionFactoryBean.getObject();
    }

//    @Bean
//    public MapperScannerConfigurer mapperScannerConfigurer() {
//        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
//        mapperScannerConfigurer.setBasePackage("org.coolerwu.outsource.mapping");
//        mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
//        return mapperScannerConfigurer;
//    }

    @Bean
    public DataSourceTransactionManager dataSourceTransactionManager(@Qualifier("dataSource") DataSource dataSource) {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }
}

Spring Boot 使用事务非常简单,首先使用注解 @EnableTransactionManagement 开启事务支持后,然后在访问数据库的Service方法上添加注解 @Transactional 便可。
OutsourceApplication.java 如下:

package org.coolerwu.outsource;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@SpringBootApplication
@EnableTransactionManagement
public class OutsourceApplication {

	public static void main(String[] args) {
		SpringApplication.run(OutsourceApplication.class, args);
	}
}

关于事务管理器,不管是JPA还是JDBC等都实现自接口 PlatformTransactionManager 如果你添加的是 spring-boot-starter-jdbc 依赖,框架会默认注入 DataSourceTransactionManager 实例。如果你添加的是 spring-boot-starter-data-jpa 依赖,框架会默认注入 JpaTransactionManager 实例。

在Spring容器中,我们手工注解@Bean 将被优先加载,框架不会重新实例化其他的 PlatformTransactionManager 实现类。

然后在Service中,被 @Transactional 注解的方法,将支持事务。如果注解在类上,则整个类的所有方法都默认支持事务。
UserService.java 代码如下:

package org.coolerwu.outsource.service;

/**
 * @author coolerwu on 2018/6/7.
 * @version 1.0
 * @time 16:33
 */
public interface UserService {

    /**
     * 用户登录
     * @param loginName
     * @param loginPass
     * @return
     */
    int login(String loginName, String loginPass);
}

UserServiceImpl.java 代码如下:

package org.coolerwu.outsource.service.service;

import org.coolerwu.outsource.mapping.UserMapper;
import org.coolerwu.outsource.po.User;
import org.coolerwu.outsource.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author coolerwu on 2018/6/7.
 * @version 1.0
 * @time 16:33
 */
@Service("userService")
@Transactional(transactionManager = "dataSourceTransactionManager", rollbackFor = {Exception.class})
public class UserServiceImpl implements UserService {
    @Autowired
    UserMapper userMapper;

    @Override
    public int login(String loginName, String loginPass) {
        User publisher = userMapper.login(loginName, loginPass);
        if (publisher == null) {
            return 0;
        }
        return 1;
    }

}

注意:这里的userMapper的自动装配可以会提示你找不到该bean,不用理会;如果强迫症的话,可以在UserMapper.java添加@Repository就可以消除。UserMapper.java 代码如下:

package org.coolerwu.outsource.mapping;

import org.apache.ibatis.annotations.Param;
import org.coolerwu.outsource.po.User;
import org.springframework.stereotype.Repository;

/**
 * @author coolerwu on 2018/6/7.
 * @version 1.0
 * @time 16:36
 */
@Repository
public interface UserMapper {

    User login(@Param("loginName") String loginName, @Param("loginPass") String loginPass);
}

另外附上UserMapper.xml 代码如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.coolerwu.outsource.mapping.UserMapper">

    <select id="login" resultType="org.coolerwu.outsource.po.User">
        SELECT * FROM tb_user WHERE LOGINNAME = #{loginName} AND LOGINPASS = #{loginPass}
    </select>

</mapper>

以及UserController.java 代码如下:

package org.coolerwu.outsource.controller;

import org.coolerwu.outsource.extra.Msg;
import org.coolerwu.outsource.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpSession;

/**
 * @author coolerwu on 2018/6/7.
 * @version 1.0
 * @time 16:27
 */
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    UserService userService;

    @RequestMapping("/login")
    public Msg login(@RequestParam("loginName") String loginName,
                     @RequestParam("loginPass") String loginPass,
                     HttpSession session) {
        int i = userService.login(loginName, loginPass);
        if (i == 1) {
            session.setAttribute("loginName", loginName);
            session.setMaxInactiveInterval(3600);
            return Msg.success();
        }
        return Msg.fail();
    }


}

这样完整的SSM搭建就完成了,注解不理解的,多去百度,有很多解释的,因此我没有必要在解释一遍了!

猜你喜欢

转载自blog.csdn.net/qq_35542218/article/details/80629607
今日推荐