Mybatis

心不动则不痛 提交于 2020-01-29 16:29:03

Mybatis知识点

  • 需要进行配置,查看前面的配置笔记
  • 分为两种写法,一种是注解,一种是xml文件
  • 事务
  • 缓存

注解写法

把JdbcTemplate改成Mybatis

// 把前面写个接口的service层的代码改成这个
// service/TestService.java

@Repository  // 同 @Controller
public class TestService {
    @Autowired
    private TestDao testDao;

    // 通过JdbcTemplate的方法才能操作数据库
    public ArrayList get(TestBean testBean) {
        return testDao.get(testBean);
    }
}
// dao/TestDao.java

public interface TestDao {
    @Select("select * from t_user where id = #{id}")
    ArrayList<TestBean> get(TestBean testBean);
    // 这个ArrayList是返回值的意思,select的返回值有bean,list
    // 其他的几个注解,增,改,删都是返回的数字Integer
}

注解有哪些

// 常用的
@Insert:实现新增 
@Update:实现更新 
@Delete:实现删除 
@Select:实现查询

// 不用的
@Result:实现结果集封装
@Results:可以与@Result 一起使用,封装多个结果集 
@ResultMap:实现引用@Results 定义的封装 
@One:实现一对一结果集封装 
@Many:实现一对多结果集封装 
@SelectProvider: 实现动态 SQL 映射 
@CacheNamespace:实现注解二级缓存的使用

这种复杂的注解我是没学的,很麻烦,很难记,只会用在简单的增删改查上,还有就是这种写法是拼接sql,一旦某个值没传,sql就是错的,所以一定要把必要的参数验证好

xml文件

  • 实现可传可不传的参数的查询,比如有些接口他可以不分页也可以分页
  • 复杂的多表查询
  • 同样全程需要bean的配合

实现一个可以不分页也可以分页的接口
可以写两个注解的接口,判断有没有传分页的参数决定用哪个接口,但是一旦也改动就得改很多接口,BUG就会被制造出来

// service/TestService.java

@Repository  // 同 @Controller
public class TestService {
    @Autowired
    private ItDaoImpl itDaoImpl;

    // 通过JdbcTemplate的方法才能操作数据库
    public ArrayList get(TestBean testBean) {
        return itDaoImpl.get(testBean);
    }
}
// dao/impl/ItDaoImpl.java

@Repository
public class ItDaoImpl {

    @Autowired
    private SqlSessionTemplate sqlSessionTemplate;

    public ArrayList get(TestBean testBean) {
        return (ArrayList) sqlSessionTemplate.selectList("mapper.TestDao.get",testBean);
    }
}
<!-- 需要再新建一个文件夹 ssm/mapper/test.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 + 下面的id 就是dao层的第一个参数 -->
<!-- 为什么不用TestDao,要用mapper.TestDao,因为要配合日记log4j记录-->
<mapper namespace="mapper.TestDao">
    <!-- parameterType就是你接受的参数的类型 -->
    <!-- 返回数据有两种写法,一是resultType,另一个是resultMap -->
    <select id="get" 
            parameterType="com.pdt.ssm.bean.TestBean"
            resultType="com.pdt.ssm.bean.TestBean" >
        select * from t_test
        <if test="pageSize != null and pageNo != null">
            limit #{pageNo},#{pageSize}
        </if>
    </select>
</mapper>

展示resultMap的使用
用于当多表查询后有多个表的数据相互掺杂使用,比如A表对于一个bean,B表对应一个bean,C表对应一个Bean,突然有需求需要三个表的相关数据,但是正常的做法是在A表的bean里加成员变量,如下

public class ABean {
    // 本来bean只有这两个字段的
    private String id;
    private String name;
    // 因为需求加两个
    private BBean bBean;
    private ArrayList<ABean> aBeanList;
}
<mapper namespace="mapper.ADao">
    <select id="test" 
            parameterType="com.pdt.ssm.bean.ABean"
            resultMap="TestMap" >
        // 逻辑就按需求来了,这里只做假设
        select A.id id,A.name name,B.id bId,B.name bName,C.id cId,C.name cName from t_A,t_B,t_C ...
    </select>
