MyBatis 基础操作
一、MyBatis框架
1.1 MyBatis简介
MyBatis是一个优秀的持久层框架,对jdbc操作数据库的过程进行封装,使开发者只需关注sql身,而不需要花费精力去处理诸如注册驱动,创建connection,创建statement,手动设置参数,结果集检索等jdbc复杂的过程代码。
MyBatis通过xml或者注解的方式将要执行的各种statement(statement,prepareStatement,CallableStatement)配置起来,并通过java对象和Statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射程java对象并返回。
1.2 JDBC操作数据库存在的问题
- 需要频繁创建和关闭与数据库的连接
使用数据库连接池解决。 - JDBC中的SQL语句存在硬编码问题,即sql语句不具有通用性,
改变sql代码 - 使用prepareStatement向占位符号传参数存在硬编码,因为sql语句的where条件不一定。
修改sql代码 - 对结果集解析存在硬编码,比如查询取结果时,需要指定列名。
将数据库记录封装成pojo对象解析比较方便。
1.3 MyBatis架构
MyBatis配置文件
MapperdStatement封装sql语句,Executor用来执行sql语句。
输入映射给占位符赋值
输出映射返回数据的原来的格式 -97
1.4 方式
一个xml文件对应一个接口,xml文件的名字与接口的名字一致。xml中sql语句的ID与接口中的方法名一致。
1.5 mybatis-config.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是mybatis配置文件的根标签,用来配置Mybatis运行环境等信息 -->
<configuration>
<settings>
<!-- 配置mybatis日志采用的是log4j -->
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
<!-- typeAliases用来设置类型别名 -->
<typeAliases>
<!-- typeAlias用来设置单个类型的别名 type:类的全限定名(全名) alias类型别名-->
<!-- <typeAlias type="com.xx.entity.Product" alias="product"/> -->
<!-- package用来批量取别名 name表示类的包名
注意:批量取别名规则:
如果类名是一个单词,那么别名是将类名首字母小写,举例:Product:product
如果类名是2个单词,那么别名是将第一个单词首字母小写,举例:ProductCatetory:productCategory
如果类名是3个及其以上单词,那么遵循驼峰表示,然后第一个单词首字母小写,举例:ProductCategoryVO:productCatetoryVO
-->
<package name="com.xx.entity"/>
</typeAliases>
<!-- environments用来配置mybatis运行环境:数据源、事务管理等 -->
<environments default="development">
<!-- environment:development运行时环境 -->
<environment id="development">
<!-- transactionManager:type表示mybatis的事务管理采用的是jdbc事务管理 -->
<transactionManager type="JDBC"/>
<!-- dataSource:表示mybatis所应用的数据源: POOLED:mybatis数据源采用的是数据库连接池-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/maven"/>
<property name="username" value="root"/>
<property name="password" value="123"/>
</dataSource>
</environment>
</environments>
<!-- mappers用来配置mybatis要加载的mapper.xml文件或者mapper接口 -->
<mappers>
<!-- 配置mapper.xml,mapper标签表示mybatis要加载的单个mapper.xml -->
<!-- mapper标签三个属性:
resouce:表示要加载项目中的mapper.xml文件的路径
url: 表示要加载本地硬盘上的哪个mapper.xml(目录)
class:表示要加载的mapper接口的路径
-->
<!-- <mapper class="com.xx.mapper.ProductMapper" /> -->
<!-- 批量加载mapper接口|mapper.xml ,name属性表示批量加载mapper文件的所在包的包名-->
<package name="com.xx.mapper"/>
</mappers>
</configuration>
1.6 mapper.xml
namespace:当前xml所在的包名.xml文件名
paramtype:如果用到自定义的类,则是类所在的包名.类名
<?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是mapper.xml文件的根标签,mapper标签内,编写sql语句
namespace:命名空间,区分每个mapper.xml
取值格式:mapper文件所在包的包名.mapper文件名(不带后缀)
-->
<mapper namespace="com.xx.mapper.ProductMapper">
<!-- 新增商品信息 id:表示语句的id parameterType表示输入的参数类型,可以java的基础数据类型和引用数据类型-->
<insert id="saveProduct" parameterType="product">
<!-- #{}相当于? #{}中写输入参数的属性名-->
insert into t_product values(null,#{name},#{code},#{price},#{count},#{description},#{status},#{create_time})
</insert>
<!-- 将id是1的商品的价格修改为800 -->
<update id="updateProductById" parameterType="product">
update t_product set price=#{price} where id=#{id}
</update>
<!-- 删除id是2的商品信息
parameterType:如果是基础数据类型、String那么#{}中可以使任何变量名,包括中文和value
如果是引用数据类型(自定义的entity),那么#{}中必须是entity所包含的属性名
-->
<delete id="deleteProductById" parameterType="int">
delete from t_product where id=#{value}
</delete>
<!-- 查询id是5的商品信息 resultType:表示返回结果类型,可以是基础数据类型、引用数据类型 -->
<select id="selectProductById" parameterType="int" resultType="product">
select * from t_product where id=#{id}
</select>
<!-- 查询所有的商品信息,mytatis中如果 sql语句查询的结果是一个List,那么resultType不取值为list,而取值为List所能包含的数据类型 -->
<select id="selectAllProduct" resultType="product">
select * from t_product
</select>
<insert id="saveProductReturnPK" parameterType="product">
<!-- selectKey在新增返回主键值时使用,表示查询主键的值,绑定给某个列或者类的某个属性
keyProperty:新增后返回的主键值赋给类的哪个属性
order:取值BEFOR:在执行insert 语句之前执行select LAST_INSERT_ID() ,将查询到的结果绑定到keyProperty
AFTER:在执行insert语句之后再去执行select LAST_INSERT_ID(),将查询到的结果绑定到keyProperty
mysql新增返回主键的值order取值AFTER
-->
<selectKey keyProperty="id" resultType="int" order="AFTER">
select LAST_INSERT_ID()
</selectKey>
insert into t_product values(null,#{name},#{code},#{price},#{count},#{description},#{status},#{create_time})
</insert>
</mapper>
1.7 mapper对应的接口
package com.xx.mapper;
import java.util.List;
import com.xx.entity.Product;
public interface ProductMapper {
public void saveProduct(Product product);
public void deleteProductById(int id);
public void updateProductById(Product product);
public Product selectProductById(int id);
public List<Product> selectAllProduct();
}
1.8 创建测试类一般步骤
- 使用Resource工具类,用来读取mybatis配置文件(获取原材料)
InputStream inputStream = Resources.getResourceAsStream(“mybatis-config.xml”); - 通过SqlSessionFactoryBuilder类获得SqlSessionFactory 对象(建造工厂)
SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(inputStream); - 得到SqlSession对象(工厂造工具)
SqlSession sqlSession = sf.openSession(); - 获取mapper对象(工具交给用户)
ProductMapper productMapper = sqlSession.getMapper(ProductMapper.class); - 执行接口里的方法(用户使用工具)
… - 提交事务
sqlSession.commit() - 关闭资源
sqlSession.close()
1.9 查询数据库操作
xml文件的配置:
<select id="selStu" parameterType="int" resultType="com.xx.entity.Student">
select * from Student where id=#{id}
</select>
@Test
public void SelStu() throws IOException{
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = build.openSession();
studentMapper mapper = sqlSession.getMapper(studentMapper.class);
ArrayList<Student> list = mapper.selStu(13);
for(Student stu1:list){
System.out.println(stu1.getId() + stu1.getSname());
}
sqlSession.commit();
sqlSession.close();
}
查询结果的返回类型是集合类型,resultType可以用集合中元素的类型都代替。
1.10 修改数据库操作
xml文件的配置:
<update id="updateSth" parameterType="com.xx.entity.Student">
update Student set sname=#{sname} where id=#{id}
</update>
@Test
public void updateSth() throws IOException{
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(in);
SqlSession openSession = build.openSession();
studentMapper mapper = openSession.getMapper(studentMapper.class);
Student student = new Student();
student.setId(12);
student.setSname("wangwu");
mapper.updateSth(student);
openSession.commit();
openSession.close();
}
传入多个参数,可以以实体类来代替
1.11 删除操作
<delete id="deleteSth" parameterType="int">
delete from Student where id=#{id}
</delete>
@Test
public void deleteSth() throws IOException{
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(in);
SqlSession openSession = build.openSession();
studentMapper mapper = openSession.getMapper(studentMapper.class);
mapper.deleteSth(12);
openSession.commit();
openSession.close();
}
1. 12 模糊查询
- xml文件:
两种都可以,推荐第二种
<select id="selLike" parameterType="String" resultType="student">
select * from Student where sname like #{name}
</select>
<select id="selLike" parameterType="String" resultType="student">
select * from Student where sname like CONCAT(CONCAT('%',#{name}),'%')
</select>
<select id="selLike" parameterType="String" resultType="student">
select * from Student where sname like '%${value}%'
</select>
Test测试:
@Test
public void selLike() throws IOException{
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(in);
SqlSession openSession = build.openSession();
studentMapper mapper = openSession.getMapper(studentMapper.class);
String name = "%li%";
mapper.selLike(name);
openSession.commit();
openSession.close();
}
1.13 插入操作
<insert id="saveStu" parameterType="com.xx.entity.Student">
insert into Student values(#{id}, #{sname})
</insert>
@Test
public void insertStu() throws IOException{
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession openSession = build.openSession();
studentMapper mapper = openSession.getMapper(studentMapper.class);
Student stu = new Student();
stu.setId(13);
stu.setSname("lisi");
mapper.saveStu(stu);
System.out.println("操作成功");
openSession.commit();
openSession.close();
}
1.14 TypeAlise类型短名
- mybatis-config.xml文件下的操作:
注意:批量取别名规则:
* 如果类名是一个单词,那么别名是将类名首字母小写,举例:Product:product
* 如果类名是2个单词,那么别名是将第一个单词首字母小写,举例:
* 如果类名是3个及其以上单词,那么遵循驼峰表示,然后第一个单词首字母小写,举例:ProductCategoryVO:productCatetoryVO
<configuration>
<settings>
<typeAlise>
<!--单个包取别名-->
<!--<typeAlise type="com.xx.entity.xx" alias="xx">-->
<!--package 批量取别名--->
<!--该包下的所有类都取别名-->
<package name="xom.xx.entity>
</typeAlise>
</settings>
</configuration>
在mapper.xml文件中,xx就代表com.xx.entity.xx
1.15 TypeHandler
将java类型与jdbc类型互换
二、 log4j
2.1 log4j概述
Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。
2.2 Log4j在mybatis-config.xml中配置
<configruation>
<settings>
<!-- 配置mybatis日志采用的是log4j -->
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
</configruation>
2.3 log4j在scr路径下加入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
2.4 #{}与${}的区别
- #{}相当于占位符,${}相当于字符串拼接符
- 当parameterType是基础数据类型以及String类型时#{}中可以是任意变量符,当parameterType是其他引用数据类型时#{}中是引用数据的属性名
- 当parameterType是基础数据类型以及String类型时 ${}中只能是value,当parameterType是其他引用数据类型时 ${}中是引用数据的属性名
- #{}解决了sql注入,${}存在sql注入
三、 动态Sql
3.1 概述
根据不同执行条件产生不同的结构的Sql语句,这种变化的sql语句叫做做动态Sql语句。动态sql主要包括:判断,分支,循环,where,set,trim等标签