MyBatis
框架 主要是配置文件【注解,约定大于配置】
持久层框架
Hibernate 全封装,不需要写数据库
MyBatis 半封装,sql需要开发人员去写
JPA 和Hibernate类似
配置
1、config.xml
规定由上至下按顺序写,否则报错
propertise 引入外部的资源文件
settings 设置,例如使用驼峰命名等
typeAliases 起别名
配置文件中具体字段可用别名代替
<typeAliases>
<!-- 给单个类起别名-->
<!-- <typeAlias type="com.MyBatis.bean.Grade" alias="grade"></typeAlias>-->
<!-- 给包下的所有类起别名,默认名字都是类名的首字母小写-->
<package name="com.MyBatis.bean"/>
</typeAliases>
给包中所有类起别名,别名为类名首字母小写
也可以使用注解@Alias(“xxx”)给某个类起别名,优先级高于统一起别名
typeHandlers
Handling Enums
objectFactory
plugins 插件
environments 开发环境,通过default可以切换
<environments default="test">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=UTF8&usessl=false&serverTimezone=UTC&rewriteBatchedStatements=true"/>
<property name="username" value="root"/>
<property name="password" value="ljh123456"/>
</dataSource>
</environment>
<environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${user}"/>
<property name="password" value="${pwd}"/>
</dataSource>
</environment>
</environments>
databaseldProvider
mappers 引入映射文件
可写多个映射配置文件(URL)
<mapper resource=“userMapper.xml”
可使用类名
mapper class=“userMapper”/>
可用包名
idea中需要 xml配置文件名和接口名相同,放在同一包下
2、mapper.xml
如果config.xml中通过包名找映射配置文件,则:
xml配置文件名和接口名相同,放在同一包下
mapper中的namespace 指向接口,方法id与接口中的方法名保持一致
// 接口
public interface employeesDao {
public List<Employees> findEmps(List<Integer> ids);
public List<Employees> findEmps02(List<Integer> ids, String name);
public List<Employees> findEmpsByEmp(Employees employees);
}
<!--mapper映射文件-->
<!-- public List<Employees> findEmps(List<Integer> list);-->
<select id="findEmps" parameterType="int" resultType="com.MyBatis.bean.Employees">
SELECT * FROM employees
<foreach collection="list" separator="," item="id" open="WHERE employee_id IN(" close=")">
#{id}
</foreach>
</select>
如果方法返回值是集合,则结果的参数类型(resultType)为泛型对应的类
之后就可通过session.getMapper(xxx.class)获取代理对象,调用方法操作数据
主键自增.
当主键是自增的情况下,添加一条记录的同时,其主键是不能使用的,但是有时我们需要该主键,这时我们该如何处理呢?这时我们只需要在其对应xml中加入以下属性即可:
useGeneratedKeys=“true” keyProperty=“对应的主键的对象”。
<!-- public int save();-->
<insert id="save" parameterType="com.Mybatis.bean.users" useGeneratedKeys="true" keyProperty="userId">
INSERT INTO users VALUES(NULL,#{userName},#{sex},#{userBirth})
</insert>
在查询多条数据封装到map集合中可以使用,这里是把userId的值来作为map集合的Key,对应的值为一个个对象
@MapKey("userId")
public Map<Integer,users> findAll();
参数处理
一个参数可以随意取值
<!-- public Intrest findOneById(int intrestId);-->
<select id="findOneById" parameterType="int" resultType="com.MyBatis.bean.Intrest">
SELECT * FROM intrest WHERE intrest_id = #{id}
</select>
多个参数,将参数封装map集合中,名字按param1,param2…排列
或者在接口给参数取别名,@param(“别名”)就可以在映射文件中参数名使用别名
public interface GradeDao {
public List<Grade> findAll();
public Grade findOneById(int gradeId);
public Grade findOne(@Param("gradeId")int userId, @Param("gradeName")String gradeName, @Param("gradeDesc")String gradeDesc);
public Grade findOneByIdAndStu(int gradeId);
}
或者接口中方法参数为map,映射文件中参数设置名字,调方法时,其参数名字作为key值,添加到map中
也可以封装到对象当中,可通过对象属性取值,调用方法参数直接传个对象
@Test
public void testFindOne02(){
Grade grade=gradeDao.findOne(2,"一年级","初入小学");
System.out.println(grade);
}
参数为list集合,查询语句需要foreach循环,设定相应的值
测试
@Test
public void testFindEmps02(){
List<Integer> list=new ArrayList<>();
list.add(106);
list.add(107);
list.add(108);
List<Employees> emplist=employeesDao.findEmps02(list,"fsd");
for (Employees e:emplist
) {
System.out.println(e.getEmployeeId()+"--"+e.getFirstName()+"--"+e.getLastName()+"--"+e.getEmail());
}
}
<!-- public List<Employees> findEmps02(List<Integer> ids,String name);-->
<select id="findEmps02" resultType="com.MyBatis.bean.Employees">
SELECT * FROM employees
<foreach collection="param1" separator="," item="id" open="WHERE employee_id IN(" close=")">
#{id}
</foreach>
AND first_name LIKE #{param2}
</select>
#{} 与 ${}取值
#{} 采用的预编译,sql 语句中包含?,?,?
${} 字符串的拼接
List集合
查询的结果封装
1》封装为一个对象
2》多条记录的封装
3》查询的一条记录封装为Map<String, Object> 查询结果的列名作为Key,列的值作为map的值
4》查询的多条记录封装为Map<Integer,实体类>,key值可以自定义,通过@mapkey(“属性”)设置key,查询到的对象作为值
resultMap
数据库列名和实体类属性名无一匹配,查询时不会创建对象,至少有一个匹配就会创建对象,解决方法:1、查询时取别名2、resultMap,主键用id,colum取值数据库列名,property取值属性名,select 语句再调用
<!-- public Map<Integer,users> findAll();-->
<resultMap id="usersMap" type="com.Mybatis.bean.users">
<result column="userSex" property="sex"></result>
</resultMap>
<select resultMap="usersMap" id="findAll" resultType="com.Mybatis.bean.users">
SELECT * FROM users
</select>
注意事项
设置事务自动提交 session = factory.openSession( true);
否则默认手动提交,在进行增删改查操作后需要手动提交 session.commit();
@Before
public void before(){
try {
InputStream inputStream = Resources.getResourceAsStream( "Mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
session = factory.openSession( true);
employeesDao = session.getMapper(employeesDao.class);
} catch (IOException e) {
e.printStackTrace();
}
}
XML文件中 & 需要转义字符,&
Junit
beforeClass和afterClass在加载类之前之后,只会执行一次。必须是静态 方法
构造方法在加载类之后,before 方法之前
before 和after在执行方法之前和之后,如果有多个方法则执行多次,每次都是before 方法* after 往复执行
关系查询
1、关联查询,
collection 对应集合 of Type
<resultMap id="gradeMap" type="com.Mybatis.bean.Grade">
<id column="grade_id" property="gradeId"></id>
<result column="grade_name" property="gradeName"></result>
<result column="grade_desc" property="gradeDesc"></result>
</resultMap>
<!--一条sql查询-->
<resultMap id="gradeMap1" type="com.Mybatis.bean.Grade" extends="gradeMap">
<collection property="list" ofType="com.MyBatis.bean.Student">
<id column="stu_id" property="stuId"></id>
<result column="stu_name" property="stuName"></result>
<result column="stu_sex" property="stuSex"></result>
<result column="stu_pnohe" property="stuPhone"></result>
<result column="grade_id" property="gradeId"></result>
</collection>
</resultMap>
<!-- public Grade findOneByIdAndStu(int gradeId);-->
<select id="findOneByIdAndStu" resultMap="gradeMap1" >
SELECT * FROM grade g LEFT JOIN stu s ON g.`grade_id`=s.`grade_id` WHERE g.`grade_id`=#{id}
</select>
<!--两条sql查询-->
<resultMap id="gradeMap2" type="com.Mybatis.bean.Grade" extends="gradeMap">
<collection property="list" ofType="com.Mybatis.bean.Student" select="com.Mybatis.dao.stuDao.findoneByGradeid" column="grade_id">
<!---在此调用stuDao接口的findoneByGradeid方法->
</collection>
</resultMap>
<select id="findOneByIdAndStu" resultMap="gradeMap2">
SELECT * FROM grade WHERE grade_id = #{id}
</select>
association 对应对象 javaType 后面不用写result
<resultMap id="stuMap" type="com.Mybatis.bean.Student">
<id column="stu_id" property="stuId"></id>
<result column="stu_name" property="stuName"></result>
<result column="stu_sex" property="stuSex"></result>
<result column="stu_pnohe" property="stuPhone"></result>
<result column="grade_id" property="gradeId"></result>
</resultMap>
<!--一条sql查询-->
<resultMap id="stuMap1" type="com.Mybatis.bean.Student" extends="stuMap">
<association property="grade" javaType="com.Mybatis.bean.Grade">
<id column="grade_id" property="gradeId"></id>
<result column="grade_name" property="gradeName"></result>
<result column="grade_desc" property="gradeDesc"></result>
</association>
</resultMap>
<!-- public Student findOneAndGrade();-->
<select id="findOneAndGrade" resultType="com.MyBatis.bean.Student" resultMap="stuMap1">
SELECT * FROM stu s LEFT JOIN grade g ON s.`grade_id`=g.`grade_id` WHERE s.`stu_id`=#{id}
</select>
<!--两条sql查询-->
</resultMap>
<resultMap id="stuMap3" type="com.Mybatis.bean.Student" extends="stuMap">
<discriminator javaType="String" column="stu_sex">
<!--这里的case可以按照value值进行不同需求的查询-->
<case value="女" resultType="com.Mybatis.bean.Student">
<association property="intrest" column="intrest_id" select="com.Mybatis.dao.intrestDao.findOneById"></association>
</case>
<case value="男" resultType="com.MyBatis.bean.Student">
<association property="grade" column="grade_id" select="com.Mybatis.dao.GradeDao.findOneById"></association>
</case>
</discriminator>
</resultMap>
<select id="findOneAndGrade" resultMap="stuMap3">
SELECT * FROM stu WHERE stu_id = #{id}
</select>
动态Sql
<!-- public List<Employees> findEmpsByEmp(Employees employees);-->
<sql id="baseSql" >
SELECT * FROM employees
</sql>
<select id="findEmpsByEmp" resultType="com.Mybatis.bean.Employees">
<include refid="baseSql"></include>
<trim prefix="where" prefixOverrides="and">
<if test="employeeId!=null and employeeId!=0">
AND employee_id=#{employeeId}
</if>
<if test="firstName!=null and firstName!='' ">
<bind name="first_Name" value="'%'+firstName+'%'"/>
AND first_name LIKE #{first_Name}
</if>
<if test="lastName!=null and lastName!=''">
<bind name="last_Name" value="'%'+lastName+'%'"/>
AND last_name LIKE #{last_Name}
</if>
<if test="min!=null and min!=0">
AND salary >= #{min}
</if>
<if test="max!=null and max!=''">
AND salary <= #{max}
</if>
</trim>
</select>
相当于javase中的switch,只能进一个
循环,需设置便利的文件、参数、开头和结尾。
<!-- public List<Employees> findEmps(List<Integer> list);-->
<select id="findEmps" parameterType="int" resultType="com.Mybatis.bean.Employees">
SELECT * FROM employees
<foreach collection="list" separator="," item="id" open="WHERE employee_id IN(" close=")">
#{id}
</foreach>
</select>
定义一些字段,方便引用 ,引用时用
<sql id="baseSql" >
SELECT * FROM employees
</sql>
重新绑定值,比如模糊查询中参数需加% ,idea中属性值为空时会报错,故应该加判断
<sql id="baseSql" >
SELECT * FROM employees
</sql>
条件查询时,自动补充where,放在基本语句之后
缓存
1、配置文件设置seting,开启全局二级缓存
2、映射文件 使用耳机缓存 配置3、
3、序列化 extends in…
Mybatis Generate
导入jar包
xml 文件详述:
https://blog.csdn.net/awecoder/article/details/101763736
多出的and或者or where标签不能解决 prefix="":前缀:trim标签体中是整个字符串拼串 后的结果。 prefix给拼串后的整个字符串加一个前缀 prefixOverrides="":前缀覆盖: 去掉整个字符串前面多余的字符 suffix="":后缀 suffix给拼串后的整个字符串加一个后缀 suffixOverrides=""后缀覆盖:去掉整个字符串后面多余的字符–>
缓存
1、配置文件设置seting,开启全局二级缓存
2、映射文件 使用耳机缓存 配置3、
3、序列化 extends in…
Mybatis Generate
导入jar包
xml 文件详述:
https://blog.csdn.net/awecoder/article/details/101763736
配置文件特殊符号