一、配置日志(LOG4J)
使用日志可以监控SQL的执行情况,目前日志框架也非常成熟,如log4j。
1、加入依赖
<!--log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
2、加入配置文件,名称必须为:log4j.properties。(可以去网上拷贝一个
模板)
log4j.rootLogger=DEBUG,Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p - %m%n
log4j.logger.org.apache=INFO
3、效果
二、全局配置(mybatis-config.xml)
1、配置文件头(固定写法,建议不要手写,从官网拷贝,或自己保存为一个模板,其中dtd为标签约束文 件,当电脑联网会自动下载,否则没有提示)
<?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">
2、configuration
<configuration>
<!-- configuration:配置,所有的配置必须在该标签中 -->
</configuration>
3、configuration标签下子标签的顺序
properties
,settings
,typeAliases
,typeHandlers
,objectFactory
,objectWrapperFactory
,reflectorFactory
,plugins
,environments
,databaseIdProvider
,mappers
如果不按这个顺序编写会出现以下报错
3、properties:配置全局参数
<!-- 配置全局参数 -->
<properties resource="h2jdbc.properties"/>
4、settings:设置选项
<settings>
<!-- 是否开启驼峰命名 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
其它设置参考官网文档
settings 的配置项很多,但是真正用到的不会太多,我们把常用的配置项研究清楚就可以了,比如关于缓存的 cacheEnabled,关于级联的lazyLoadingEnabled 和 aggressiveLazy Loading,关于自动映射的autoMappingBehavior和mapUnderscoreToCamelCase,关于执行器类型的defaultExecutorType 等。
5、typeAliases:别名设置
<!--别名设置-->
<typeAliases>
<!-- 设置单个别名 -->
<typeAlias type="org.example.entity.Student" alias="Student"/>
<!-- 设置批量别名 -->
<!--<package name="org.example.entity"/>-->
</typeAliases>
注意:
- 不管是通过 typeAlias 标签配置,还是通过package 标签配置的别名,在mapper.xml文件中使用的时候,是可以忽略大小写的。
- 如果不手动设置别名,默认是类名的小写。
- 如果配置了注解别名,注解别名会覆盖上面的所有配置。
@Alias("stu")
public class Student {
...
}
6、environments
环境列表,表示在该标签下,可以配置多个environment标签,default可以指定一个默认环境。 使用场景:例如配置两个environment,一个为开发环境,一个为上线环境,开发时使用mysql,上线时使 用oracle。这样不用改变明细代码,而只用改变default就可以随意切换,非常方便。
<environments default="dev">
<environment id="dev">
<!--事务管理器配置-->
<transactionManager type="JDBC"/>
<!--数据源的配置-->
<dataSource type="POOLED">
<property name="driver" value="${h2jdbc.driver}"/>
<property name="url" value="${h2jdbc.url}"/>
<property name="username" value="${h2jdbc.username}"/>
<property name="password" value="${h2jdbc.password}"/>
</dataSource>
</environment>
</environments>
<environment id="development">
环境配置标签,id为该环境的唯一标识符<transactionManager type="JDBC" />
事务管理器配置,type="JDBC"表示使用JDBC自带的事务管理器,“JDBC”表示事务管理器的一个实 例,这里使用默认值即可。<dataSource type="POOLED">
数据源的配置,这里可以配置三种选项:- UNPOOLED:不使用连接池技术
- POOLED:使用连接池技术
- JNDI:使用JNDI的方式
7、mappers:映射器
1、概念
- 映射器是MyBatis最复杂、最核心的组件。
- 映射器提供DAO层接口到mapper.xml文件的映射,我们只需要调用DAO层的方法,就可以以执行对应的SQL语句,这里用到的是java的动态代理特性。
- mappers:配置mapper列表,专门放置我们写好的xxxMapper.xml配置文件。
- mapper:resource指定xxxMapper.xml配置文件的所在路径。
2、配置映射器
<!-- 配置mappers -->
<mappers>
<!-- 配置单个mapper,指定文件路径
resource:指定类路径下的映射文件路径
-->
<!--<mapper resource="StudentMapper.xml" />-->
<!-- 使用类名注册
1、指定xxxMapper映射接口的类路径
2、xxxMapper.xml文件要和映射接口在同一目录,且名称要保持一致。
3、没有sql映射文件,所有sql通过注解写在接口中。
-->
<!-- <mapper class="org.example.mapper.StudentMapper"/> -->
<!-- 批量注册:指定包名,全包扫描,但xml映射文件要和映射接口放在同一包下 -->
<package name="org.example.mapper"/>
</mappers>
3、使用注解配置(不需要sql映射文件)
public interface StudentMapper {
//根据id查询学生
@Select("select * from student where id=#{id}")
Student findById(Integer id);
}
注意:
- 注解虽然使用方便,但并不推荐,毕竟SQL写在代码中,产生了高耦合,维护起来不方便。
- 实际开发中,也可以混合使用,重要的复杂的写在xml中,不重要的简单的可以使用注解。
4、批量注册
批量注册:指定包名,全包扫描,但xml映射文件要和映射接口放在同一包下
<package name="org.example.mapper"/>
我们通常可以在资源包下,创建一个和映射接口一模一样的文件。
三、增删改查
增删改查的接口定义方法和映射配置如下:
1、CRUD
1、insert --映射插入语句
接口(StudentMapper.java
):
//新增学生
int insert(Student stu);
xml(StudentMapper.xml
)
<!--新增学生-->
<insert id="insert" parameterType="Student">
insert into student values(null,#{name},#{age},#{email})
</insert>
2、delete – 映射删除语句
接口(StudentMapper.java
):
//删除学生
Boolean delete(Integer id);
xml(StudentMapper.xml
)
<!--删除学生-->
<delete id="delete" parameterType="Integer">
delete from student where id=#{id}
</delete>
3、update --映射更新语句
接口(StudentMapper.java
):
//更新学生
Boolean update(Student stu);
xml(StudentMapper.xml
)
<!--更新学生-->
<update id="update" parameterType="Student">
update student set name=#{name},age=#{age},email=#{email} where id=#{id}
</update>
4、select – 映射查询语句
接口(StudentMapper.java
):
//根据id查询学生
Student getStuById(Integer id);
xml(StudentMapper.xml
)
<!--根据id查询学生-->
<select id="getStuById" resultType="Student">
select id,name,age,email from student where id = #{id}
</select>
2、注意事项
1)parameterType(参数类型)可以省略,resultType(返回类型)不能省略。
2)mybatis允许增删改直接定义以下类型返回值
- 只需要在接口上设置返回值类型,mybatis就可以自动为我们返回相应类型的执行结果。
- Integer、Long、Boolean、void包装类和基本类型都。
3)事务提交
- SqlSession默认是手动提交事务,如需自动提交,在参数中设置true。
- sqlSessionFactory().openSession()—>手动提交事务
- sqlSessionFactory().openSession(true)—>自动提交事务
4)获取添加操作后的主键值
在映射配置中增加:
- useGeneratedKeys=“true”:使用自增主键获取主键策略
- keyProperty=“id”:指定对应的主键属性,也就是mybatis获取到主键值后,将这个值放到JavaBean的
哪个属性中。
例如:
<!--新增学生。添加后返回记录的id需配置useGeneratedKeys="true" keyProperty="id"-->
<insert id="insert" parameterType="Student" useGeneratedKeys="true" keyProperty="id">
insert into student values(null,#{name},#{age},#{email})
</insert>
四、注解
在Mapper接口中,可以使用Annotation完成SQL映射
1、@Select
相当于<select>
元素
@Select("select * from student")
List<Student> list();
2、@Insert
相当于<insert>
元素
@Insert("insert into student values(#{id},#{name},#{age},#{email})")
int insert2(Student stu);
如果要获取主键id,可以使用@Option注解
@Insert("insert into student values(#{id},#{name},#{age},#{email})")
@Options(useGeneratedKeys = true,keyColumn = "id",keyProperty = "id")
int insert2(Student stu);
3、@Delete
相当于<delete>
元素
//删除学生2
@Delete("delete from student where id = #{id}")
boolean delete2(Integer id);
4、@Update
相当于<update>
元素
@Update("update student set name=#{name},age=#{age},email=#{email} where id=#{id}")
int update2(Student stu);
5、什么时候用注解?
通常情况下,如果比较简单的SQL,可以使用注解,如果比较复杂,还是建议写到配置文件中。在开发的时候,也可以使用注解+配置文件的混合方式。
五、映射配置
1、单个参数
mybatis不会做任何处理,使用#{参数名}的方式即可,且参数名没有要求。 也就是#{}中的参数既可以写id,也可以写其它名称。
<select id="getStuById" resultType="Student">
select id,name,age,email from student where id = #{id}
</select>
2、多个参数
1)有多个参数的时候,用上述方法就会抛出异常:
org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: org.apache.ibatis.binding.BindingException: Parameter 'id' not found. Available parameters are [arg1, arg0, param1, param2]
### Cause: org.apache.ibatis.binding.BindingException: Parameter 'id' not found. Available parameters are [arg1, arg0, param1, param2]
2)当有多个参数的时候,mybatis会做特殊处理,把参数封装到一个Map中,key为param+下标的方式:param1,param2,…,#{param1},#{param2}
<select id="findByMap" resultType="Student">
select id,name,age,email
from student
where id=#{param1} and name=#{param2}
</select>
3)使用注解
当参数很多,上述处理容易写错,也不方便,我们希望和接口中定义的方法参数名保持一致,可以在接口参数前使用注解:@param
Student findByIdAndName(@Param("id") Integer id, @Param("name") String name);
在映射配置中和注解的名称对应起来:
<select id="findByMap" resultType="Student">
select id,name,age,email
from student
where id=#{id} and name=#{name}
</select>
3、对象参数
如果多个参数正好和我们的实体类对应,我们就可以直接传入对象。
#{属性名}:取出传入pojo的属性值
4、Map参数
如果多个参数和我们的实体类不对应,为了方便,我们也可以传入Map类型。
#{key}:取出map中对应的值
接口:
Student findByMap(Map<String, Object> map);
映射配置:
<select id="findByMap" resultType="Student">
select id,name,age,email
from student
where id=#{id} and name=#{name}
</select>
测试:
/**
* 测试findByMap
*/
@Test
public void testFindByMap(){
SqlSession session = sqlSessionFactory.openSession();
try{
//获取Mapper对象
StudentMapper mapper = session.getMapper(StudentMapper.class);
//调用对象的方法
Map<String, Object> map = new HashMap<String, Object>();
map.put("id", "8");
map.put("name", "老狗");
Student stu = mapper.findByMap(map);
//打印
System.out.println(stu);
}finally{
session.close();
}
}
5、Collection作为参数
如果参数类型是集合,例如List、Set、数组(Array),也会进行特殊处理,mybatis会对List进行Map封 装,需要使用key来获取,此处可以使用三种key:
- #{arg0[index]}
- #{collection[index]}
- #{list[index]}
如果是数组:#{array[index]}
6、#{}和${}的区别
- #{}:以预编译的形式,将参数设置到sql语句中,相当于PreparedStatment,防止SQL注入
- ${}:取出的值直接拼接在sql语句中,相当于Statment,会有安全问题
通常情况下,我们会使用#{}居多,不过在SQL中需要拼接时,就会用到${}的方式。
例如:我们以下列代码为例,id使用${}的方式获取,name使用#{}的方式获取
<select id="findByIdAndName" resultType="Student">
select id,name,age,email
from student
where id=${id} and name=#{name}
</select>
运行测试类,我们看控制台的输出结果:
六、返回类型的处理
1、查询返回List
注意:在映射配置中,返回类型依然是集合中对象的类型,而非List
<!--模糊查询List<Student> findByLike(String str);-->
<select id="findByLike" resultType="com.turing.entity.Student">
select id,name,age,email
from student
where name like #{str}
</select>
2、查询返回Map
注意:在映射配置中,返回类型如果是Map,类型写map即可。
<!--根据id查询学生对象,返回Map
Map<String, Object> findById2(int id);
-->
<select id="findByLike2" resultType="map">
select id,name,age,email
from student
where name like #{str}
</select>
3、多条记录封装成一个Map
例如:Map<Integer,Student>:key是记录中的主键,value是学生对象。
接口:
@MapKey("id")把id作为返回值map的key
Map<String, Student> findByLike3(String str);
映射文件:
<select id="findByLike3" resultType="Student">
select id,name,age,email
from student
where name like #{str}
</select>
测试类:
@Test
public void testFindByLike3(){
SqlSession session = sqlSessionFactory.openSession();
try{
//获取Mapper对象
StudentMapper mapper = session.getMapper(StudentMapper.class);
//调用对象的方法
Map<String, Student> map = mapper.findByLike3("%老%");
//打印
System.out.println(map);
}finally{
session.close();
}
}
完整代码
代码已托管在gitee上面,点击直达