Spring对MyBatis的整合

一、Spring对MyBatis的整合

①首先在pom.xml中添加所需要的依赖:

   <dependencies>
        <!--测试包-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>

        <!--spring依赖的包-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring</artifactId>
            <version>5.2.7.RELEASE</version>
            <type>pom</type>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.2.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>5.2.7.RELEASE</version>
        </dependency>

        <!--aop所依赖的包-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.2.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>aopalliance</groupId>
            <artifactId>aopalliance</artifactId>
            <version>1.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.2.7.RELEASE</version>
        </dependency>

        <!--mybatis所依赖的包-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>
        <!--数据库所依赖的包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.19</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.2</version>
        </dependency>

        <!--日志所依赖的包-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <!--lombok所依赖的包-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>

        <!--mybatis和spring的整合包:由mybatis提供-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.2</version>
        </dependency>
        <!--由于mybatis底层还是用的jdbc:所以加入此依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.7.RELEASE</version>
        </dependency>
    </dependencies>

②关键步骤
配置DataSource数据源
配置SqlSessionFactoryBean
使用SqlSessionTemplate进行持久化操作编写测试类测试运行结果

1.配置DataSource数据源

在spring中配置数据源,首先要选择一种具体的数据源实现技术,目前流行的数据源实现有dbcp、c3p0、Proxool , Druid等,他们都实现了功能。这里以Druid数据源为例进行讲解,首先要确保pom.xml中要有Druid的的起步依赖配置

2.配置SqlSessionFactoryBean:SqlSessionFactoryBean来自mybatis-spring的整合包

    <!--配置SqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="mapperLocations" value="classpath:mapper/*.xml"></property>
        <property name="typeAliasesPackage" value="com.acoffee.maven"></property>
        <property name="configuration">
            <bean class="org.apache.ibatis.session.Configuration">
                <property name="lazyLoadingEnabled" value="true"></property>
                <property name="aggressiveLazyLoading" value="false"></property>
            </bean>
        </property>
    </bean>

这个sqlSessionFactory组件就相当于mybatis的配置文件.
逐个列出所有的SQL映射文件比较繁琐,在SqlSessionFactoryBean的配置中可以使用mapperlocations属性扫描式加载SQL映射文件

③掌握注入映射器

MyBatis中可以使用SqlSession的getMapper(Class< T> type)方法,根据指定的映射器和映射文件直接生成实现类,这样不必自行编写映射的实现类,就可以调用映射器的方法进行功能实现。

