Mybatis学习
欢迎来到Mybatis学习
经过这么久终于还是决定对mybatis下手了,终于来到小白的ssm框架学习的最后一层框架----mybatis了。
Mybatis入门程序
先带大家快速入门一下mybatis吧,就先编写一个mybatis的入门程序。
先导入jar包
数据库里建好表,再建好表的关系映射在domain里,再在domain里面写一个customer.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="myTest">
<!--根据cust_id查询客户-->
<select id="queryCustomerById" parameterType="Int"
resultType="com.itlike.domain.Customer">
SELECT * FROM `customer` WHERE cust_id = #{cust_id}
</select>
</mapper>
建立一个SqlMappingConfig.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>
<!--配置sql打印-->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!-- spring整合后 environments配置将废除 使用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="1234" />
</dataSource>
</environment>
</environments>
<!--加载映射文件-->
<mappers>
<mapper resource="com/itlike/domain/Customer.xml"></mapper>
</mappers>
</configuration>
编写一个测试类:
public class MyTest {
@Test
public void test() throws IOException {
//1.sqlSessionFactoryBuilder 加载配置文件
SqlSessionFactoryBuilder sqlSessionFactoryBuilder= new SqlSessionFactoryBuilder();
//2.读取配置文件
InputStream resourceAsStream= Resources.getResourceAsStream("SqlMappingConfig.xml");
//3.获取session工厂
SqlSessionFactory sessionFactory= sqlSessionFactoryBuilder.build(resourceAsStream);
//4.获取会话=JDBC连接
SqlSession sqlSession= sessionFactory.openSession();
//5.执行sql
Customer queryCustomerById= sqlSession.selectOne("queryCustomerById", 2);
System.out.println(queryCustomerById);
//6.关闭session工厂
sqlSession.close();
}
}
执行sql语句那里要连接到customer.xml文件,之前在配置文件里写的是查询int类型的ID,所以就可以直接写id
然后就完成了,可以进行单元测试去验证自己的查询。
Mybatis整体架构:
SqlSessionFactoryBuilder主要是用来创建sqlsession的,创建好了就不需要了,所以创建工厂只需要创建一次,我们就可以把它封装到utils工具类里面,使用静态代码块只加载一次:
public class MybatisUtils {
private static final SqlSessionFactory sessionFactory ;
static {//1.sqlSessionFactoryBuilder 加载配置文件
SqlSessionFactoryBuilder sqlSessionFactoryBuilder= new SqlSessionFactoryBuilder();
//2.读取配置文件
InputStream resourceAsStream= null;
try {
resourceAsStream = Resources.getResourceAsStream("SqlMappingConfig.xml");
} catch (IOException e) {
e.printStackTrace();
}
//3.获取session工厂
sessionFactory= sqlSessionFactoryBuilder.build(resourceAsStream);}
public static SqlSession opensession(){
return sessionFactory.openSession();
}
}
就可以直接在测试类里面调用utils里面的opensession了:
SqlSession sqlSession = MybatisUtils.opensession();
测试结果与上面一致。
Mybatis增删改查
查询一条记录
<!--根据cust_id查询客户-->
<select id="queryCustomerById" parameterType="Int"
resultType="com.itlike.domain.Customer">
SELECT * FROM `customer` WHERE cust_id = #{cust_id}
</select>
@Test
public void test() throws IOException {
SqlSession sqlSession = MybatisUtils.opensession();
Customer queryCustomerById= sqlSession.selectOne("queryCustomerById", 2);
System.out.println(queryCustomerById);
sqlSession.close();
}
查询所有
上面已经通过ID查询进行了查询某一条记录的操作,现在我们进行查询所有的操作。表的配置文件里面写:
<!-- 查询所有-->
<select id="queryALLCustomer" resultType="com.itlike.domain.Customer">
SELECT * FROM `customer`
</select>
通过集合将表里的对象封装到一个List集合里面:
@Test
public void test2(){
SqlSession sqlSession= MybatisUtils.opensession();
List<Customer> queryALLCustomer= sqlSession.selectList("queryALLCustomer");
for (Customer customer : queryALLCustomer) {
System.out.println(customer);
}
}
模糊查询
查询姓李的记录
<!-- 模糊查询-->
<select id="queryLikeCustomer" parameterType="String" resultType="com.itlike.domain.Customer">
SELECT * FROM customer WHERE cust_name LIKE '%${value}%';
</select>
@Test
public void test3(){
SqlSession sqlSession = MybatisUtils.opensession();
List<Customer> queryLikeCustomer = sqlSession.selectList("queryLikeCustomer","李" );
for (Customer customer : queryLikeCustomer) {
System.out.println(customer);
}
sqlSession.close();
}
面试的时候可能会考#{ }和${ }的区别,需要注意一下:
但是${ }不能防止sql注入,所以我们可以这样写:
<select id="queryLikeCustomer" parameterType="String" resultType="com.itlike.domain.Customer">
SELECT * FROM customer WHERE cust_name LIKE #{cust_name};
</select>
因为#{ }传值的时候会将string类型的%李%将?替换掉,然后再在两边加上‘ ’ 所以得到的sql语句就是SELECT * FROM customer WHERE cust_name LIKE’%李%’,所以我们可以这样传值:
List<Customer> queryLikeCustomer = sqlSession.selectList("queryLikeCustomer","%李%" );
###插入操作
<!-- 插入记录-->
<insert id="insertCustomer" parameterType="com.itlike.domain.Customer">
insert into `customer`(cust_name,cust_profession,cust_phone,email)
values (#{cust_name},#{cust_profession},#{cust_phone},#{email})
</insert>
修改数据库当中的记录需要手动提交事务
@Test
public void insert(){
SqlSession sqlSession = MybatisUtils.opensession();
Customer customer= new Customer();
customer.setCust_name("卡特琳娜");
customer.setCust_profession("法刺");
customer.setCust_phone("13533941120");
customer.setEmail("123456852@qq.com");
sqlSession.insert("insertCustomer",customer);
// 手动提交事务
sqlSession.commit();
sqlSession.close();
}
更新与删除
更新:
<!-- 更新记录-->
<update id="updateCustomer" parameterType="com.itlike.domain.Customer">
UPDATE customer SET cust_name=#{cust_name} ,cust_profession=#{cust_profession} ,cust_phone=#{cust_phone},email=#{email}
WHERE cust_id=#{cust_id}
</update>
可以自己new一个customer对象,必须要有id,也可以像我这样查找一个id来进行修改
@Test
public void update(){
SqlSession sqlSession = MybatisUtils.opensession();
Customer queryCustomerById= sqlSession.selectOne("queryCustomerById", 14);
queryCustomerById.setCust_name("永恩");
queryCustomerById.setCust_profession("刺客");
queryCustomerById.setCust_phone("1234567897898");
queryCustomerById.setEmail("27315756557@qq.com");
sqlSession.insert("updateCustomer",queryCustomerById);
sqlSession.commit();
sqlSession.close();
}
删除:
<!-- 删除操作-->
<delete id="deleteCustomer" parameterType="com.itlike.domain.Customer">
delete from customer where cust_id=#{cust_id}
</delete>
@Test
public void dalete(){
SqlSession sqlSession = MybatisUtils.opensession();
sqlSession.delete("deleteCustomer",14);
sqlSession.commit();
sqlSession.close();
}
Mapper开发
使用动态代理实现开发,就不用再写接口然后写它的实现类那样麻烦了,就只需要添加映射之后定义接口即可,但是定义接口时必须满足它的规则
<mapper namespace="com.itlike.mapper.CustomerMapper">
<!--根据cust_id查询客户-->
<select id="queryCustomerById" parameterType="Integer"
resultType="com.itlike.domain.Customer">
SELECT * FROM `customer` WHERE cust_id = #{cust_id}
</select>
<!-- 查询所有-->
<select id="queryALLCustomer" resultType="com.itlike.domain.Customer">
SELECT * FROM `customer`
</select>
<!-- 模糊查询-->
<select id="queryLikeCustomer" parameterType="String" resultType="com.itlike.domain.Customer">
SELECT * FROM customer WHERE cust_name LIKE #{cust_name};
</select>
<!-- 插入记录-->
<insert id="insertCustomer" parameterType="com.itlike.domain.Customer">
!-- 更新记录-->
<update id="updateCustomer" parameterType="com.itlike.domain.Customer">
UPDATE customer SET cust_name=#{cust_name} ,cust_profession=#{cust_profession} ,cust_phone=#{cust_phone},email=#{email}
WHERE cust_id=#{cust_id}
</update>
<!-- 删除操作-->
<delete id="deleteCustomer" parameterType="com.itlike.domain.Customer">
delete from customer where cust_id=#{cust_id}
</delete>
</mapper>
定义接口的规则:
/*
使用动态代理必须遵守接口规则:
namespace必须与路径名一致
id必须和mapper接口方法名一致
parameterType必须与接口方法参数类型一致
resultType必须与接口方法返回值一致
* */
public interface CustomerMapper {
/*查询一个*/
public Customer queryCustomerById(Integer id);
//查询所有
public List<Customer> queryALLCustomer();
//模糊查询
public List<Customer> queryLikeCustomer(String name);
//添加
public void insertCustomer(Customer customer);
//更新
public void updateCustomer(Customer customer);
//删除
public void deleteCustomer(Customer customer);
}
这样就可以在测试类里面写测试了
@Test
public void test(){
SqlSession sqlSession = MybatisUtils.opensession();
CustomerMapper mapper= sqlSession.getMapper(CustomerMapper.class);
Customer customer = mapper.queryCustomerById(2);
System.out.println(customer);
List<Customer> customer1= mapper.queryALLCustomer();
for (Customer customer2 : customer1) {
System.out.println(customer2);
}
sqlsession.close();
}
就不一 一写了这里写了两个查询,注意要调用sqlsession的getMapper使用它里面的动态代理 ,然后就是最后记得关闭sqlsession
Mapper传参普通类型与@param
在mapper传参时如果是一个普通类型参数则可以直接通过mapper传进去,但是如果是多个参数例如:
select *from `customer` where cust_id=#{id} and cust_name=#{name}
这是就会报错
可以将{id}和{name}中的id跟name改为arg0和arg1或者param1和param
如果你想自己改为其他的就可以在mapper接口那里添加@param注解
public interface CustomerMapper {
public Customer queryCustomerWithID(@Param("id") Integer id,@Param("name") String name);
}
这时你{id}和{name}里面的值必须跟@param里面的值一样,就可以写成你自己想写的值了
map集合传参
还可以将要传的值添加到map集合里面,本质就是传了一个值
public interface CustomerMapper {
public Customer queryCustomerWithID(Map<String,Object> map);
}
@Test
public void getCustomer(){
SqlSession sqlSession = MybatisUtils.opensession();
CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);
HashMap<String, Object> customer = new HashMap<>();
customer.put("id",2);
customer.put("name","李白");
Customer customer1= mapper.queryCustomerWithID(customer);
System.out.println(customer1);
sqlSession.close();
}
这里map的key值必须跟前面映射里面的sql语句里的id跟name保持一致
POJO类型传参
就是普通类传参
public interface CustomerMapper {
public Customer queryCustomerWithID(Customer customer);
}
@Test
public void getCustomer(){
SqlSession sqlSession = MybatisUtils.opensession();
CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);
//POJO类型传参
Customer customer= new Customer();
customer.setCust_name("李白");
customer.setCust_id(2);
Customer customer1= mapper.queryCustomerWithID(customer);
System.out.println(customer1);
}
注意sql语句中的#{ }中的值必须跟类当中的字段保持一致
mybatis核心配置文件
在xml映射文件配置时下列标签要按照顺序来,因为它里面是有约束的,如果没有按顺序来就会报错,顺序如下图
properties标签
配置属性文件及读取属性文件
settings标签
这是mybatis中极为重要的调整设置,它们会改变mybatis的运行时的行为
,它里面有很多标签
<!--配置sql打印-->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
typeAliases
设置类型别名,是为java类型设置一个短的名字,可以定义单个别名也可以批量别名定义
<!-- 定义别名-->
<typeAliases>
<!-- 定义单个别名-->
<!-- <typeAlias alias="Customer" type="com.itlike.domain.Customer"/>-->
<!-- 批量定义别名,别名为类名-->
<package name="com.itlike.domain"/>
</typeAliases>
typeHandlers
类型处理器,开发当中一般很少使用,除非是你自己想要定义一些类型,才会来写它自己的一些处理器
Plugins
插件是mybatis提供的一个非常强大的机制,mybatis允许你在已映射语句执行过程中的某一点进行拦截调用,还可以通过插件修改mybatis的一些核心行为
Environments
mybatis可以配置多重环境,比如测试,开发和生产环境需要有不同的配置,每种环境通过Environment标签来配置并指定唯一标识符,可以通过Environments中的default属性指定一个环境的标识符来快速的切换属性,
spring整合后 environments配置将废除 使用spring中的连接池,就是说实际开发当中使用spring管理数据源
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理 -->
<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>
databaseIDprovider
mybatis可以根据不同的数据厂商执行不同的语句,可以通过databaseIDprovider标签来进行设置
mappers
加载映射文件
<!--加载映射文件-->
<mappers>
<mapper resource="com\itlike\domain\Customer.xml"></mapper>
<!--
1.名称必须和接口名称一致
2.必须和mapper接口在同一目录
-->
<!-- <mapper class="com.itlike.mapper.CustomerMapper"/>-->
<!-- <package name="com.itlike.mapper"/>-->
</mappers>
缓存
mybatis一级缓存
是sqlSession级别的一个缓存,本地缓存(默认开启),在sqlSession没有关闭之前再去查询时,会从缓存当中取出数据,不会发送新的sql
mybatis一级缓存失效情况
在下列情况中即使你没有关闭sqlSession,也还是会重新发送新的sql
1.如果在关闭之前,执行了增删改 缓存就会失效
2.手动清除缓存:sqlSession.clearcache()
3.如果两次查询的条件不一样也会失效
4.如果两个查询在不同的sqlSession当中
mybatis二级缓存
是mapper级别的一个缓存,全局作用域缓存一个namespace对应一个缓存,如果会话关闭,一级缓存的数据会被保存到二级缓存当中,不同namespace查出的数据会放到自己对应的缓存当中,现在默认也是打开的
1
<!-- 打开二级缓存-->
<setting name="cacheEnabled" value="true"/>
2
<!-- 二级缓存-->
<cache></cache>
3
public class Customer implements Serializable{
mybatis缓存相关配置项