一、Mybatis框架:
它是一个开源的(源代码开放),持久化的框架,其内部对JDBC进行了封装,开发人员只用关注sql代码的编写,而不用关心底层数据库的连接,结果集的遍历等执行。
它是一个半自动化的ORM(Object Relation Mapping)框架,实现了数据库表中字段与Java程序中实体类成员变量的映射(增、删、改、查)。sql语句执行完,会遵循这种映射关系对结果集进行封装。
二、MyBatis快速入门
1、在Mysql数据库中准备一个website(网站表)。
2、在src目录下,创建一个mybatis.entity包,并在此包下创建实体类(Website)。
实体类名要与数据库中表名一致,实体类中的成员变量名要与表中字段名一致,数据类型也要保持一致。
public class Website {
private int id;
private String name;
private String url;
private int age;
private int alexa;
private int uv;
private String country;
@Override
public String toString() {
return "Website [id=" + id + ", name=" + name + ", url=" + url + ", age=" + age + ", alexa=" + alexa + ", uv="
+ uv + ", country=" + country + "]";
}
}
3、在src目录下,创建一个mybatis.mapper包,并在此目录下创建一个WebsiteMapper.xml映射文件。
第一行是xml的版本号,字符编码集,第二三四行是一个dtd文件,里面大致规定了一些在此映射文件中节点之间先后顺序的编写要求等。
<?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属性:设置当前映射器的命令空间 -->
<!-- 一般命名为“此文件所在包名+映射文件名” -->
<mapper namespace="mybatis.mapper.WebsiteMapper">
<!-- 查询所有网站信息 -->
<!--ID属性:在此<mapper>节点中ID号唯一 -->
<!--resultType属性:查询出来的结果封装成哪一种类型对象 -->
<select id="selectAllWebsite"
resultType="mybatis.entity.Website">
select * from website
</select>
</mapper>
4、在src目录下,创建一个mybatis-config.xml主配置文件。
此文件中配置了MySQL数据库驱动,连接数据库的参数,日志信息,mybatis的运行环境和将mapper映射文件加载到主配置文件中。
<?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>
<settings>
<!-- 日志 -->
<setting name="logImpl" value="LOG4J" />
</settings>
<!-- 配置mybatis运行环境 -->
<environments default="development">
<environment id="development">
<!-- 使用JDBC的事务管理 -->
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<!-- MySQL数据库驱动 -->
<property name="driver" value="com.mysql.cj.jdbc.Driver" />
<!-- 连接数据库的URL -->
<property name="url"
value="jdbc:mysql://localhost:3306/test_db?charset=utf8mb4&useSSL=false&useTimezone=true&serverTimezone=GMT%2B8" />
<property name="username" value="root" />
<property name="password" value="密码" />
</dataSource>
</environment>
</environments>
<!-- 将mapper文件加入到配置文件中 -->
<mappers>
<mapper resource="mybatis/mapper/WebsiteMapper.xml" />
</mappers>
</configuration>
5.在src目录下创建mybatis.test包,并创建一个测试类(Test)。
public static void main(String[] args) throws IOException {
//SqlSessionFactoryBuilder建造者
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//通过SqlSessionFactoryBuilder建造者,创建SqlSessionFactory工厂
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sessionFactory = sqlSessionFactoryBuilder.build(in);
//通过SqlSessionFactory工厂,创建SqlSession
SqlSession sqlSession = sessionFactory.openSession();
//通过SqlSession查找SQL映射,并执行
//SQL映射的查找:通过命名空间+SQL映射ID
List<Website> websiteList = sqlSession.selectList("mybatis.mapper.WebsiteMapper.selectAllWebsite");
for(Website website:websiteList) {
System.out.println(website);
}
}
三、Mybatis核心对象
1、Mybatis的三个核心类(接口):SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession。
首先创建一个SqlSessionFactoryBuilder建造者,再通过建造者创建SqlSessionFactory工厂对象,获取SqlSessionFactory对象之后,再获取SqlSession实例。SqlSession里面包括了所有执行SQL操作的方法,用该实例可以直接执行已映射的SQL语言。
2、MyBatis工具类
//MyBatis工具类
public class MyBatisUtils {
//定义静态的全局的SqlSessionFactory变量
private static SqlSessionFactory factory = null;
static {
//写在静态代码块中,只会创建一次
String config = "mybatis-config.xml";
try {
InputStream in = Resources.getResourceAsStream(config);
factory = new SqlSessionFactoryBuilder().build(in);
} catch (IOException e) {
e.printStackTrace();
}
}
//方法的返回一个SqlSession实例
public static SqlSession getSqlSession() {
SqlSession sqlSession = null;
if(factory != null) {
sqlSession = factory.openSession();
}
return sqlSession;
}
}
四、Mapper映射器
由映射器接口和XML文件组成。
1、添加语句(例:添加网站)
映射器接口:接口名称必须与xml配置文件中的namespace保持一致。
接口中方法名称必须与对应的SQL映射操作ID保持一致;参数类型保持一致。
在MyBatis中,MyBatis映射接口中方法不允许重载,因为每个方法名都将被作为一个Mapped Statement的一个ID。在Mapped Statement中ID不能重名(每个ID都在映射接口中对应一个方法,ID不能重名,所以方法名也不能重名)。
int insertWebsite(Website website);
XML文件:所有的标签必须写在<mapper></mapper>标签中,mapper标签中要有namespace属性(设置当前映射器的命令空间,此名称要与映射器接口名称一致)。
添加语句写在<insert></insert>标签中,此标签由如下属性:
id属性:SQL映射的名称。
parameterType属性:传入参数的类型(实体类)。
#{属性}:获取传入对象的某个属性值。
<insert id="insertWebsite" parameterType="com.apesource.entity.Website">
insert into website (name,url,age,alexa,uv,country) values(#{name},#{url},#{age},
#{alexa},#{uv},#{country})
</insert>
测试类:调用MyBatis工具类,创建SqlSEssion实例,再通过传入映射器接口,创建该接口的代理对象。
Website website = new Website();
website.setName("猿究院111");
website.setAge(12);
website.setUrl("https://www.apesource.com");
website.setAlexa(12);
website.setUv(12);
website.setCountry("CN");
SqlSession sqlSession = MyBatisUtils.getSqlSession();
WebsiteMapper websiteMapper = sqlSession.getMapper(WebsiteMapper.class);
websiteMapper.insertWebsite(website);
sqlSession.commit();
2、查询所有网站信息
映射器接口:如果明确知道查询结果是一条数据,那么返回的结果可以定义成
Website ---> Website selectAllWebsite();
返回的结果是好多个Website对象,所以要定义成List集合。
List<Website> selectAllWebsite();
XML文件:查询语句要写在<select></select>标签中,
id属性:SQL映射的名称。
resultType属性:查询结果使用哪一种类型封装。
<select id="selectAllWebsite"
resultType="com.apesource.entity.Website">
select * from website
</select>
测试类:
SqlSession sqlSession = MyBatisUtils.getSqlSession();
WebsiteMapper websiteMapper = sqlSession.getMapper(WebsiteMapper.class);
List<Website> websiteList = websiteMapper.selectAllWebsite();
for (Website web : websiteList) {
System.out.println(web);
}
3、按照网站名称实现模糊查询
映射器接口:
List<Website> selectWebsiteLikeName(String keyWord);
XML文件:
concat()函数:拼接字符串 concat('%',?,'%')
<select id="selectWebsiteLikeName" resultType="com.apesource.entity.Website"
parameterType="string">
select * from website where name like concat('%',#{keyWord},'%')
</select>
4、按照age区间查询
方式1:使用注解的方式(使用场景:参数只有几个)
映射器接口:注解中的名称要与xml文件中sql语句需要传入的参数名称一致。
List<Website> selectWebsiteBetweenAge(@Param("paramBegin")int begin,@Param("paramEnd")int end);
XML文件:
<select id="selectWebsiteBetweenAge" resultType="com.apesource.entity.Website">
select * from Website w where w.age between #{keyBegin} and #{keyEnd}
</select>
方式2:使用Map(使用场景:参数有多个)
映射器接口:
List<Website> selectWebsiteBetweenAge(Map<String, Integer> paramMap);
XML文件:
<select id="selectWebsiteBetweenAge" resultType="com.apesource.entity.Website">
select * from Website w where w.age between #{paramBegin} and #{paramEnd}
</select>
测试类:
SqlSession sqlSession = MyBatisUtils.getSqlSession();
WebsiteMapper websiteMapper = sqlSession.getMapper(WebsiteMapper.class);
Map<String, Integer> paramMap = new HashMap<String, Integer>();
//键的名称要与sql查询语句中名称一致 #{keyBegin}、#{keyEnd}
paramMap.put("keyBegin", 10);
paramMap.put("keyEnd", 20);
List<Website> websiteList = websiteMapper.selectWebsiteBetweenAge(paramMap);
for (Website website : websiteList) {
System.out.println(website);
}
方式3:JavaBean(按照多值、模糊、区间查询 )
将age区间的上限,下限重新定义一个类(WebsiteCondition),传入的参数就是WebsiteCondition类型的。
映射器接口:
List<Website> selectWebsiteByCondition(WebsiteCondition website);
XML文件:
resultType属性:查询结果使用哪一种类型封装(使用website类封装)。
parameterType属性:传入参数的类型(WebsiteCondition类型)。
<select id="selectWebsiteByCondition" resultType="com.apesource.entity.Website"
parameterType="com.apesource.mapper.condition.WebsiteCondition">
select * from Website w
where w.name like concat('%',#{name},'%') OR
w.url like concat('%',#{url},'%') OR
w.age between #{ageBegin} and #{ageEnd} OR
w.uv between #{uvBegin} and #{uvEnd} OR
w.country = #{country}
</select>
5、聚合函数(例:统计网站总数量)
映射器接口:
int selectWebsiteCount();
XML文件:返回1个结果
统计总共有多少条数据。
<select id="selectWebsiteCount" resultType="int">
select count(id) from website w;
</select>
6、多条统计结果
映射器接口:
List<Map<String, ?>> selectWebsiteInfo2();
XML文件:
根据website表中查找国家,根据国家进行统计,计算uv()的最大(小)值,平均值
<select id="selectWebsiteInfo2" resultType="map">
select country,
count(id) as count,
max(uv) as max,
min(uv) as min,
avg(uv) as avg
from website w
group by country;
</select>
7、主键回填(主键设置为自增)
添加某条数据时,可能需要拿到添加的这条数据的id以便于后续的操作,这时就需要"主键回填",
通过在<insert>标签里设置useGeneratedKeys和keyProperty两个属性。
useGeneratedKeys属性:设置为true。
keyProperty属性:实体类的"id"成员变量。
在测试类中通过成员变量的get()拿到"自增主键"。