@Test
    public void testSingleParam(){
        SqlSession sqlSession = MyBatisUtil.createSession();
        AdminMapper adminMapper = sqlSession.getMapper(AdminMapper.class);

MyBatis-Spring中提供了MapperScannerConfigurer,它可以扫描指定包中的接口并将它直接注册为MapperFactoryBean。 MapperScannerConfigurer的配置方法如下示例所示:

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.acoffee.maven.mapper"></property>
    </bean>

1.basePackage属性中可以包含多个包名,多个包含之间使用逗号或分号隔开。

2.MapperScannerConfigurer会为所有又它创建的映射器实现开启自动装配,也就是说,MapperScannerConfigurer创建的所有映射器实现都会被自动注入SqlSessionFactory实例,因此在如上示例中配置DAO组件时无需显示注入SqlSessionFactory实例

3.如果只有一个sqlSessionFactory我们可以不用配置sqlSessionFactoryBeanName,它会自动依赖。但是若环境中出于不同目的配置了多个SqlSessionFactory实例,将无法进行自动装配,此时应显示指定所依赖的SqlSessionFactory实例,配置方式如下所示。

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.acoffee.maven.mapper"></property>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
    </bean>

注意这里使用的是sqlSessionFactoryBeanName属性而不是sqlSessionFactory属性,正如该属性名所表达的,这个属性关注的是Bean的名称,所以为其赋值使用的是value而不是ref。

ref和value的区别?
ref是引用(指针),value是布尔、string等的值。 用ref还是value,需要看源码里这个name是什么类型的!

映射器被注册到Spring容器时,Spring会根据其接口名称为其命名,默认规则是首字母小写的非完全限定类名。 例如EmpMapper类型的组件会被默认命名为empMapper

对应关系:
在这里插入图片描述

代码实现:
mapper接口(数据交互层):

public interface EmpMapper {
    public List<Emp> selectEmpsByDeptno(@Param("deptno") byte deptno);
    public Emp selectEmpByEmpno(@Param("empno") short empno);
}

public interface DeptMapper {
    public Dept selectDeptByDeptno(@Param("deptno") byte deptno);
    public Dept selectDeptByDeptnoWithStep(@Param("deptno") byte deptno);
}

类:

@Data
public class Dept {
    private byte deptno;
    private String dname;
    private String loc;
    private List<Emp> emps;
}

@Data
public class Emp {
    private short empno;
    private String ename;
    private String job;
    private short mgr;
    private Date hiredate;
    private double sal;
    private double comm;
    private Dept dept;
}

接口(业务层):

public interface DeptService {
    public Dept findDeptByDeptno(byte deptno);
}

实现类(业务):

@Service
public class DeptServiceImpl implements DeptService {
    @Autowired
    private DeptMapper deptMapper;
    @Override
    public Dept findDeptByDeptno(byte deptno) {
        return this.deptMapper.selectDeptByDeptno(deptno);
    }
}

beans.xml文件(就相当于将mybatis-config.xml融入在其中):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">

    <!--配置扫描包-->
    <context:component-scan base-package="com.acoffee.maven"></context:component-scan>

    <context:property-placeholder location="datasource.properties"></context:property-placeholder>
    <!--配置数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
        <property name="initialSize" value="${initialSize}"></property>
        <property name="maxWait" value="${maxWait}"></property>
        <property name="maxActive" value="${maxActive}"></property>
        <property name="minIdle" value="${minIdle}"></property>
    </bean>
    <!--配置SqlSessionFactory:相当于读取mybatis中的mybatis-config.xml文件-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="mapperLocations" value="classpath:mapper/*.xml"></property>
        <property name="typeAliasesPackage" value="com.acoffee.maven"></property>
        <property name="configuration">
            <bean class="org.apache.ibatis.session.Configuration">
                <property name="lazyLoadingEnabled" value="true"></property>
                <property name="aggressiveLazyLoading" value="false"></property>
            </bean>
        </property>
    </bean>
    <!--MapperScannerConfigurer会为所有它创建的映射器实现开启自动装配-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.acoffee.maven.mapper"></property>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
    </bean>
</beans>

测试类:

public class AppTest {

    private Logger logger = Logger.getLogger(this.getClass());

	//测试业务层
    @Test
    public void testSmService() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        DeptServiceImpl deptService = context.getBean("deptServiceImpl", DeptServiceImpl.class);
        Dept dept = deptService.findDeptByDeptno((byte) 10);
        logger.info("***********");
        logger.info(dept.getDeptno());
        logger.info(dept.getDname());
        logger.info(dept.getLoc());
        logger.info("该部门共有" + dept.getEmps().size() + "个员工");
        logger.info("***********");
        for (Emp emp:dept.getEmps()){
            logger.info(emp.getEmpno()+"\t"+emp.getSal());
        }
    }

	//测试数据交互层
    @Test
    public void testSmDao() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        DeptMapper deptMapper = context.getBean("deptMapper", DeptMapper.class);
        Dept dept = deptMapper.selectDeptByDeptno((byte) 10);
        logger.info("***********");
        logger.info(dept.getDeptno());
        logger.info(dept.getDname());
        logger.info(dept.getLoc());
        logger.info("该部门共有" + dept.getEmps().size() + "个员工");
        logger.info("***********");
        for (Emp emp:dept.getEmps()){
            logger.info(emp.getEmpno()+"\t"+emp.getSal());
        }
    }
}

执行结果:
在这里插入图片描述

二、Spring对MyBatis的整合(Mybatis使用注解)

Emp 类:

@Data
public class Emp {
    private short empno;
    private String ename;
    private String job;
    private short mgr;
    private Date hiredate;
    private short sal;
    private short comm;
    private byte deptno;
    private Dept depts;
}

Dept类:

@Data
public class Dept {
    private byte deptno;
    private String dname;
    private String loc;
    private List<Emp> emps;
}

deptMapper 接口(这里我们使用mapper注解:就相当于上面的DeptMapper.xml配置文件直接整合到了这个接口中):

@Mapper
public interface deptMapper {
    @Insert("insert into dept(deptno,dname,loc)values(#{deptno},#{dname},#{loc})")
    public void add(Dept dept);

    @Delete("delete from dept where deptno=#{deptno}")
    public void delete(byte deptno);

    @Update("update dept set dname=#{dname},loc=#{loc} where deptno=#{deptno}")
    public void update(Dept dept);

    @Results({
            @Result(property = "deptno",column = "deptno"),
            @Result(property = "dname",column = "dname"),
            @Result(property = "loc",column = "loc"),
            @Result(property = "emps",column = "deptno",many = @Many(select = "com.acoffee.maven.mapper.empMapper.selectEmpByDeptno",fetchType = FetchType.EAGER))
    })
    @Select("select * from dept where deptno=#{deptno}")
    public Dept selectOne(byte deptno);
    
