一、MyBatis 入门
1、架构:
- sqlMapConfig.xml文件(这个文件名可以自己定义)
- mapper.xml文件时sql的映射文件(这个文件需要在上边的sqlMapConfig.xml进行配置)
- 通过mybatis环境配置构造sqlSessionFactory会话工厂
- 会话工厂创建sqlSession会话
- mybatis底层自定义了Executor执行器接口操作数据库,两个接口实现,一个是基本实现,一个是缓存实现
- Mapped Statement 是mybatis的一个底层封装对象,包装了mybatis的配置信息,sql映射信息,mapper.xml中的一个sql对应一个mapped statement对象。so sql的id就是Mapped statement 的id
- Mapped Statement对sql执行输入参数进行定义,包括HashMap基本类型 pojo 。类似于jdbc的preparedStatement的参数设置。
- Mapped Statement对输出结果进行定义,包括hashMap 基本类型 pojo
2、下载
下载文件
- mybatis-x.x.x.jar核心包
- lib依赖包
3、入门程序
创建java工程
-
加入mybatis的核心包,依赖包,数据驱动包
- lib\asm-3.3.1.jar
lib\cglib-2.2.2.jar
lib\commons-logging-1.1.1.jar
lib\ehcache-core-2.6.5.jar
lib\javassist-3.17.1-GA.jar
lib\junit-4.9.jar
lib\log4j-1.2.17.jar
lib\log4j-api-2.0-rc1.jar
lib\log4j-core-2.0-rc1.jar
lib\mybatis-3.2.7.jar
lib\mybatis-ehcache-1.0.2.jar
lib\mysql-connector-java-5.1.7-bin.jar
lib\slf4j-api-1.7.5.jar
lib\slf4j-log4j12-1.7.5.jar
- lib\asm-3.3.1.jar
-
config目录下创建log4j.properties 创建输出日志
# Global logging configuration log4j.rootLogger=DEBUG, stdout # Console output... log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
-
创建SqlMapConfig.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> <!--jdbc的配置方式,spring中的配置方式--> <environments default="development"> <environment id="development"> <!-- 使用jdbc事务管理--> <transactionManager type="JDBC" /> <!-- 数据库连接池--> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" /> <property name="username" value="root" /> <property name="password" value="mysql" /> </dataSource> </environment> </environments> </configuration>
-
创建PO类
Public class User { private int id; private String username;// 用户姓名 private String sex;// 性别 private Date birthday;// 生日 private String address;// 地址 get/set……
-
程序编写-基本的操作*查询
- Users.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"> <mapper namespace="test"> </mapper>
- Users.xml
<select id="findUserById" parameterType="int" resultType="com.baip.po.User"> select * from user where id = #{id} </select> <!-- 自定义条件查询用户列表 --> <select id="findUserByUsername" parameterType="java.lang.String" resultType="com.baip.po.User"> select * from user where username like '%${value}%' </select>
paramterType定义输入到sql中映射类型,#{id}表示使用preparedstatement设置占位符号,并将输入变量id传到sql
resultType:定义结果映射类型
#{id}是进行映射的表示一个占位符号,可以实现preparedStatement向占位符中设置值,防止sql注入。如果传入的参数是简单类型,括号中可以是value或者是其他的名称。
${}是进行拼接的 ,不进行jdbc的类型转换,括号中只能是value- 加载映射文件,在SqlMapConfig.xml中
<mappers> <mapper resource="sqlmap/User.xml"/> </mappers>
- 测试程序
private SqlSessionFactory sqlSessionFactory; @Before public void createSqlSessionFactory() throws IOException { // 配置文件 String resource = "SqlMapConfig.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); // 使用SqlSessionFactoryBuilder从xml配置文件中创建SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder() .build(inputStream); }
@Test
public void testFindUserById() {
// 数据库会话实例
SqlSession sqlSession = null;
try {
// 创建数据库会话实例sqlSession
sqlSession = sqlSessionFactory.openSession();
// 查询单个记录,根据用户id查询用户信息
User user = sqlSession.selectOne("test.findUserById", 10);
// 输出用户信息
System.out.println(user);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (sqlSession != null) {
sqlSession.close();
}
}
}
```
-
新增* 自增键返回
User.xml中<insert id="insertUser" parameterType="com.baip.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>
- keyProperty 返回的主键放到pojo的哪个属性上
- order 执行顺序
- resultType查看返回的追歼类型
- LAST_INSERT_ID mysql的函数
关于主键的赋值方式可以是:
select uuid() SELECT 自定义序列.NEXTVAL FROM DUAL
二、Dao开发方法
上边的测试方法类似于传统的Dao方法,通过SqlSessionFactory创建sqlSession调用SqlSession的数据库方法
调用sqlSession的数据库方法执行statement的id存在硬编码,不利于开发维护。sqlSession.selectOne
这个selectOne就是Dao写的方法,这个就是硬编码
1、Mapper动态代理的方式
- 实现原理
Mapper接口开发方法中需要遵循如下的规范- Mapper.xml文件中的nameSpace和maper接口的类路径相同
- Mapper接口方法名和Mapper.xml中定义的id相同
- Maper接口中输入的参数类型和Mapper.xml中定义的每个sql的parameterType的类型相同
- Mapper接口中输出的参数类型和mapper.xml中定义的每个sql的result的类型相同
- Mapper.xml映射文件
<mapper namespace="com.baip.mapper.UserMapper"> <select id="findUserById" parameterType="int" resultType="com.baip.po.User"> select * from user where id = #{id} </select>
- Mapper.java接口文件:
注意相等的地方:Public interface UserMapper { //根据用户id查询用户信息 public User findUserById(int id) throws Exception; //查询用户列表 public List<User> findUserByUsername(String username) throws Exception; //添加用户信息 public void insertUser(User user)throws Exception; }
- UserMapper namespace 和interface的接口名一致
- findUserById id和方法名一致
- UserMapper的 findUserById方法参数 int类型和parameterType参数保持一致
- UserMapper的 findUserById方法返回参数 和 resultType保持一致
- 加载UserMapper.xml
在SqlMapConfig.xml中,加载映射文件<!-- 加载映射文件 --> <mappers> <mapper resource="mapper/UserMapper.xml"/> </mappers>
三、SqlMapConfig.xml配置文件
1、配置内容
从上到下依次:
- properties
- settings
- typeAliases(类型别名)
- typeHandlers(类型处理器)
- objectFactory对象工厂
- plugin(插件)
- environments(环境集合属性对象)
environment(环境子属性对象)
transactionManager(事务管理)
dataSource(数据源) - mappers映射器
2、properties
-
定义db.properties文件
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/mybatis jdbc.username=root jdbc.password=mysql
-
SqlMapConfig.xml中引用:
<properties resource="db.properties"/> <environments default="development"> <environment id="development"> <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>
mybatis对对应属性的加载顺序
- proerties元素内定义的属性首先被读取
- properties元素中的resource或者是url加载属性,会覆盖读取的同名属性
- 最后读取parameterType传递的属性,覆盖已经读取的同名属性
3、settings配置
<settings>
<!-- 打开延迟加载 的开关 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 将积极加载改为消极加载即按需要加载 -->
<setting name="aggressiveLazyLoading" value="false"/>
<!-- 开启二级缓存 -->
<setting name="cacheEnabled" value="true"/>
</settings>
4、typeAliases(类型别名)
别名 | 映射类型 |
---|---|
_byte | byte |
_long | long |
_short | short |
_int | int |
_integer | int |
_double | double |
_float | float |
_boolean | boolean |
string | String |
byte | Byte |
long | Long |
short | Short |
int | Integer |
integer | Integer |
double | Double |
float | Float |
boolean | Boolean |
date | Date |
decimal | BigDecimal |
bigdecimal | BigDecimal |
自定义别名
<typeAliases>
<!-- 单个别名定义 -->
<typeAlias alias="user" type="com.baip.po.User"/>
<!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以) -->
<package name="com.baip.po"/>
<package name="其它包"/>
</typeAliases>
5、mappers映射器
1.类型处理器用于java类型和jdbc类型映射,如下: <mapper resource="sqlmap/User.xml" />
<mapper url="file:///D:\workspace\mybatis_01\config\sqlmap\User.xml" />
-
<mapper class="com.baip.mapper.UserMapper"/>
此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。 -
<package name="com.baip.mapper"/>
注册指定包下的所有mapper接口 此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
6、Mapper.xml映射文件
6.1 parameterType
传递pojo对象
<select id='findUserByUser' paramterType="User" resultType="user">
select * from wehre id=#{id} and usernamelike '%${usernaem}%'
</select>
上边标注的是user对象中的字段名
传递hashmap
Sql映射文件定义如下:
<!-- 传递hashmap综合查询用户信息 -->
<select id="findUserByHashmap" parameterType="hashmap" resultType="user">
select * from user where id=#{id} and username like '%${username}%'
</select>
这里的id和username都是指hashMap的key
resultType总结
- 输出
pojo
对象和输出pojo
列表在sql
中定义resultType
是一样的 - 返回单个
pojo
对象要保证sql
查询出来的结果集为单条,内部使用session.selectOne
方法调用 - 返回
pojo
列表表示查询出来的结果集可能多条,内部使用session.selectList
方法,mapper
接口使用List<pojo>
对象作为方法返回值
7、动态sql
1、if
<!-- 传递pojo综合查询用户信息 -->
<select id="findUserList" parameterType="user" resultType="user">
select * from user
where 1=1
<if test="id!=null and id!=''">
and id=#{id}
</if>
<if test="username!=null and username!=''">
and username like '%${username}%'
</if>
</select>
2、where
自动处理第一个and
<select id="findUserList" parameterType="user" resultType="user">
select * from user
<where>
<if test="id!=null and id!=''">
and id=#{id}
</if>
<if test="username!=null and username!=''">
and username like '%${username}%'
</if>
</where>
</select>
3、foreach
向sql传递数组或List mybatis使用foreach解析
<if test="ids!=null and ids.size>0">
<foreach collection="ids" open=" and id in(" close=")" item="id" separator="," >
#{id}
</foreach>
</if>
8、sql片段
<sql id="query_user">
<if test="id!=null and id!=''">
and id=#{id}
</if>
<if test="username!=null and username!=''">
and username like '%${username}%'
</if>
</sql>
使用的时候,include
<select id="findUsers" parameterType="user" resultType="user">
select * from user
<where>
<include refid="namespace.query_user"/>
</where>
</select>
如果是其他的workspace里的代码片段,那就需要前边追加一个namespace
四、整合spring
通过spring管理sqlSessionFactory mapper接口
mybatis提供的spring整合jar包
mybatis-spring-x.x.x.jar
SqlMapConfig.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>
<!—使用自动扫描器时,mapper.xml文件如果和mapper.java接口在一个目录则此处不用定义mappers -->
<mappers>
<package name="cn.baip.mapper" />
</mappers>
</configuration>
applicationContext.xml 定义数据库连接池和sqlSessionFactory
<!-- 加载配置文件 -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 数据库连接池 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxActive" value="10"/>
<property name="maxIdle" value="5"/>
</bean>
<!-- mapper配置 -->
<!-- 让spring管理sqlsessionfactory 使用mybatis和spring整合包中的 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 数据库连接池 -->
<property name="dataSource" ref="dataSource" />
<!-- 加载mybatis的全局配置文件 -->
<property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml" />
</bean>
</beans>
1、Mapper Dao接口实现继承sqlSessionDaoSupport
- 在sqlMapConfig.xml中配置映射文件
<mappers> <mapper resource="mapper.xml文件的地址" /> <mapper resource="mapper.xml文件的地址" /> </mappers>
```
- 定义dao接口
- dao接口实现类集成SqlSessionDaoSupport
SqlSession sqlSession = this.getSqlSession(); User user = sqlSession.selectOne("test.findUserById", id); return user;
- spring配置
<bean id="" class="mapper接口实现"> <property name="sqlSessionFactory" ref="sqlSessionFactory" ></property> </bean>
2、使用org.mybatis.spring.mapper.MapperFactoryBean
- 在sqlMapConfig.xmlz中配置mapper.xml位置
- d定义接口
- spring中定义
<bean id="" class="org.mybatis.spring.mapper.MapperFactoryBean"> <property name="mapperInterface" value="mapper接口地址"/> <property name="sqlSessionFactory" ref="sqlSessionFactory"/> </bean>
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<!--mapperInterface指定mapper接口-->
<property name="mapperInterface" value="com.baip.ssm.mapper.UserMapper"/>
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
```
3、mapper扫描,感觉这个比较常用
mapper编写
-
定义mapper接口
注意mapper.xml的文件名和mapper的接口名保持一致,而且放在同一个目录下
-
配置mapper扫描在application中
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="mapper接口包地址"></property> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> </bean>
多个包的时候,中间可以用逗号或者是分号分割
spring容器中获取mapper的实现对象。
如果将mapper.xml 和mapper接口的名称保持一致,放在同一个目录下,不用在sqlMapConfig.xml中进行配置