一.CRUD的练习操作
在此之前,CRUD的操作都是基于TEST文件上的修改,有必要对教材上原始代码深入理解
public class TestMybatis {
public static void main(String[] args) throws IOException {
1 String resource = "mybatis-config.xml";
2 InputStream inputStream = Resources.getResourceAsStream(resource);
3 SqlSessionFactory sqlSessionFactory = new
4 SqlSessionFactoryBuilder().build(inputStream);
5 SqlSession session=sqlSessionFactory.openSession();
6 List<Category> cs=session.selectList("listCategory");
7 for (Category c : cs) {
8 System.out.println(c.getName());
第一二行:定义MyBatis的配置文件的路径,并作为输出流加载配置文件
配置文件就涉及到了数据源和SQL映射的配置文件,前者就像之前学的MVC中的model层和JDBC驱动用于与数据库连接,包括数据库驱动、数据库URL、用户名、密码等。一些全局配置项等等,通常放到类路径下;后者用于配置SQL语句与Java方法的映射关系。它包括了一系列的<select>
、<insert>
、<update>
和<delete>
等元素,每个元素都对应一个SQL语句和一个Java方法。简单来说就是一个负责连接,一个负责Java和SQL方法映射
第三行往后就是会话工厂的实例对象,依照配置文件的映射关系,将Java方法转换成sql语句完成对数据库进行操作
所以,在开始CRUD操作之前,从整体框架出发需要完成对配置文件的修改,完成数据库连接和映射方法的定义,
数据库连接池配置:
<configuration>
<typeAliases>
<package name="com.how2java.pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/how2java?characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/how2java/pojo/Category.xml"/>
</mappers>
</configuration>
-
<typeAliases>
:MyBatis框架的类型别名配置,用于指定Java对象的别名,提高编码效率。但<package name="com.how2java.pojo"/>
并不是一个具体的别名,而是一个将com.how2java.pojo
包下的所有Java类注册为别名的配置。也就是说,如果在com.how2java.pojo
包下有一个名为Category
的Java类,那么它的别名就是category
,如果有一个名为Product
的Java类,那么它的别名就是product
,以此类推。那么在SQL映射文件中就可以使用<select id="getCategory" resultType="category">
来引用com.how2java.pojo.Category
类,其中resultType
属性的值为category
,即该类的别名 -
<environments>
:定义MyBatis框架所需的数据库环境,可以包含多个<environment>
元素,每个<environment>对应一个数据源,default
属性指定了默认的数据库环境, -
<transactionManager>
:事务管理器配置,用于指定事务的管理方式,常用的包括JDBC
、MANAGED
和SPRING
等。这里指定的是JDBC <dataSource>
:数据源配置,是本质上用来配置数据库信息的,在其中<property>
属性配置,包含了driver
、url
、username
和password
等数据库的配置信息<mappers>
标签用于指定MyBatis的映射器,也就是SQL映射文件的位置。在这个例子中,<mappers>
标签包含了一个<mapper>
标签,指定了com/how2java/pojo/Category.xml
文件作为MyBatis的映射器。通过将映射器的位置配置在MyBatis配置文件中,MyBatis可以自动扫描指定位置下的所有映射文件,并将它们加载到内存中,以便在Java应用程序中使用。这样,我们就可以在Java应用程序中方便地使用MyBatis进行数据库操作,而不需要手动编写SQL语句。
SQL映射文件配置:因为要使用到CRUD操作,所以这里要给出相关方法的映射配置 :
<mapper namespace="com.how2java.pojo">
<insert id="addCategory" parameterType="Category" >
insert into category_ ( name ) values (#{name})
</insert>
<delete id="deleteCategory" parameterType="Category" >
delete from category_ where id= #{id}
</delete>
<select id="getCategory" parameterType="_int" resultType="Category">
select * from category_ where id= #{id}
</select>
<update id="updateCategory" parameterType="Category" >
update category_ set name=#{name} where id=#{id}
</update>
<select id="listCategory" resultType="Category">
select * from category_
</select>
</mapper>
-
<mapper>
是映射文件的根节点,namespace属性指定操作的接口名。 -
<insert>
为插入操作,id为操作的标识符,parameterType为传入参数的数据类型,其中category_是表名,name是表中的一个字段名,#{name}是MyBatis的占位符,表示name字段的值由Category对象中的name属性提供。insert,delete后面的操作也是同理 -
<select>
为查询操作,根据不同的参数类型返回不同的实体结果。id、parameterType、resultType分别为操作的标识符、传入参数的数据类型和返回结果的数据类型。#{id}表示传入的参数。SQL语句中的*表示查询所有字段,后面的表名为被查询的表名。
以上是insert和delete的操作结果演示,后面冗余的操作也是同理
核心部分:
Category c = new Category();
c.setId(1);
session.delete("deleteCategory",c);
Category c = new Category();
c.setName("ihui永不放弃");
session.insert("addCategory",c);
Category c= session.selectOne("getCategory",3);
System.out.println(c.getName()); //获取
listAll(session);//查询
核心代码的地方直接是用java的crud方法,最后是通过配置文件转换成对应的SQL语句
2.动态SQL练习
IF:用条件语句实现模糊查询和整体查询
<?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="com.how2java.pojo">
<select id="listProduct" resultType="Product">
select * from product_
<if test="name!=null">
where name like concat('%',#{name},'%')
</if>
</select>
</mapper>
核心字段在配置文件中,因为要查询的对象多,相应需要的SQL语句也需要更多,这里在配置文件中实用IF标签来制定SQL语句的查询条件。如果name属性存在,则将它作为查询条件来实现模糊查询,如果没有name属性传入,就查询所有
where name like concat('%',#{name},'%')
在SQL语句中添加查询条件,即查询name属性中包含指定字符的记录。其中,#{name}
是MyBatis的占位符,表示在执行SQL语句时,将会使用name属性的值来替换这个占位符。concat('%',#{name},'%')
是SQL语句中的字符串拼接函数,用于将查询条件中的字符与通配符%拼接起来,形成模糊查询的效果
WHERE:自动去掉多余的and或or关键字
如果添加了多个查询条件,那么就需要用and或or连接这些条件。但是,如果其中某个条件没有成立,就会导致SQL语句中出现多余的and或or关键字,从而导致SQL语句语法错误。<where>
标签会自动判断这种情况,并且去掉多余的and或or关键字,以保证SQL语句的正确性。
例如:这个多条件语句,如果传值参数不全的话,就会变成select * from product_ and price > 10.很明显此时 多余了一个and,所以用where标签能自动判断并且删除不必要的连接符以保证正确性
类似的,还有set标签和trim标签
-
<set>
标签用于在SQL语句中添加更新字段,并且会自动去掉多余的逗号和空格,以保证SQL语句的正确性。 -
<trim>
标签用于在SQL语句中添加任意的SQL片段,并且可以自定义前缀、后缀和连接符。
Choose:实现多条件判断,类似于java中的switch语句
<select id="selectProduct" parameterType="Product" resultType="Product">
select * from product
<where>
<choose>
<when test="id != null">
and id = #{id}
</when>
<when test="name != null">
and name like concat('%',#{name},'%')
</when>
<when test="price != null">
and price = #{price}
</when>
<otherwise>
and 1 = 1
</otherwise>
</choose>
</where>
</select>
如果所需要的值都没有传入,就会默认执行otherwise中的语句,即全部查询,主要是由when和otherwise两个标签构成
Foreach:遍历集合生成查询条件
foreach标签通常用于in 这样的语法里,用于实现遍历集合或数组中的元素,并将它们作为查询条件的一部分,生成类似于SELECT * FROM product_ WHERE ID IN (1, 2, 3)
的SQL语句,基本结构如下:
<foreach collection="collection" item="item" index="index"
open="open" close="close" separator="separator">
...
</foreach>
collection
:指定要遍历的集合或数组的名称,可以是OGNL表达式或者是Java对象的属性名。item
:指定遍历过程中每个元素的名称,可以是任意合法的Java变量名。index
:指定遍历过程中每个元素的索引,可以是任意合法的Java变量名。open
:指定遍历过程中生成的SQL语句的开头部分。close
:指定遍历过程中生成的SQL语句的结尾部分。separator
:指定遍历过程中每个元素之间的分隔符。
根据教材中的代码
在这个例子中,#{item}
表示要查询的ID
值,它会在运行时被list
集合中的每个元素所替换。<foreach>
标签将List<Integer>
类型的ids
集合中的元素转化为id
查询条件,并以IN
符号连接查询条件,从而查询出所有在1
、3
、5
范围内的产品
三.分页功能
这里实现的分页功能是一种分页查询的方式,与之前的MVC中的翻页有所不同,并没有实现交互功能
但是,相同的是这里也两种方式来实现可以用注解或者xml配置
private static void xmlWay(SqlSession session) {
Map<String,Object> params = new HashMap<>();
params.put("start", 0);
params.put("count", 5);
List<Category> cs =session.selectList("listCategory", params);
for (Category c : cs) {
System.out.println(c);
}
private static void annotationWay(SqlSession session) {
CategoryMapper mapper = session.getMapper(CategoryMapper.class);
List<Category> cs =mapper.listByPage(0, 5);
for (Category c : cs) {
System.out.println(c);
在MyBatis中,用两种方式来定义SQL语句:XML文件配置SQL语句或者通过注解方式在Java接口中定义SQL语句。前者使用session.selectList("statementId", parameter)
的方式来执行查询操作,即 List<Category> cs =session.selectList("listCategory", params);后者调用该SQL语句时,需要先通过session.getMapper()
方法获取该接口的实现类实例,再进一步执行查询操作
先说配置方式:向params
对象中添加start
和count
两个参数,分别表示查询结果的起始位置和查询结果的数量,调用session.selectList()
方法,传入查询语句的ID和params
对象作为参数,执行查询操作,事先要在配置文件中定义好相关需要被调用的映射方法
<mapper namespace="com.how2java.pojo">
<insert id="addCategory" parameterType="Category" >
insert into category_ ( name ) values (#{name})
</insert>
<delete id="deleteCategory" parameterType="Category" >
delete from category_ where id= #{id}
</delete>
<select id="getCategory" parameterType="_int" resultType="Category">
select * from category_ where id= #{id}
</select>
<update id="updateCategory" parameterType="Category" >
update category_ set name=#{name} where id=#{id}
</update>
<select id="listCategory" resultType="Category">
select * from category_
<if test="start!=null and count!=null">
limit #{start},#{count}
</if>
</select>
</mapper>
其中在CRUD的方法上新加了 listCategory方法:即查询category_表中所有的分类信息记录,如果传入了start和count参数,则进行分页查询。使用了<if>标签来判断是否传入了分页查询的参数,如果传入了,则使用limit关键字进行分页查询,parameterType和resultype
属性指定了SQL语句中使用的参数类型和查询结果的返回类型
注解方式:session.getMapper()
方法获取一个CategoryMapper
接口的实现类实例。调用mapper.listByPage()
方法,传入查询结果的起始位置和查询结果的数量作为参数,执行查询操作
事先要定义好接口类:
|
其中@Param
注解用来指定方法参数的名称,方便在SQL语句中引用;@Results
注解定义了一个products
属性,用来存放该分类下的所有产品信息;@Many
注解表示该属性为一对多关系,select
属性指定了查询该分类下所有产品信息的SQL语句
参数类型和结果类型可以是Java基本类型、JavaBean、Map、List等类型。例如,parameterType="int"
表示参数类型为整型,resultType="Category"
表示结果类型为Category
类。
注解的方式调用了接口类来实现相关功能,代码也相对简洁一些,但是觉得在这个地方xml的配置对新手还是要友好些,配置中方法的编写更容易懂一些更易上手,注解的方式相对较难
Pagehelper:第三方插件便于实现分页功能,相当分页功能的一个封装体
在看完how2j的教材后有一个疑问,chartgpt给出了完美的回答
运行效果:
其主要就是帮助减少xml配置中sql动态标签,自动来进行分页处理,适合用于用xml方法来查询,减少代码工作量和复用性
此外,常用的方法有:
startPage(int pageNum, int pageSize)
:开始分页,指定当前页码和每页显示的记录数。startPage(int pageNum, int pageSize, boolean count)
:开始分页,指定当前页码、每页显示的记录数和是否进行总记录数的统计。offsetPage(int offset, int limit)
:开始分页,指定偏移量和每页显示的记录数。setPageSize(int pageSize)
:设置每页显示的记录数。setPageNum(int pageNum)
:设置当前页码。setCount(boolean count)
:设置是否进行总记录数的统计。setOrderBy(String orderBy)
:设置排序字段和排序方式。setOrderByOnly(boolean orderByOnly)
:设置是否仅按照排序字段进行排序。getPageInfo()
:获取分页信息,包括当前页码、每页显示的记录数、总记录数、总页数等clearPage()
:清除分页设置,恢复默认设置。