MyBatis学习(五)

Spring和MyBaits整合

1、整合思路

  • 需要spring通过单例方式管理SqlSessionFactory。
  • spring和mybatis整合生成代理对象,使用SqlSessionFactory创建SqlSession。(spring和mybatis整合自动完成)
  • 持久层的mapper都需要由spring进行管理。

2、整合环境

3、SqlSessionFactory

  • 在applicationContext.xml配置sqlSessionFactory和数据源
  • sqlSessionFactory在mybatis和spring的整合包下。
    <?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:util="http://www.springframework.org/schema/util"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
            http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd">
    
        <!-- 加载配置文件 -->
        <context:property-placeholder location="classpath:jdbc.properties" />
    
        <!-- 数据源 -->
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="${jdbc.driver}" />
            <property name="url" value="${jdbc.url}" />
            <property name="username" value="${jdbc.user}" />
            <property name="password" value="${jdbc.password}" />
        </bean>
    
    
        <!-- sqlSessinFactory -->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <!-- 加载mybatis的配置文件 -->
            <property name="configLocation" value="ecut/spring/mybaits-config.xml" />
            <!-- 数据源 -->
            <property name="dataSource" ref="dataSource" />
        </bean>
    </beans>

4、原始dao开发(和spring整合后)

  • 映射文件RoleMapper.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">
    
    <!-- namespace命名空间,作用就是对sql进行分类化管理,理解sql隔离 注意:使用mapper代理方法开发,namespace有特殊重要的作用 -->
    <mapper namespace="ecut.spring.mapper.RoleMapper">
    
        <select id="getRole" parameterType="java.lang.Integer"
            resultType="Role">
            SELECT id , role_name as roleName , note FROM t_role WHERE id = #{value}
        </select>
    
    </mapper>
  • 配置文件mybaits-config.xml
    <?xml version="1.0" encoding="UTF-8"?>
    
    <!DOCTYPE configuration
      PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
      "http://mybatis.org/dtd/mybatis-3-config.dtd">
    
    <configuration>
        <!-- 别名定义 -->
        <typeAliases>
            <typeAlias type="ecut.spring.po.Role" alias="Role"/>
        </typeAliases>
        <!-- 加载 映射文件 -->
        <mappers>
            
             <!--通过resource方法一次加载一个映射文件 -->
            <mapper resource="ecut/spring/mapper/Role.xml"/>
        </mappers>
        
    </configuration>
  • 接口dao
    package ecut.spring.dao;
    
    
    import ecut.spring.po.Role;
    
    public interface RoleDao {
        
        //根据id获取角色
        public Role getRole(Integer id) throws Exception ;
        
        
    }
  • 接口dao实现类(继承SqlSessionDaoSupport)
    package ecut.spring.dao;
    
    import org.apache.ibatis.session.SqlSession;
    import org.mybatis.spring.support.SqlSessionDaoSupport;
    
    import ecut.spring.po.Role;
    
    public class RoleDaoImpl extends SqlSessionDaoSupport implements RoleDao{
        //  SqlSessionDaoSupport有方法setSqlSessionFactory
        
        @Override
        public Role getRole(Integer id) throws Exception {
            //继承SqlSessionDaoSupport,通过this.getSqlSession()得到sqlSessoin
            SqlSession session =this.getSqlSession();
            //执行查询操作
            Role role = session.selectOne("test.getRole", id);
            // Spring 管理资源,使用完会自动关闭,释放资源
            return role;
        }
    
    }

    让RoleDaoImpl实现类继承SqlSessionDaoSupport,因为 SqlSessionDaoSupport有方法setSqlSessionFactory()方法,因此在applicationContext中使用提供setter方法进行注入,setter方法依赖于无参构造和setter方法,且在创建factory时候只需读取配置文件,因此在bean中需要配置configLocation属性。SqlSessionFactory通过Spring的配置文件注入,再由spring和mybatis整合自动完成SqlSessionFactory创建SqlSession。在接口实现类中通过this.getSqlSession()的方法获取到session完成操作。

    <!-- sqlSessinFactory -->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <!-- 加载mybatis的配置文件 -->
            <property name="configLocation" value="ecut/spring/mybaits-config.xml" />
            <!-- 数据源 -->
            <property name="dataSource" ref="dataSource" />
        </bean>
  • 配置dao
        <!-- 原始dao接口 -->
        
        <bean id="roleDao" class="ecut.spring.dao.RoleDaoImpl">
            <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
        </bean>

    在applicationContext.xml中配置dao。dao接口实现类需要注入SqlSessoinFactory,通过spring进行注入。

  • 测试类
    package ecut.spring.test;
    
    import java.io.IOException;
    
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    import org.springframework.context.support.AbstractApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import ecut.spring.dao.RoleDao;
    import ecut.spring.po.Role;
    
    
    public class RoleDaoImplTest {
        
        private AbstractApplicationContext container;
        
        private RoleDao roleDao;
        
        @Before
        public  void init() throws IOException {
            // 指定configuration metadata配置元数据
            String configLocations = "classpath:ecut/**/spring/applicationContext.xml";
            // 创建spring IOC容器
            container = new ClassPathXmlApplicationContext(configLocations);
            roleDao = (RoleDao) container.getBean("roleDao", RoleDao.class);
        }
    
        @Test
        public void testGetRole() throws Exception {
            // 从容器中获取的bean实例中获取属性值
            Role role = roleDao.getRole(1);
            System.out.println(role);
            
        }
        
        @After
        public void destroy(){
            // 关闭spring的IOC容器
            container.close();
        }
    }

 5、mapper代理开发

  • mapper类
    package ecut.spring.mapper;
    
    import ecut.spring.po.Role;
    
    public interface RoleMapper {
        
        //根据id获取角色
        public Role getRole(Integer id) throws Exception ;
        
    }
  • mapper配置文件
    <?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">
    
    <!-- namespace命名空间,作用就是对sql进行分类化管理,理解sql隔离 注意:使用mapper代理方法开发,namespace有特殊重要的作用 -->
    <mapper namespace="ecut.spring.mapper.RoleMapper">
    
        <select id="getRole" parameterType="java.lang.Integer"
            resultType="Role">
            SELECT id , role_name as roleName , note FROM t_role WHERE id = #{value}
        </select>
    
    </mapper>
  • 通过MapperFactoryBean创建代理对象
       <!-- mapper配置 
        MapperFactoryBean:根据mapper接口生成代理对象
        -->
        <bean id="roleMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
            <!-- mapperInterface指定mapper接口 -->
            <property name="mapperInterface" value=" ecut.spring.mapper.RoleMapper"/>
            <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
        </bean>

    不整合之前是要通过session去创建RoleMapper对象,再由mybaits自动生成的mapper代理对象

    SqlSession session = factory.openSession();
    //创建RoleMapper对象,mybaits自动生成的mapper代理对象
    RoleMapper roleMapper = session.getMapper(RoleMapper.class);

    通过MapperFactoryBean创建代理对象存在的问题:需要针对每个mapper进行配置,麻烦。

  • 通过MapperScannerConfigurer进行mapper扫描(建议使用)
        <!-- mapper批量扫描,从mapper包中扫描出mapper接口,自动创建代理对象并且在spring容器中注册 
        遵循规范:将mapper.java和mapper.xml映射文件名称保持一致,且在一个目录 中
        自动扫描出来的mapper的bean的id为mapper类名(首字母小写)
        -->
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <!-- 指定扫描的包名 
            如果扫描多个包,每个包中间使用半角逗号分隔 -->
            <property name="basePackage" value="ecut.spring.mapper"/>
            <!-- 不能使用  name="sqlSessionFactory" 会使数据源配置后执行-->
            <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
            
        </bean>

    若mapper 的名称是TRoleMapper自动扫描出来的mapper的bean的id为TRoleMapper而不是首字母小写tRoleMapper。可以根据日志来确定bean的id是多少,如RoleMapper的日志为DEBUG [main] - Creating shared instance of singleton bean 'roleMapper',则可以知道RoleMapper的id是roleMapper

  • 测试类
    package ecut.spring.test;
    
    import java.io.IOException;
    
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    import org.springframework.context.support.AbstractApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import ecut.spring.mapper.RoleMapper;
    import ecut.spring.po.Role;
    
    public class RoleMapperTest {
        
        private AbstractApplicationContext container;
        private RoleMapper roleMapper;
        
        @Before
        public  void init() throws IOException {
            // 指定configuration metadata配置元数据
            String configLocations = "classpath:ecut/**/spring/applicationContext.xml";
            // 创建spring IOC容器
            container = new ClassPathXmlApplicationContext(configLocations);
            roleMapper = (RoleMapper) container.getBean("roleMapper", RoleMapper.class);
        }
        
        @Test
        public void testGetRole() throws Exception {
            // 从容器中获取的bean实例中获取属性值
            Role role = roleMapper.getRole(1);
            System.out.println(role);
            
        }
        
        @After
        public void destroy(){
            // 关闭spring的IOC容器
            container.close();
        }
    }