</mapper>

<resultMap id="TestMap" type="com.pdt.ssm.bean.ABean">
   <result column="id" property="id"></result>
   <result column="上面mapper查出来的字段name" property="bean里的key值"></result>

   <!-- 内嵌的另一个bean --> 
   <association property="bBean" javaType="com.pdt.ssm.bean.BBean">
     <result column="bId" property="id"></result>
     <result column="bName" property="name"></result>
   </association>

   <!-- 内嵌的另一个bean的ArrayList --> 
   <collection property="bean里的key值" ofType="com.pdt.ssm.bean.CBean">
     <result column="cId" property="id"></result>
     <result column="cName " property="name"></result>
   </collection>
</resultMap>

常用标签

<mapper namespace="id名字" >
   <select id="id名字" parameterType="com.pdt.ssm.bean.ABean" resultMap和resultType></select>
   <where></where>
   <when></when>
   <choose></choose>
   <if test="pageSize != null and pageNo != null"></if>
   <foreach collection="list" index="index" item="item" open="(" separator="," close=")"> #{item} </foreach>
</mapper>
<resultMap id="id名字" type="com.pdt.ssm.bean.ABean">
   <result column="id" property="id"></result>
   <!-- 内嵌的另一个bean --> 
   <association property="bBean" javaType="com.pdt.ssm.bean.BBean"></association>
   <!-- 内嵌的另一个bean的ArrayList --> 
   <collection property="bean里的key值" ofType="com.pdt.ssm.bean.CBean"></collection>
</resultMap>

有个注意的点是sql里的大于小于==在mapper里不能用符号==,因为跟标签的<>是一样的,所以需要改成&gt;&lt;

事务
有个例子是A向B转钱,A扣100,B还没加100程序报错,为了避免这个情况应该用事务,原理就是等整个程序运行完没问题再把数据提交,@Transactional

缓存
相关链接,没用过

逆向生成文件

<dependency>
     <groupId>org.mybatis.generator</groupId>
     <artifactId>mybatis-generator-core</artifactId>
     <version>1.3.5</version>
</dependency>
<!-- generatorConfig.xml 放在跟pom.xml同一级就行 -->

<?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/mydb"
                        userId="root"
                        password="123456">
        </jdbcConnection>

        <!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 和 NUMERIC 类型解析为java.math.BigDecimal -->
        <javaTypeResolver>
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>

        <!-- 生成模型(PO)的包名和位置 -->
        <javaModelGenerator targetPackage="com.shaw.bean"
                            targetProject="src/main/java">
            <!-- enableSubPackages:是否让schema作为包的后缀 -->
            <property name="enableSubPackages" value="false"/>
            <!-- 从数据库返回的值被清理前后的空格 -->
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>

        <!-- 生成映射文件的包名和位置-->
        <sqlMapGenerator targetPackage="mapper"
                         targetProject="src/main/resources">
            <!-- enableSubPackages:是否让schema作为包的后缀 -->
            <property name="enableSubPackages" value="false"/>
        </sqlMapGenerator>

        <!-- 生成DAO的包名和位置-->
        <javaClientGenerator type="XMLMAPPER"
                             targetPackage="com.shaw.dao"
                             targetProject="src/main/java">
            <!-- enableSubPackages:是否让schema作为包的后缀 -->
            <property name="enableSubPackages" value="false"/>
        </javaClientGenerator>

        <!-- 要生成的表 tableName是数据库中的表名或视图名 domainObjectName是实体类名-->
        <table tableName="t_it" domainObjectName="IT"/>
    </context>
</generatorConfiguration>
public class MyBatisGeneratorApp {
    public void generator() throws Exception{
        List<String> warnings = new ArrayList<String>();
        boolean overwrite = true;
        //指定 逆向工程配置文件
        File configFile = new File("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 {
            MyBatisGeneratorApp generatorSqlmap = new MyBatisGeneratorApp();
            generatorSqlmap.generator();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

虽然文件是生成出来了,但是我还是决定自己去手写,看不懂,也不好改

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!