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里不能用符号,因为跟标签的<>
是一样的,所以需要改成>
和<
;
事务
有个例子是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();
}
}
}
虽然文件是生成出来了,但是我还是决定自己去手写,看不懂,也不好改