注意
1.results中的每个result需要用逗号分隔
2.查询所有的时候因为使用d_id,d_username这种列名,所以要有ResultMap,来知晓与User中的哪些属性来对应,否则查出来的都是null。
public interface UserMapper {
// @Insert("insert into t_user(username,password,age) values (#{username},#{password},#{age})")
// @Options(keyColumn = "id",keyProperty = "id",useGeneratedKeys = true)
void save(User u);
// @Update("update t_user set username=#{username},password=#{password},age=#{age} where id = #{id}")
void update(User u);
// @Select("select id,username,password,age from t_user where id = #{id}")
User get(Long id);
// @Select("select id as d_id,username as d_username,password as d_password,age as d_age from t_user")
// @ResultMap("base_map") 用配置文件中的base_map
// @Results({ //不用配置文件中的base_map
// @Result(column = "d_id",property = "id"),
// @Result(column = "d_username",property = "username"),
// @Result(column = "d_password",property = "password"),
// @Result(column = "d_age",property = "age"),
// })
List list();
// @Delete("delete from t_user where id = #{id}")
void delete(Long id);
}
以上可替代下面的内容:
insert into t_user(username,password,age) values (#{username},#{password},#{age})
update t_user set username=#{username},password=#{password},age=#{age} where id = #{id}
delete from t_user where id = #{id}
问题:mybatis中的方法都是只支持传入一个参数。
如果想传入多个参数.
注意此处要指定resultType
mapper接口中常规如下
1.在方法参数定义Map集合,把需要传入的参数放入map中.
User login(Map map);
测试类中常规:
Map uMap = new HashMap();
uMap.put("username","卡丁");
uMap.put("password","66");
User u = mapper.login(uMap);
System.out.println(u);
mapper接口中如下:
2.使用@Param注解来解决.
User login(@Param("username") String username,@Param("password") String password);
测试类中:
User u = mapper.login("卡丁","66");
System.out.println(u);
员工(Employee)和部门(Department),多对一:员工表中含有外键(部门号)
domain包:
public class Employee {
private Long id;
private String name;
private Department dept;
public Employee() {
}
public Employee(String name) {
this.name = name;
}
//getter setter方法略
}
public class Department {
private Long id;
private String name;
public Department() {
}
public Department(String name) {
this.name = name;
}
//getter setter略去
}
主配置文件添加mapper,添加别名
两mapper接口
public interface EmployeeMapper {
void save(Employee e);
Employee get(Long id);
}
---------------------------
public interface DepartmentMapper {
void save(Department d);
Department get(Long id);
}
两mapper.xml文件
== 注意此处insert中部门号要#{dept.id},就是说从dept中找id==
insert into t_employee(name,dept_id) values (#{name},#{dept.id})
insert into t_department(name) values (#{name})
测试类:
注意:此处many2one的保存操作,要先保存one方,再保存many方
1.保存
@Test
public void testSave(){
SqlSession session = MybatisUtils.openSession();
EmployeeMapper eMapper = session.getMapper(EmployeeMapper.class);
DepartmentMapper dMapper = session.getMapper(DepartmentMapper.class);
Employee e = new Employee();
Department d = new Department();
d.setName("一号部门");
e.setName("一号员工");
e.setDept(d);
dMapper.save(d);
eMapper.save(e);
session.commit();
session.close();
}
}
2.查询
这里有坑需要注意:
简单的查,是不能通过员工把部门也查询出来的,所以EmployeeMapper.xml要配置resultMap
insert into t_employee(name,dept_id) values (#{name},#{dept.id})
1.在myBatis中默认的延时加载时禁用的.
在主配置文件中开启延时加载
lazyLoadingEnabled:默认为false,禁用延时加载.
2.many变成代理对象.
当调用many方的任意属性,都会触发one方的加载.
aggressiveLazyLoading:当启用时, 有延迟加载属性的对象在被调用时将会完全加载任意属性。否则, 每种属性将会按需要加载。
3.在many方默认的调用equals,clone,hashCode,toString 方法都会出发one方的加载
lazyLoadTriggerMethods
主配置文件中配置settings
在查询所有many记录,每个many对应的one都是不同,查询N个many对象,总共会发出N+1条SQL.(性能特别不友好)
使用leftJoin的方式来解决.
这里写于resultMap中,不采用发sql的方式
--------------------------
dept_ 采用 columnPrefix措施简化
生命周期:
和session一样的生命周期.
通过session.get(1L),session.get(1L),总共两次get方法只会发一条SQL.第二次使用的是一级缓存的内容
//清除一级缓存中内容
session.clearCache();
针对数据量大的时候,使用分页+clearCache()及时清除缓存
one需要处理外键关系
员工类中的dept_id属性删除,并在部门类中增加员工对象emps.
public class Department {
private Long id;
private String name;
private List emps = new ArrayList();
public Department() {
}
public Department(String name) {
this.name = name;
}
//getter setter方法
//toString方法(id,name)
}
主配置文件中定义别名,注册mapper:
两个mapper接口
public interface DepartmentMapper {
void save(Department e);
Department get(Long id);
void handlerRelation(@Param("deptId")Long deptId,@Param("empId")Long empId);
}
----------------------------
public interface EmployeeMapper {
void save(Employee e);
Employee get(Long id);
}
两个mapper文件
insert into t_department (name) values (#{name})
update t_employee set dept_id = #{deptId} where id = #{empId}
insert into t_employee (name) values (#{name})
测试:
public class TestOne2Many {
@Test
public void test01() {
SqlSession session = MybatisUtils.openSession();
EmployeeMapper eMapper = session.getMapper(EmployeeMapper.class);
DepartmentMapper dMapper = session.getMapper(DepartmentMapper.class);
Employee e1 = new Employee("一号员工");
Employee e2 = new Employee("二号员工");
Department d = new Department("一号部门");
d.getEmps().add(e1);
d.getEmps().add(e2);
eMapper.save(e1);
eMapper.save(e2);
dMapper.save(d);
//需要由one方去处理外键关系
List es = d.getEmps();
for (Employee e : es) {
dMapper.handlerRelation(d.getId(),e.getId());
}
session.commit();
session.close();
}
@Test
public void testGet() {
SqlSession session = MybatisUtils.openSession();
DepartmentMapper dMapper = session.getMapper(DepartmentMapper.class);
Department dept = dMapper.get(22L);
System.out.println(dept);
List emps = dept.getEmps();
for (Employee emp : emps) {
System.out.println(emp);
}
session.close();
}
}
在这个地方,犯了个错误,就是用insert,update,delete更改数据库中的内容的时候,切记session.commit操作,要不然数据库中内容不会改变.
1.建数据库表,学生表,教师表,中间表(学生id,教师id)
2.教师类学生类分别提供id,name属性,无参及有参(name)构造器,对应属性的getter,setter方法.
3.在主配置文件中定义别名,并注册对应mapper.xml.
4.两个mapper接口
public interface StudentMapper {
void save(Student t);
}
---------------------------------
public interface TeacherMapper {
void save(Teacher t);
void handlerRelation(@Param("teaId")Long teaId,@Param("stuId")Long stuId);
}
两个mapper.xml文件,注意TeacherMapperz中的handlerRelation
insert into t_student(name) values (#{name})
-------------------------------------------------------
insert into t_teacher(name) values (#{name})
insert into tea_stu (t_id,s_id) values (#{teaId},#{stuId})
测试类:
@Test
public void test(){
Teacher t1 = new Teacher();
t1.setName("老师一");
Teacher t2 = new Teacher();
t2.setName("老师二");
Student s1 = new Student();
s1.setName("学生一");
Student s2 = new Student();
s2.setName("学生二");
t1.getStus().add(s1);
t1.getStus().add(s2);
t2.getStus().add(s1);
t2.getStus().add(s2);
SqlSession session = MybatisUtils.openSession();
TeacherMapper tMapper = session.getMapper(TeacherMapper.class);
StudentMapper sMapper = session.getMapper(StudentMapper.class);
tMapper.save(t1);
tMapper.save(t2);
sMapper.save(s1);
sMapper.save(s2);
//来处理中间表的的关系
List t1Stus = t1.getStus();
for (Student student : t1Stus) {
tMapper.handlerRelation(t1.getId(),student.getId());
System.out.println(student);
}
List t2Stus = t2.getStus();
for (Student student : t2Stus) {
tMapper.handlerRelation(t2.getId(),student.getId());
System.out.println(student);
}
session.commit();
session.close();
}
注意
resuilMap代替resultType
mapper接口中提供get方法.
public interface StudentMapper {
Student get(Long id);
}
---------------------------------------
public interface TeacherMapper {
Teacher get(Long id);
}
mapper的xml文件中:
StudentMapper
TeacherMapper
测试:
@Test
public void testQ(){
SqlSession session = MybatisUtils.openSession();
TeacherMapper tMapper = session.getMapper(TeacherMapper.class);
Teacher teacher = tMapper.get(9L);
List stus = teacher.getStus();
for (Student student : stus) {
System.out.println(student);
}
System.out.println(teacher);
session.close();
}
-----------------------分隔符---------------------------------------------------
Mapper的使用
1.把mapper当做是Dao辅助工具
2.直接将mapper当做是Dao.
步骤:
1.导入相关的资源包
1.myBatis自身的包
2.spring相关的包
3.spring-mybatis-plugins.jar整合
数据库连接池druid.
2.创建resources添加配置文件
3.编写配置文件
1.导入外部文件db.properties
2.配置数据源
3.配置sessionFactory
4.配置事务管理器
5.配置事务模板
6.AOP切面配置
定义service,Mapper对应bean.
application.xml中内容如下:
1.service全都变成注解配置的方式.
2.在配置文件中添加注解扫描的配置
3.添加扫描mapper的类
1.回顾hibernate中的缓存
二级缓存的生命周期和sessionFactory一样的生命周期
什么样类型的对象适合放入二级缓存
读远远大于写的对象.
hibernate中的缓存:
1.一级缓存
2.二级缓存
3.查询缓存(限制很多,命中率比较低)
开启二级缓存后,get (),insert(),get(); 总共发2条sql
MyBatis中的二级缓存.
一般来说,我们将myBatis中二级缓存说成是myBatis缓存
步骤:
1.需要在mapper文件中添加
2.缓存的对象需要实现序列化接口
myBatis开启二级缓存后,get (),insert(),get(); 总共发3条sql
在mybatis中无论是selectOne还是selectList都是使用查询缓存.当对象新增,更新,删除的时候,都回去清空查询缓存
让myBatis的缓存和hibernate中的二级缓存靠近
步骤:
1.让所有list都不是缓存 userCache=false
2.让新增操作不清空缓存. flashCache=false