ssm学习笔记day07mybatis
项目的准备
创建springboot项目(moudle),加入依赖lombok(自动添加setter,getter,toString)、Spring Web(处理servlet请求)、MySQL Driver(mysql的驱动器)、JDBC(JAVA与mysql的接口)、mybatis framework。
ps:我在添加mybatis framework依赖的时候,上面灰了,应该是maven里面没有对应的包导致的,解决办法很简单,之前学过maven的相关东西,直接在pom.xml中加上依赖即可。
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
对项目做配置,首先配置对应的数据库。
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis-example
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
接下来进入正题,先写好Emp对象(/bean/Emp.class)
package com.atguigu.mybatis.bean;import lombok.Data;@Data
public class Emp {private Integer id;private String empName;private Integer age;private Double empSalary;}
然后创建EmpMapper接口(/dao/EmpMapper)
package com.atguigu.mybatis.dao;import com.atguigu.mybatis.bean.Emp;
import org.apache.ibatis.annotations.Mapper;@Mapper //告诉spring这是mysql操作数据库
public interface EmpMapper {Emp getEmpById(Integer id);void addEmp(Emp emp);void updateEmp(Emp emp);void deleteEmpById(Integer id);
}
这个就相当于以前的DAO层,用mybatis去实现了。
接下来就是配置mybatis信息,可以用插件事半功倍,下载插件mybatisX,如果要编写对应的xml,可以在函数附近按ALT+ENTER
即可。
然后找resource下找一个合适位置存放即可,这里存放在了mapper/EmpMapper.xml
里面的内容如下,前两句是固定搭配,不用记忆,<mapper>
负责绑定对应的mapper接口类,然后编写方法。
<?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-->
<mapper namespace="com.atguigu.mybatis.dao.EmpMapper">
</mapper>
但是mybatis也要知道这个xml在哪里,于是还需要再resource/application.prosperities写相应的位置。这里用通配符(**.xml
)表示文件里面的所有文件都能绑定。
CRUD的编写
在Empmapper类中,我们需要对这个类标注为@mapper让mybatis识别到这个类,然后接几个方法类。如图下所示。
package com.atguigu.mybatis.mapper;import com.atguigu.mybatis.bean.Emp;
import org.apache.ibatis.annotations.Mapper;@Mapper //告诉spring这是mysql操作数据库
public interface EmpMapper {Emp getEmpById(Integer id);void addEmp(Emp emp);void updateEmp(Emp emp);void deleteEmpById(Integer id);
}
然后这些方法的具体实现要在/mapper/Empmapper.xml去实现。刚才我们把这个xml和
该类进行了绑定。实现方法的格式如下:
<?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-->
<mapper namespace="com.atguigu.mybatis.mapper.EmpMapper"><!-- 在里面写方法 , id绑定方法名 #{变量名} resultType返回类型--><select id="getEmpById" resultType="com.atguigu.mybatis.bean.Emp">SELECT id , emp_name empName, age , emp_salary empSalary FROM t_emp WHERE id = #{id}</select><insert id="addEmp">insert into t_emp(emp_name , age , emp_salary) values(#{empName} ,#{age} , #{empSalary})</insert><update id="updateEmp">UPDATE t_emp SET emp_name = #{empName} , age = #{age} , emp_salay = #{empSalary} WHERE id = #{id}</update><delete id="deleteEmpById">DELETE FROM t_emp WHERE id = #{id}</delete>
</mapper>
用标签标记方法类型,如<select>
、<update
、<insert>
、<delete>
等,id是绑定mapper类的方法,然后里面写sql语句即可。需要注意的是,方法中可能会带有参数,也需要传到sql语句中,可以用#{变量名}引用。
开SQL日志
很简单,在application.prosperities中配置相关信息即可。
语法为logging.level."mapper包"=debuglogging.level."mapper包"=debuglogging.level."mapper包"=debug
含义是mapper包里面的类进行的debug级别以上的行动都会被记录。
为添加的数据提供自增id
useGenerateKeys相当于insert标签的属性类,表示是否使用自增ID, keyProperty表示自增的变量是id。
<!-- useGeneratedKeys表示是否使用自增ID, keyProperty表示自增的变量是id--><insert id="addEmp" useGeneratedKeys="true" keyProperty="id">insert into t_emp(emp_name , age , emp_salary) values(#{empName} ,#{age} , #{empSalary})</insert>
useGenerateKeys具有自增回填的功能,当制定的id自增后,会返回到原有的实例对象中。
可以通过Test实验理解:
@Testvoid testCRUD(){Emp emp = new Emp();emp.setId(5);emp.setEmpName("张三5");emp.setAge(105);emp.setEmpSalary(1000.00);empMapper.addEmp(emp);Integer empId = emp.getId();System.out.println(empId);}
empMapper.add(emp)之后,把自增的id返回到emp的id当中,输出便可以查看自增后的id是多少。
查询所有数据(集合)
<!-- 在里面写方法 , id绑定方法名 #{变量名} resultType返回类型--><select id="getEmpById" resultType="com.atguigu.mybatis.bean.Emp">SELECT id , emp_name empName, age , emp_salary empSalary FROM t_emp WHERE id = #{id}</select><!-- 返回的是集合,但是还是写集合中元素的对象类型--><select id="getAll" resultType="com.atguigu.mybatis.bean.Emp">SELECT id , emp_name empName, age , emp_salary empSalary FROM t_emp</select>
和之前的selectEmpById类似,返回类型只看集合元素的类型,不用管是不是集合。
开启驼峰和下划线的转换
在Emp实体类中,属性是驼峰命名法,而在数据库中用的是下划线命名法,需要一个工具对其进行转换,方法很简单,只需要在application.prosperites中添加一句话
mybatis.configuration.map-underscore-to-camel-case=true
参数传递遇到多个参数的解决办法
示例
EmpParamMapper实现
package com.atguigu.mybatis.mapper;import com.atguigu.mybatis.bean.Emp;
import org.apache.ibatis.annotations.Mapper;import java.util.List;
import java.util.Map;@Mapper
public interface EmpParamMapper {Emp getEmploy(Integer id);Emp getEmploy02(List<Integer> ids);
//void addEmploy(Emp e);
//void addEmploy2(Map<String , Object> m);}
EmpParamMapper.xml实现
<?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.atguigu.mybatis.mapper.EmpParamMapper"><select id="getEmploy" resultType="com.atguigu.mybatis.bean.Emp">SELECT * FROM t_emp WHERE id = #{abc}</select><select id="getEmploy02" resultType="com.atguigu.mybatis.bean.Emp">SELECT * FROM t_emp WHERE id = #{ids[1]}</select><insert id="addEmploy">INSERT INTO t_emp(emp_name , age) VALUES(#{empName} , #{age})</insert><insert id="addEmploy2">INSERT INTO t_emp(emp_name , age) VALUES(#{empName} , #{age})</insert></mapper>
@Param的使用
package com.atguigu.mybatis.mapper;import com.atguigu.mybatis.bean.Emp;
import org.apache.ibatis.annotations.Mapper;import java.util.List;
import java.util.Map;@Mapper
public interface EmpParamMapper {Emp getEmployByIdAndName(Integer id, @Param("name") String name);Emp getEmployHaha(@Param("id") Integer id, @Param("m") Map<String, Object> m , @Param("ids") List<Integer> ids , @Param("e") Emp e);
}
<?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.atguigu.mybatis.mapper.EmpParamMapper"><select id="getEmployByIdAndName" resultType="com.atguigu.mybatis.bean.Emp">SELECT * FROM t_emp WHERE id = #{id} AND emp_name = #{name}</select><select id="getEmployHaha" resultType="com.atguigu.mybatis.bean.Emp">SELECT * FROM t_emp WHERE id = #{id} AND emp_name = #{m.name} AND age = #{ids[2]} AND emp_salary = #{e.empSalary}</select>
</mapper>
参数传递返回值的处理
很简单,基本类型就直接写就完事了
其中Map比较复杂,需要制定Map_key对应的属性值,用@Mapkey(“属性名”)指定,剩下的基本上大差不差,例子如下:
package com.atguigu.mybatis.mapper;import com.atguigu.mybatis.bean.Emp;
import org.apache.ibatis.annotations.MapKey;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;import java.math.BigDecimal;
import java.util.List;
import java.util.Map;@Mapper
public interface EmpReturnValueMapper {Long countEmp();BigDecimal getEmpSalary(@Param("id")Integer id);@MapKey("id")Map<Integer , Emp> getAllEmp();
}
<?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.atguigu.mybatis.mapper.EmpReturnValueMapper"><select id="countEmp" resultType="java.lang.Long">SELECT COUNT(*) FROM t_emp</select><select id="getEmpSalary" resultType="java.math.BigDecimal">SELECT emp_salary FROM t_emp WHERE id = #{id}</select><select id="getAllEmp" resultType="com.atguigu.mybatis.bean.Emp">SELECT * FROM t_emp</select></mapper>
自定义结果集ResultMap,使用方法如下,<select>
标签中属性resultMap绑定对应的id,自定义<resultMap>
标签,然后<id>
标签绑定的是主键,<result>
绑定的是属性,然后column是数据库中的属性名,property是JavaBean中的属性名。
<resultMap id="EmpRm" type="com.atguigu.mybatis.bean.Emp"><id column="id" property="id"></id><result column="emp_name" property="empName"></result><result column="age" property="age"></result><result column="emp_salary" property="empSalary"></result></resultMap><select id="getEmpById" resultMap="EmpRm">SELECT * FROM t_emp WHERE id = #{id}</select>
关联查询
说白了就是表的链接,然后封装到一个类中,比如说网上买东西中,一个用户对应多个订单,一个订单对应一个用户购买。于是我们定义以下两种Bean
Customer
import lombok.Data;import java.util.List;@Data
public class Customer {private Integer id;private String customerName;private String phone;private List<Order> orders;
}
Order
package com.atguigu.mybatis.bean;import lombok.Data;
import org.springframework.boot.autoconfigure.amqp.RabbitConnectionDetails;import java.math.BigDecimal;@Data
public class Order {private Integer id;private String address;private BigDecimal amount;private Integer customerId;//订单对应的客户private Customer customer;
}
可以发现Order中有Customer的成员类,我们要通过SQL语句封装这个Order类,就要用到表的链接,这时困难出现了,怎么把表的多个元素返回到一个成员类中呢,根据关联查询一对一和一对多的关系分为assiciation、collection。以下是两个xml的实现方法:
利用ReslutMap,在里面套一个assiciation,assiciation的property属性对应成员类的名字,JavaType对应成员类的类型;collection的property属性对应成员类集合的名字,OfType对应成员类的类型。
<?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.atguigu.mybatis.mapper.OrderMapper"><resultMap id="OrderRM" type="com.atguigu.mybatis.bean.Order"><id column="id" property="id"></id><result column="address" property="address"></result><result column="amount" property="amount"></result><result column="customer_id" property="customerId"></result><association property="customer" javaType="com.atguigu.mybatis.bean.Customer"><id column="c_id" property="id"></id><result column="customer_name" property="customerName"></result><result column="phone" property="phone"></result></association></resultMap><select id="getOrderByIdWithCustomer" resultMap="OrderRM">SELECT o.* , c.id c_id , c.customer_name , c.phone FROM t_order oLEFT JOIN t_customer cON o.customer_id = c.idWHERE o.id = #{id}</select>
</mapper>
<?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.atguigu.mybatis.mapper.CustomerMapper"><resultMap id="CustomerRM" type="com.atguigu.mybatis.bean.Customer"><id column="c_id" property="id"></id><result column="customer_name" property="customerName"></result><result column="phone" property="phone"></result><collection property="orders" ofType="com.atguigu.mybatis.bean.Order"><id column="id" property="id"></id><result column="address" property="address"></result><result column="amount" property="amount"></result><result column="customer_id" property="customerId"></result></collection></resultMap><select id="getCustomerByIdWithOrders" resultMap="CustomerRM">SELECT c.id c_id , c.customer_name , c.phone , o.* FROM t_customer cLEFT JOIN t_order oON o.customer_id = c.idWHERE c.id = #{id}</select>
</mapper>