zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    新的开始
    0基础学习ios开发笔记第二天
    0基础学习ios开发笔记第一天
    Linux内核中SPI/I2c子系统剖析
    Linux内核之mmc子系统-sdio
    系统调用和中断处理的异同(以Linux MIPS为例)
    开始lisp的旅程
    Linux kernel驱动相关抽象概念及其实现 之“bus,device,driver”
    Linux kernel驱动相关抽象概念及其实现 之“linux设备模型kobject,kset,ktype”
    /etc/udev
  • 原文地址:https://www.cnblogs.com/AmyZheng/p/9385887.html
Copyright © 2011-2022 走看看