    @Select("select * from dept")
    public List<Dept> selectAll();
}

empMapper 接口(与上述的deptMapper接口同理):

@Mapper
public interface empMapper {
    
    @Select("select * from emp where deptno=#{deptno}")
    public Emp selectEmpByDeptno(short deptno);

    @Results({
            @Result(property = "empno", column = "empno"),
            @Result(property = "ename", column = "ename"),
            @Result(property = "job", column = "job"),
            @Result(property = "mgr", column = "mgr"),
            @Result(property = "hiredate", column = "hiredate"),
            @Result(property = "sal", column = "sal"),
            @Result(property = "comm", column = "comm"),
            @Result(property = "depts", column = "deptno", one = @One(select = "com.acoffee.maven.mapper.deptMapper.selectOne", fetchType = FetchType.LAZY))
    })
    @Select("select * from emp where empno=#{empno}")
    public Emp selectDeptByEmpno(short empno);
}

beans.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!--配置扫描包-->
    <context:component-scan base-package="com.acoffee.maven"></context:component-scan>

    <context:property-placeholder location="datasource.properties"></context:property-placeholder>
    <!--配置数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
        <property name="initialSize" value="${initialSize}"></property>
        <property name="maxWait" value="${maxWait}"></property>
        <property name="maxActive" value="${maxActive}"></property>
        <property name="minIdle" value="${minIdle}"></property>
    </bean>
    <!--配置SqlSessionFactory:相当于读取mybatis中的mybatis-config.xml文件-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="typeAliasesPackage" value="com.acoffee.maven"></property>
        <!--configuration相当于mybatis-config.xmlsetting标签-->
        <property name="configuration">
            <bean class="org.apache.ibatis.session.Configuration">
                <property name="lazyLoadingEnabled" value="true"></property>
                <property name="aggressiveLazyLoading" value="false"></property>
            </bean>
        </property>
    </bean>
    <!--MapperScannerConfigurer会为所有又它创建的映射器实现开启自动装配-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.acoffee.maven.mapper"></property>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
    </bean>
</beans>

测试文件:

public class AppTest {

    private Logger logger = Logger.getLogger(this.getClass());

    @Test
    public void testSM() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        deptMapper deptMapper = context.getBean("deptMapper", deptMapper.class);
        List<Dept> depts = deptMapper.selectAll();

        for (Dept dept: depts){
            logger.info(dept);
        }
    }

    @Test
    public void testAdd(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        deptMapper deptMapper = context.getBean("deptMapper", deptMapper.class);
        Dept dept = new Dept();
        dept.setDeptno((byte)70);
        dept.setDname("Frank");
        dept.setLoc("Chengdu");
        deptMapper.add(dept);

    }
    @Test
    public void testDelete(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        deptMapper deptMapper = context.getBean("deptMapper", deptMapper.class);
        deptMapper.delete((byte) 70);

    }

    @Test
    public void testUpdate(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        deptMapper deptMapper = context.getBean("deptMapper", deptMapper.class);
        Dept dept = new Dept();
        dept.setDeptno((byte)60);
        dept.setDname("Frank");
        dept.setLoc("Chengdu");
        deptMapper.update(dept);
    }

    @Test
    public void testOneToMany(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        deptMapper deptMapper = context.getBean("deptMapper", deptMapper.class);
        Dept dept = deptMapper.selectOne((byte) 10);
        logger.info(dept.getDeptno()+"→ → →"+dept.getDname()+"→ → →"+dept.getLoc());
        for (Emp emp : dept.getEmps()) {
            logger.info(emp+"\n");
        }
    }
    @Test
    public void testManyToOne(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        empMapper empMapper = context.getBean("empMapper", empMapper.class);
        Emp emp =  empMapper.selectDeptByEmpno((short)7369);
        logger.info(emp.getEmpno()+"→ → →"+emp.getEname()+"→ → →"+emp.getSal()+"\n"+emp.getDepts());
    }
}

上述的测试文件中我们只展示最后的一对多、和多对一的结果:

testOneToMany的结果:
在这里插入图片描述
testManyToOne的结果:
在这里插入图片描述
多对一结果中出现列表的原因是不要以为 他是很多个对象 其实这个列表是一个Dept对象,出现列表的原因只是因为出现了这个部门(Dept对象)展示出了所有的Emp对象,为什么这个结果会展示出来呢?是因为我们在deptMapper接口中的selectOne中有Result注解,所以就将这个Dept对象中的所有的Emp对象都展示出来了,就像俄罗斯套娃一样。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值