MyBatis封装
通过静态方法启动方便后续操作调用
public class MyBatisUtil {
private static SqlSessionFactory sqlSessionFactory =null;
static {
String resource="mybatis-config.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
字段名与属性名不一致
方案一
在SQL语句对字段取别名使别名与属性名一致
<select id="getProById" resultType="products">
SELECT id sid,name sname FROM Students;
</select>
方案二
开启驼峰命名转换
要求:
java类名是驼峰类名
private Integer stuId;
private String stuName;
private Integer stuAge;
sql属性名是_分割
stu_id;
stu_name;
stu_age;
在全局配置文件中configuration标签下通过setting打开
<settings>
<!-- 开启驼峰命名转换将数据库中a_test转为实体类中aTest -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- 程序运行日志 -->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
方式三
通过resultMap手动映射,手动指定一个映射规则
1、mapper标签中通过resultMap标签自定义映射规则
<!--
通过resultMap指定映射规则
type:封装对象(实体类的全类名或别名)
id:相当于给当前resultMap起名
-->
<resultMap type="products" id="pro">
<!-- 主键映射:property:java属性名,column:sql字段名 -->
<id property="proId" column="pro_id"/>
<!-- 普通字段映射:property:属性名,column:字段名。指定为哪个字段值赋属性 -->
<result property="proName" column="pro_name"/>
<result property="proPrice" column="pro_price"/>
<result property="proImage" column="pro_image"/>
<result property="proDesc" column="pro_desc"/>
</resultMap>
2、查询接口中通过resultMap指定需要使用的映射规则
<select id="getProById" resultMap="pro">
SELECT * FROM products
</select>
复杂的结果映射
一对一
实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
private Integer id;
private String sname;
private String sdesc;
// 一对一:一个学生对应一个老师
private Teacher teacher;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Teacher {
private Integer tid;
private String tname;
}
连接查询
<select id="getStuAndTeaById" resultMap="stuAndTea">
SELECT * FROM student s
LEFT JOIN
teacher t
ON s.tid = t.tid WHERE s.id = #{id}
</select>
<!--
autoMapping="true":开启自动映射
满足自动映射规则,MyBatis自动映射
注意:用自动映射则不去掉主键id
-->
<resultMap type="student" id="stuAndTea" autoMapping="true">
<!--
column:字段名
property:属性名
-->
<id column="id" property="id"/>
<!--
映射自定义对象的
association属性
property:属性名
javaType:类名
-->
<association property="teacher" javaType="teacher" autoMapping="true">
<id column="tid" property="tid"/>
</association>
</resultMap>
分步查询
需要新建分布查询类的接口类和.xml文件
学生类(student)接口类
Student getStuAndTeaById(@Param("id")Integer id);
老师类(teacher)接口类
List<Teacher> getTeacherByTid(@Param("tid") Integer tid);
xml文件配置
<select id="getStuAndTeaById" resultMap="stuAndTea">
SELECT * FROM student WHERE id = #{id}
</select>
<resultMap type="student" id="stuAndTea" autoMapping="true">
<id property="id" column="id"/>
<!--
association属性
column:分布查询的条件
select:选择调用查询表单
-->
<association property="teacher" javaType="teacher" column="tid" select="getTeacherByTid"></association>
</resultMap>
<select id="getTeacherByTid" resultType="teacher">
SELECT * FROM teacher WHERE tid = #{tid}
</select>
一对多
数据库中的体现:外键
<mapper namespace="com.woniuxy.dao.TeacherMapper">
<select id="getAllTeaAndStu" resultMap="teaAndStu">
SELECT * FROM teacher t
LEFT JOIN
student s
ON t.tid = s.tid;
</select>
<resultMap type="teacher" id="teaAndStu" autoMapping="true">
<id column="tid" property="tid"/>
<!-- 专门处理 集合 -->
<collection property="allStu" ofType="student" autoMapping="true">
<id column="id" property="id"/>
</collection>
</resultMap>
</mapper>
Dao层:正常编写代码
service层:提前调用Dao层代码,改变代码MyBatis代码结果结构
测试层:直接调用service层方法
模糊查询
1、Dao层
正常放接口和.xml代码
接口类(GoodsDao)
List<Goods> selGoods(@Param("val")String val);
.xml文件(GoodsDao.xml)
<select id="selGoods" resultType="com.xxx.model.Goods">
SELECT * FROM Goods WHERE `p_name` LIKE #{val};
</select>
2、service层
相当于中转站,为查询内容添加模糊语句
接口类(GoodsService)
// 方法与Dao层一致
List<Goods> sellikeGoods(String val);
实现类(GoodsServiceImpl)实现GoodsService
@Override
public List<Goods> likeselGoods(String val) {
// 实现Dao层接口
SqlSession session = MyBatisUtil.getSqlSession();
GoodsDao goods = session.getMapper(GoodsDao.class);
// 为其添加模糊查询语句,并返回对象
List<Goods> selGoods = goods.selGoods("%" + val + "%");
return selGoods;
}
分页查询
1、普通分页
limit n1 n2
n1(查询页码):(pagenum-1)*pagesize
n2(页码容量):pagesize
1、Dao层
正常放接口和.xml代码
接口类(GoodsDao)
List<Goods> fenGoods(@Param("start")Integer start,@Param("pagesize")Integer pagesize);
.xml文件(GoodsDao.xml)
<select id="fenGoods" resultType="com.xxx.model.Goods">
SELECT * FROM Goods LIMIT #{start},#{pagesize};
</select>
2、service层
相当于中转站,为优化分页查询弊端
接口类(GoodsService)
// 方法与Dao层一致
List<Goods> fenselGoods(Integer start, Integer pagesize);
实现类(GoodsServiceImpl)实现GoodsService
@Override
public List<Goods> fenselGoods(Integer start, Integer pagesize) {
// 实现Dao层接口
SqlSession session = MyBatisUtil.getSqlSession();
GoodsDao goods = session.getMapper(GoodsDao.class);
// 为其调整查询位置,并返回对象
List<Goods> selGoods = goods.selGoods2((start - 1) * pagesize, pagesize);
session.close();
return selGoods;
}
2、PageHelper分页
1、导入pageHeplper核心jar包和sql转换jar包
2、MyBatis全局配置文件中配置pageHelper(environments标签上方)
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
3、Dao层
正常放接口和.xml代码
接口类(GoodsDao)
// 此处接口无需传参
List<Goods> selGoods();
.xml文件(GoodsDao.xml)
<select id="selGoods" resultType="com.xxx.model.Goods">
SELECT * FROM Goods
</select>
4、service层
相当于中转站,为优化分页查询弊端
接口类(GoodsService)
// service层接收用户值
void fenselGoods(Integer start, Integer pagesize);
实现类(GoodsServiceImpl)实现GoodsService
@Override
public void fenselGoods2(Integer start, Integer pagesize) {
//查询之前需要配置分页
PageHelper.startPage(start, pagesize);
//普通查询
SqlSession session = new MyBatisUtil().getSqlSession();
GoodsDao goods = session.getMapper(GoodsDao.class);
List<Goods> goods3 = goods.selGoods3();
//将数据丢到分页插件 自动分页
PageInfo<Goods> pageInfo = new PageInfo<>(goods3);
// 根据规定页数获取当前页数据
System.out.println(pageInfo.getList().get(0));
System.out.println(pageInfo.getList().get(1));
// 总的页数
System.out.println(pageInfo.getPages());
// 总条数
System.out.println(pageInfo.getTotal());
}