#{}和${}
#{}:表示一个占个位符?
#{id}:里面的id表示输入参数的参数名称,如果该参数是简单类型,那么#{}里面的参数名称可以任意,如果该参数是POJO类型,那么#{}里面的参数名称必须与pojo的属性对应
${}:表示一个sql连接符
{value}:里面的value表示输入参数的参数名称,如果该参数是简单类型,那么${}里面的参数名称必须是value
${}的使用有sql攻击的风险,使用要慎重!!但在有些情况下必须使用${},比如排序时
主键自增返回
通过修改sql映射文件,可以将mysql自增主键返回:
<insert id="insertUser"parameterType="cn.itcast.mybatis.po.User">
<!-- selectKey将主键返回,需要再返回 -->
<selectKey keyProperty="id"order="AFTER"resultType="java.lang.Integer">
select LAST_INSERT_ID()
</selectKey>
insert into user(username,birthday,sex,address)
values(#{username},#{birthday},#{sex},#{address});
</insert>
添加selectKey实现将主键返回
keyProperty:返回的主键存储在pojo中的哪个属性
order:selectKey的执行顺序,是相对与insert语句来说,由于mysql的自增原理执行完insert语句之后才将主键生成,所以这里selectKey的执行顺序为after
resultType:返回的主键是什么类型
LAST_INSERT_ID():是mysql的函数,返回auto_increment自增列新记录id值。
uuid实现自增
需要增加通过select uuid()得到uuid值
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
<selectKey resultType="java.lang.String" order="BEFORE"
keyProperty="id">
select uuid()
</selectKey>
insert into user(id,username,birthday,sex,address)
values(#{id},#{username},#{birthday},#{sex},#{address})
</insert>
注意这里使用的order是“BEFORE”必须大写 AFTER或者BEFOR
mybatis开发dao的方式:
- 原始dao的开发方式:书写dao接口和接口实现类
- Mapper代理的开发方式:即开发mapper接口(相当于dao接口)
全局配置文件
SqlMapConfig.xml的配置内容和顺序如下(顺序不能乱):
Properties(属性)
Settings(全局参数设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境信息集合)
environment(单个环境信息)
transactionManager(事物)
dataSource(数据源)
mappers(映射器)
properties
<properties resource="">
<property name="" value="">
</property>
<properties>
加载的顺序
1、 先加载properties中property标签声明的属性
2、 再加载properties标签引入的java配置文件中的属性
3、 parameterType的值会和properties的属性值发生冲突。
<typeAliases>
<!--单个别名的定义 -->
<!-- <typeAlias type="com.pojo.User" alias="User" /> -->
<!-- 批量别名的定义 对指定包下的po持久类进行指定别名,默认别名为类名,不区分大小写-->
<package name="com.pojo"/>(推荐使用)
</typeAliases>
mapper
1、使用资源相对路径
<mapper resource=’’/>
2、使用绝对路径
<mapper url=’’/>
3、使用mapper接口的全路径名
<mapper class=’’/>
注意:此种方法要求mapper接口和mapper映射文件的名称相同,且放到同一个目录下;
4、注册指定包下的所有映射文件(推荐使用)
<package name=""/>
注意:此种方法要求mapper接口和mapper映射文件的名称相同,且放到同一个目录下;
映射文件
输入映射
- 简单类型
- Pojo类型
包装pojo类型:#{}中的参数名称要和包装pojo中的对象层级一致,并且属性名称要一致,写法像值栈,表达式封装的书写格式
Map:同传递POJO对象一样,map的key相当于pojo的属性
输出映射
resultType:
使用resultType进行结果映射时,需要查询出的列名和映射的对象的属性名一致,才能映射成功。 如果查询的列名和对象的属性名全部不一致,那么映射的对象为空。 如果查询的列名和对象的属性名有一个一致,那么映射的对象不为空,但是只有映射正确那一个属性才有值。 如果查询的sql的列名有别名,那么用这个别名和属性进行映射。
resultMap:使用resultMap进行结果映射时,不需要查询的列名和映射的属性名必须一致。但是需要声明一个resultMap,来对列名和属性名进行映射.
动态sql:
动态sql标签:if标签、where标签、sql片段、foreach标签 if标签:&&不能用,只能用and进行连接 where标签:默认去掉第一个and,如果都不存在则自己干掉 sql片段:可以定义sql语句任意的一部分,不建议将where和select写入,通过include标签引入sql片段
mybatis与hibernate的区别及各自应用场景
Mybatis技术特点:
1、 通过直接编写SQL语句,可以直接对SQL进行性能的优化;
2、 学习门槛低,学习成本低。只要有SQL基础,就可以学习mybatis,而且很容易上手;
3、 由于直接编写SQL语句,所以灵活多变,代码维护性更好。
4、 不能支持数据库无关性,即数据库发生变更,要写多套代码进行支持,移植性不好。
Hibernate技术特点:
1、 标准的orm框架,程序员不需要编写SQL语句。
2、 具有良好的数据库无关性,即数据库发生变化的话,代码无需再次编写。
3、 学习门槛高,需要对数据关系模型有良好的基础,而且在设置OR映射的时候,需要考虑好性能和对象模型的权衡。
4、 程序员不能自主的去进行SQL性能优化。
Mybatis应用场景:
需求多变的互联网项目,例如电商项目。
Hibernate应用场景:
需求明确、业务固定的项目,例如OA项目、ERP项目等。
高级结果映射
一对一
使用association标签进行配置
一对多
使用collection标签进行配置
多对多
使用association标签,collection标签进行嵌套配置
延迟加载
在mybatis中,resultMap标签的association标签和collection标签具有延迟加载的功能。
<!--将返回的结果映射在user类中 -->
<association property="user" select="com.mapper.OrderMapper.findUserById" column="user_id">
</association>
<settings>
<setting name="lazyLoadingEnabled" value="true" />
<setting name="aggressiveLazyLoading" value="false" />
</settings>
查询缓存
在mybatis中一级缓存是sqlsession范围的,与sqlsession对象有关,当事务提交了之后缓存中的数据就清空了
二级缓存是namespace范围的,所以mybatis的二级缓存对细颗粒度的数据,缓存不好,一旦一个商品的数据进行更新就要使得整个缓存的数据进行更新.
Spring和mybatis的整合(重点)
单个mapper代理类配置
<bean id="userMapper"class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value=""></property>
<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
</bean>
批量设置mapper代理类(默认生成的对象id为类名,第一个字母小写 )
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.map"></property>
</bean>
逆向工程
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
File configFile = new File("config/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);
<?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/mybatis" userId="root"
password="123">
</jdbcConnection>
<!-- <jdbcConnection driverClass="oracle.jdbc.OracleDriver" connectionURL="jdbc:oracle:thin:@127.0.0.1:1521:yycg"
userId="yycg" password="yycg"> </jdbcConnection> -->
<!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL
和 NUMERIC 类型解析为java.math.BigDecimal -->
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- targetProject:生成PO类的位置 -->
<javaModelGenerator targetPackage="com.po"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- targetProject:mapper映射文件生成的位置 -->
<sqlMapGenerator targetPackage="com.dao"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>
<!-- targetPackage:mapper接口生成的位置 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.dao" targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</javaClientGenerator>
<!-- 指定数据库表 -->
<table tableName="items"></table>
<table tableName="orders"></table>
<table tableName="orderdetail"></table>
<table tableName="user"></table>
</context>
</generatorConfiguration>