/**
* helloWorld的小结:
*
* 1.导入Mybatis的jar包
* 2.创建一个全局配置文件 mybatis-config.xml ,根据全局配置文件,创建了一个
SqlSessionFactory对象.
* 3.创建一个sql映射文件, EmployeeMapper.xml,该配置文件中配置了sql语句.
* 4.将sql映射文件注册到全局配置文件中
* 5.从SqlSessionFactory中获取SqlSession对象. sqlSession代表和数据库的一次会话.
* 然后调用selectOne("sql语句的唯一标识",执行sql的参数)完成查询操作.
* 6.最后将SqlSession对象关闭.释放资源.
*/
/**
* Mapper接口的好处:
* 1.接口中定义的方法明确的类型约束(方法参数的类型 方法返回值的类型)
* 2.接口本身:
* 接口本身就是抽象.抽出了规范.不强制要求如何做具体的实现.可以使用jdbc,
hibernate,Mybatis.
* 接口将规范与具体的实现分离.
* Mapper接口开发, MyBatis会为接口生成代理实现类。代理对象完成具体的增删改查操作.
* 最底层还是使用selectOne,update等方法来完成的.
*
* Mapper接口开发需要注意:
* 1.Mapper接口要与sql映射文件动态绑定. sql映射文件的namespace指定成接口的全类名.
* 2.Mapper接口方法与sql映射文件的sql语句绑定。 sql语句的id值指定成接口中的方法名.
*/
1.properties
<!--
1.properties: Mybatis可以是用properties来引入外部properties类型的文件.
resource: 引入类路径下的资源
url: 引入网络路径或者是磁盘路径下的资源
-->
<properties resource="db.properties" ></properties>
2.settings
<!--
2.settings: 包含了很多重要的设置项
setting: 用来设置每一个设置项
name:设置项的名称
value:设置项的值
-->
<settings>
<!-- 自动映射下划线到驼峰命名 DB: last_name autoMapping lastName -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
3.typeAliases
<!--
3.typeAliases:别名处理,为java 类型注册别名
typeAlias: 为某个java类指定别名
type: 指定java的类型(包名+ 类名
alias: 指定具体的别名。 如果alias不显示的指定,则默认的别名是类名的首字母小
写.
别名不区分大小写。
package: 批量取别名.
name:指定包名。 为该包下的所的类取默认的别名。
批量取别名可能会出现别名冲突的情况. 例如指定的包下与子包下相同的类.
可以使用@Alias("别名")在类上标注具体的别名.
-->
<typeAliases>
<package name="com.atguigu.mybatis.beans"/>
<!-- <typeAlias type="com.atguigu.mybatis.beans.Employee" alias="emp" /> -->
</typeAliases>
4.environments
<!--
4.environments: 环境们。 使用default来指定具体使用的环境.
environment:配置具体的环境.
id: 当前环境的标识
transactionManager:事务管理器
type: 配置具体的事务管理器的类型
JDBC: JdbcTransactionFactory
MANAGED:ManagedTransactionFactory
最终: 事务管理要交给Spring. 使用Spring的声明式事务.
dataSource:数据源
type: 执行数据源的类型.
UNPOOLED:不是用连接池 UnpooledDataSourceFactory
POOLED:使用连接池 PooledDataSourceFactory
JNDI:从web服务器中获取数据源. JndiDataSourceFactory
最终: 数据源交给Spring管理
-->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
</environment>
</environments>
5.databaseIdProvider
<!--
5.databaseIdProvider:
Mybatis用来支持多数据库厂商。Mybatis可以根据不同的数据库执行不同的sql语句
DB_VENDOR: VendorDatabaseIdProvider 作用就是得到数据库厂商的标识名.
Connection.getMetaData().getDataBaseProductName();
常见的数据库厂商的标识名:
MySQL: MySQL
Oracle: Oracle
SQL Server: SQL Server
-->
<databaseIdProvider type="DB_VENDOR">
<!-- 为数据库厂商的标识名起别名 -->
<property name="MySQL" value="mysql"/>
<property name="Oracle" value="oracle"/>
<property name="SQL Server" value="sqlserver"/>
</databaseIdProvider>
6.mappers
<!--
6.mappers: 引入sql映射文件
mapper: 引入单个的sql映射文件
resource: 引入类路径下的sql映射文件
url:引入网络路径或者是磁盘路径下的sql映射文件.
package: 批量引入sql映射文件
要求:
1.sql映射文件的名字与 Mapper接口的名字一致.
2.Sql映射文件与Mapper接口必须在同一目录下.
name:指定包名
-->
<mappers>
<!-- <mapper resource="mybatis/config/EmployeeMapper.xml"/> -->
<package name="com.atguigu.mybatis.dao"/>
</mappers>
1.增删改查
<insert id="" parameterType="" databaseId="" >
<update>
<delete>
<select id="" parameterType="" resultType="" databaseId="">
如果想要获取到增删改对数据的影响条数,可以直接在接口的方法中声明返回值类型即可.
2.主键自增以及主键值的返回
a.对于支持自增主键的数据库(Mysql),可以使用useGeneratedKeys=“true” keyProperty=“javaBean的属性”
b.对于不支持自增主键的数据库(oracle),使用selectKey的子标签完成主键值得返回.
selectKey的用法:
BEFORE: selectKey在插入语句之前执行
AFTER: selectKey在插入语句之后执行
c.Oracle数据库的自增策略:
使用序列模拟自增. 可以从序列中查询 nextval currval.
3.参数传递:
单个参数(普通类型(基本类型/包装类型+String)): Mybatis不会做特殊的处理
取值: #{参数名(随便写)} 取出参数值
多个参数:MyBatis会做特殊处理. 多个参数会被封装成一个Map。
封装map的规则:
key: param1 ,param2 , param3 … paramN / 0 1 2 …N-1
value:具体传入的参数值
异常: ### Cause: org.apache.ibatis.binding.BindingException: Parameter ‘id’ not found.
Available parameters are [1, 0, param1, param2]
解决: 取值使用#{param1/ 0} #{param2 / 1 }
命名参数**: 明确的指定多个参数封装map的时候所使用的key。 @Param(“key”)
取值: #{@Param指定的key/paramN}
POJO: 如果参数很多,正好又是业务逻辑的数据模型中的属性,直接传入POJO
取值: #{POJO的属性名}
Map: 如果参数很多,不是业务逻辑的数据模型中的属性,可以封装成map传入.
取值: #{map中的key}
参数处理的源码分析:
names={0=id,1=lastName}
args=[1001,Tom]
public Object getNamedParams(Object[] args) {
final int paramCount = names.size();
if (args == null || paramCount == 0) {
return null;
} else if (!hasParamAnnotation && paramCount == 1) {
return args[names.firstKey()];
} else {
final Map<String, Object> param = new ParamMap<Object>();
int i = 0;
for (Map.Entry<Integer, String> entry : names.entrySet()) {
param.put(entry.getValue(), args[entry.getKey()]);
// add generic param names (param1, param2, ...)
final String genericParamName = GENERIC_NAME_PREFIX + String.valueOf(i + 1);
// ensure not to overwrite parameter named with @Param
if (!names.containsValue(genericParamName)) {
param.put(genericParamName, args[entry.getKey()]);
}
i++;
}
return param;
}
参数值的获取方式:
#{}: 可以获取map中的值 或者是POJO对象属性的值。 还可以直接获取普通类型的参数.
${}: 可以获取map中的值 或者是POJO对象属性的值
区别:
#{}:是以预编译的形式将参数设置到sql语句中. PreparedStatement 防止sql注入.
KaTeX parse error: Expected 'EOF', got '#' at position 48: … 大部分情况下推荐使用#̲{},原生的jdbc不支持占位…{}来进行动态的赋值.
eg: select xxxxx from where 条件 order by 排序字段 排序方式 limit ?,?;
分表:
select * from 2016_salary ;
select * from 2017_salary ;
select * from ${year}_salary ;
用户选择2016年,则从2016_salary表查.