mybatis小结3
配置文件
<?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>
<!-- 引入属性文件 -->
<properties resource="mysql.properties">
</properties>
<!--添加全局设置 -->
<settings>
<!--开启日志 -->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!-- 為類起別名,方便使用 -->
<!--
type:該類的全限定名稱
alias:為type起的別名,在映射文件中,我們可以直接使用別名
-->
<!-- <typeAlias type="com.kang2.Student" alias="Student"/>
</typeAliases> -->
<typeAliases>
<!-- 为指定的包下所有的类起别名,默认的别名为首字母小写的类名 -->
<package name="com.kang.model"/>
</typeAliases>
<environments default="mysql">
<!--环境: id就是该环境的唯一标识 -->
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<!--连接数据库需要的配置 -->
<property name="driver" value="${driverClassName}"/>
<property name="username" value="${userName}"/>
<property name="password" value="${password}"/>
<!-- 在xml文件中,属性值中的& 就是&符号 -->
<property name="url"
value="${url}"/>
</dataSource>
</environment>
<!-- <environment id="oracle"></environment> -->
</environments>
<!-- 配置映射文件 -->
<!-- <mappers>
<mapper resource="com/kang/dao/Student.mapper.xml"/>
<mapper resource="com.kang.dao.RPDao"/> -->
<!-- 使用注解时mapper的配置方式
class:指定注解所在的接口的全限定名称
-->
<!-- <mapper class="com.kang.dao.RoomDao"/>
</mappers> -->
<mappers>
<mapper resource="com/kang/dao/StudentMapper.xml"/>
</mappers>
</configuration>
属性文件
#属性文件,在属性文件中配置,在xml中引用该属性文件
#等号前面的是属性名,后面是属性值,不用双引号或者分号
driverClassName=com.mysql.cj.jdbc.Driver
userName=root
password=12346
url=jdbc:mysql://localhost:3306/mybatis1?characterEncoding=UTF8&&serverTimezone=UTC"
单元测试
package com.kang.test;
import static org.junit.jupiter.api.Assertions.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import com.kang.dao.StudentDao;
import com.kang.model.Student;
/*
* 单元测试:当某个功能开发完毕,可以通过单元测试先测试该功能
* 如果没问题,在发布
*
* @BeforeAll:随着测试类的加载而加载,所以是静态方法,在所有的方法执行前执行该方法只会执行一次。
* @BeforeEach:在执行@Test方法之前执行,执行了几个@Test,该方法就会执行几次
* @Test:该方法中写我们要测试的功能,可以有多个@Test方法
* @AfterEach:在执行完每个@Test方法之后执行,执行了几个@Test方法,该方法就执行几次
* @AfterAll: 所有测试任务都完成了,就会执行该方法,随着类加载的,是静态方法,只执行一次
*
* 除了@Test,其他的都只需要一个即可
*/
public class MyTest{
//由于我们使用的是Session对象,所以SessionFactory值需要一个,
//让sessionFactory对象只创建一个
private static SqlSessionFactory sqlsessionFactory;
private SqlSession sqlSession;
@BeforeAll
public static void createFactory() throws IOException {
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
sqlsessionFactory = new SqlSessionFactoryBuilder().build(in);
}
@BeforeEach
public void createSession() {
sqlSession = sqlsessionFactory.openSession();
}
@Test
public void add() {
StudentDao dao = sqlSession.getMapper(StudentDao.class);//动态代理
Student student = new Student(null,"小华","男",23);
dao.add(student);
}
@Test
public void queryById() {
StudentDao dao = sqlSession.getMapper(StudentDao.class);
//Student student =dao.queryById(1);
//System.out.println(student);
List<Student> student = dao.queryAll();
System.out.println(student);
}
@AfterEach
public void releaseSession() {
sqlSession.commit();
sqlSession.close();
}
@AfterAll
public static void releaseFactory() {
sqlsessionFactory=null;
}
}
面向接口
接口
package com.kang.dao;
import java.util.List;
import com.kang.model.Student;
public interface StudentDao {
public int add(Student student);
public Student queryById(int id);
public List<Student> queryAll();
}
实体
package com.kang.model;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.type.Alias;
/*
* @Alias("Student"):
* 当我们通过为整个包配置别名的方式设置,如果默认的别名也就是类名的首字母小写,
* 不符合我们的需求时,可以通过该注解定义我们需要的别名, 例如
* @Alias("Student") 那么该类的别名就是Stu
*/
public class Student {
//有意将表中字段名和实体类的属性名不一致
private Integer stuId;
private String stuName;
private String stuSex;
private Integer stuAge;
public Integer getStuid() {
return stuId;
}
public void setStuid(Integer stuid) {
this.stuId = stuId;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public String getStuSex() {
return stuSex;
}
public void setStuSex(String stuSex) {
this.stuSex = stuSex;
}
public Integer getStuAge() {
return stuAge;
}
public void setStuAge(Integer stuAge) {
this.stuAge = stuAge;
}
public Student(@Param("stuId") Integer stuId,
@Param("stuName") String stuName,
@Param("stuSex") String stuSex,
@Param("stuAge") Integer stuAge) {
super();
this.stuId = stuId;
this.stuName = stuName;
this.stuSex = stuSex;
this.stuAge = stuAge;
}
public Student() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "Student [stuid=" + stuId + ", stuName=" + stuName + ", stuSex=" + stuSex + ", stuAge=" + stuAge + "]";
}
}
映射文件
<?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">
<!--
mybatis中最强大的功能之一:结果集映射(resultMap)
处理的问题:
1.字段名和属性名不匹配
***2.多表关联查询时,通过resultMap来建立多张表之间和对象的关系
-->
<mapper namespace="com.kang.dao.StudentDao">
<!--
id:为resultMap起一个名字,将来有可能需要多个resultMap,靠id区分
type:用来指定该resultMap需要映射的实体类类型
-->
<!-- <resultMap type="com.kang.model.Student" id="studentMap">
为字段和属性名建立映射关系
主键映射用id标签
column:字段名
property:字段对应的属性名
当查出来的字段名为id时,会将id的值赋值给student对象的stuId属性
<id column="id" property="stuId"></id>
普通字段用result标签
<result column="name" property="stuName"/>
<result column="age" property="stuAge"/>
<result column="sex" property="stuSex"/>
</resultMap>
-->
<resultMap type="student" id="studentMap">
<!-- 构造方法的参数进行映射 -->
<constructor>
<!-- idArg就等同于上面的id标签 都代表主键 -->
<!-- javaType:指定该字段对应的java类型
再官方文档的xml配置中,类型别名可以找见,mybatis为我们常用的java类型都齐了别名
例如jaava.lang.int 对应为_int
这种方式,顺序必须和构造方法的参数一样
-->
<!-- <idArg column="id" javaType="integer"/>
<arg column="name" javaType="string"/>
<arg column="sex" javaType="string"/>
<arg column="age" javaType="integer"/> -->
<!--
column:字段名
name:构造方法的 参数上@Param注解的命名
name属性必须配合@Param注解使用
-->
<idArg column="id" name="stuId"/>
<arg column="name" name="stuName"/>
<arg column="sex" name="stuSex"/>
<arg column="age" name="stuAge"/>
</constructor>
</resultMap>
<!-- #{}部分,填的是实体类的属性名 -->
<insert id="add">
insert into student (name,age,sex) values(#{stuName},#{stuAge},#{stuSex})
</insert>
<!--
当字段名和实体类的属性名不匹配时,我们的查询结果无法映射成指定的对象
查询完的映射结果就为null
解决方案:
1.起别名:通过别名让字段名和属性名匹配起来,一般我们让别名和属性名一样
-->
<select id="queryById" resultType="student">
<!-- select * from student where id = #{id} -->
select
id as stuId,
name as stuName,
sex as stuSex,
age as stuAge
from
student
where
id=#{id}
</select>
<!-- 如果有多出查询,如果我们每次都要给字段起别名,就会很麻烦
2.我们可以将常用的sql片段封装起来以供多处使用不用每次都写
include 标签就是用来引入我们封装浩的sql片段
-->
<!-- <select id="queryAll" resultType="student">
select
<include refid="Student_alias"></include>
from student
</select> -->
<!-- 使用resultMap
指定返回值类型时候,标签的属性不能用resultType了
要使用resultMap,该属性的值,就是我们上面定义resultMap时的id值
由于在resultMap中已经为字段和属性建立了映射关系,此处就不用再起别名了
-->
<select id="queryAll" resultMap="studentMap">
select * from student
</select>
<!-- 用来封装sql片段的标签 -->
<sql id="Student_alias">
id as stuId,
name as stuName,
sex as stuSex,
age as stuAge,
</sql>
</mapper>