逆向工程

1、什么是逆向工程

  • mybaits需要程序员自己编写sql语句,mybatis官方提供逆向工程 可以针对单表自动生成mybatis执行所需要的代码(mapper.java,mapper.xml、po..)
  • 企业实际开发中,常用的逆向工程方式:由于数据库的表生成java代码。

2、环境配置

jar包下载地址: http://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-core/1.3.7

3、使用方法

  • 运行逆向工程

    建议使用java程序方式,不依赖开发工具。

  • 生成代码的配置文件
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE generatorConfiguration
      PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
      "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
    
    <generatorConfiguration>
        <context id="testTables" targetRuntime="MyBatis3">
            <commentGenerator>
                <!-- 是否去除自动生成的注释 true:是 : false:否 -->
                <property name="suppressAllComments" value="true" />
            </commentGenerator>
            <!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
            <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                connectionURL="jdbc:mysql://localhost:3306/test" userId="root"
                password="123456">
            </jdbcConnection>
    
            <!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 和 
                NUMERIC 类型解析为java.math.BigDecimal -->
            <javaTypeResolver>
                <property name="forceBigDecimals" value="false" />
            </javaTypeResolver>
    
            <!-- targetProject:生成PO类的位置 -->
            <javaModelGenerator targetPackage="ecut.reverse.po"
                targetProject=".\src">
                <!-- enableSubPackages:是否让schema作为包的后缀 -->
                <property name="enableSubPackages" value="false" />
                <!-- 从数据库返回的值被清理前后的空格 -->
                <property name="trimStrings" value="true" />
            </javaModelGenerator>
            <!-- targetProject:mapper映射文件生成的位置 -->
            <sqlMapGenerator targetPackage="ecut.reverse.mapper" 
                targetProject=".\src">
                <!-- enableSubPackages:是否让schema作为包的后缀 -->
                <property name="enableSubPackages" value="false" />
            </sqlMapGenerator>
            <!-- targetPackage:mapper接口生成的位置 -->
            <javaClientGenerator type="XMLMAPPER"
                targetPackage="ecut.reverse.mapper" 
                targetProject=".\src">
                <!-- enableSubPackages:是否让schema作为包的后缀 -->
                <property name="enableSubPackages" value="false" />
            </javaClientGenerator>
            <!-- 指定数据库表 -->
            <table tableName="t_dubber"></table>
            <table tableName="t_comic"></table>
            <table tableName="t_role"></table>
            
            <!-- 有些表的字段需要指定java类型
             <table schema="" tableName="">
                <columnOverride column="" javaType="" />
            </table> -->
        </context>
    </generatorConfiguration>

    参照地址http://www.mybatis.org/generator/configreference/xmlconfig.html进行逆向工程配置文件配置

  • 执行生成程序
    package ecut.reverse;
    
    import java.io.File;
    import java.util.ArrayList;
    import java.util.List;
    
    import org.mybatis.generator.api.MyBatisGenerator;
    import org.mybatis.generator.config.Configuration;
    import org.mybatis.generator.config.xml.ConfigurationParser;
    import org.mybatis.generator.internal.DefaultShellCallback;
    
    public class GeneratorSqlmap {
    
        public void generator() throws Exception{
    
            List<String> warnings = new ArrayList<String>();
            boolean overwrite = true;
            //指定 逆向工程配置文件
            File configFile = new File("./src/generatorConfig.xml"); 
            ConfigurationParser cp = new ConfigurationParser(warnings);
            Configuration config = cp.parseConfiguration(configFile);
            DefaultShellCallback callback = new DefaultShellCallback(overwrite);
            MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config,
                    callback, warnings);
            myBatisGenerator.generate(null);
    
        } 
        public static void main(String[] args) throws Exception {
            try {
                GeneratorSqlmap generatorSqlmap = new GeneratorSqlmap();
                generatorSqlmap.generator();
            } catch (Exception e) {
                e.printStackTrace();
            }
            
        }
    
    }

    参照地址http://www.mybatis.org/generator/configreference/xmlconfig.html,运行后生成代码如下

  •  测试类

    package ecut.reverse.test;
    
    import java.io.IOException;
    import java.util.List;
    
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    import org.springframework.context.support.AbstractApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import ecut.reverse.mapper.TRoleMapper;
    import ecut.reverse.po.TRole;
    import ecut.reverse.po.TRoleExample;
    
    
    public class RoleTest {
    
        private AbstractApplicationContext container;
        
        private TRoleMapper roleMapper;
    
        @Before
        public  void init() throws IOException {
            // 指定configuration metadata配置元数据
            String configLocations = "classpath:ecut/**/reverse/applicationContext.xml";
            // 创建spring IOC容器
            container = new ClassPathXmlApplicationContext(configLocations);
            // 从容器中获取的bean实例中获取属性值
            roleMapper = (TRoleMapper) container.getBean("TRoleMapper", TRoleMapper.class);
        }
    
        //根据主键删除 
        @Test
        public void testDeleteByPrimaryKey() {
            roleMapper.deleteByPrimaryKey(8);
        }
    
        //插入
        @Test
        public void testInsert() {
            //构造 角色对象
            TRole role = new TRole();
            role.setRoleName("路飞");
            role.setNote("海贼王");
            role.setComicId(2);
            roleMapper.insert(role);
        }
    
        //自定义条件查询
        @Test
        public void testSelectByExample() {
            TRoleExample roleExample = new TRoleExample();
            //通过criteria构造查询条件
            TRoleExample.Criteria criteria = roleExample.createCriteria();
            criteria.andComicIdEqualTo(2);
            criteria.andIdGreaterThanOrEqualTo(2);
            //可能返回多条记录
            List<TRole> list = roleMapper.selectByExample(roleExample);
            
            for(TRole r:list){
                System.out.println("id="+r.getId()+",roleName="+r.getRoleName()+",note="+r.getNote()+",comicId="+r.getComicId());
            }
        }
    
        //根据主键查询
        @Test
        public void testSelectByPrimaryKey() {
            TRole role = roleMapper.selectByPrimaryKey(1);
            System.out.println("id="+role.getId()+",roleName="+role.getRoleName()+",note="+role.getNote()+",comicId="+role.getComicId());
        }
    
        //更新数据
        @Test
        public void testUpdateByPrimaryKey() {
            
            //对所有字段进行更新,需要先查询出来再更新
            TRole role = roleMapper.selectByPrimaryKey(8);
            
            role.setComicId(3);;
            //没有非空判断
            roleMapper.updateByPrimaryKey(role);
            //如果传入字段不空为才更新,在批量更新中使用此方法,不需要先查询再更新
            //roleMapper.updateByPrimaryKeySelective(record);
            
        }
        
        @After
        public void destroy(){
            // 关闭spring的IOC容器
            container.close();
        }
    
    }

    mapper 的名称是TRoleMapper自动扫描出来的mapper的bean的id为TRoleMapper而不是首字母小写tRoleMapper。可以根据日志来确定bean的id是多少,如TRoleMapper的日志为DEBUG [main] - Creating shared instance of singleton bean 'TRoleMapper',则可以知道TRoleMapper的id是TRoleMapper

MyBaits视频及资料

转载请于明显处标明出处

https://www.cnblogs.com/AmyZheng/p/9385887.html

posted @ 2018-07-29 19:14  AmyZheng  阅读(341)  评论(0编辑  收藏  举报