一. 注解开发实现CRUD【重要】
1. Mapper接口中使用注解
public interface StudentMapper {
//查询全部
@Select("SELECT * FROM student")
public abstract List<Student> selectAll();
//新增操作
@Insert("INSERT INTO student VALUES (#{id},#{name},#{age})")
public abstract Integer insert(Student stu);
//修改操作
@Update("UPDATE student SET name=#{name},age=#{age} WHERE id=#{id}")
public abstract Integer update(Student stu);
//删除操作
@Delete("DELETE FROM student WHERE id=#{id}")
public abstract Integer delete(Integer id);
}
2. 核心配置文件引入Mapper
文件结构
<!--核心配置文件中配置-->
<!--加载映射文件-->
<mappers>
<!--引入mapper接口的位置-->
<!--使用mapper配置文件配置,class里面使用Mapper类的全类名-->
<!--<mapper class="com.itheima.mapper.StudentMapper"/>-->
<!--引入整个mapper包(扫包)-->
<package name="com.itheima.mapper"/>
</mappers>
3. 测试类
public class Test01 {
@Test
public void selectAll() throws Exception{
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.获取StudentMapper接口的实现类对象
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//5.调用实现类对象中的方法,接收结果
List<Student> list = mapper.selectAll();
//6.处理结果
for (Student student : list) {
System.out.println(student);
}
//7.释放资源
sqlSession.close();
is.close();
}
@Test
public void insert() throws Exception{
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.获取StudentMapper接口的实现类对象
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//5.调用实现类对象中的方法,接收结果
Student stu = new Student(4,"赵六",26);
Integer result = mapper.insert(stu);
//6.处理结果
System.out.println(result);
//7.释放资源
sqlSession.close();
is.close();
}
@Test
public void update() throws Exception{
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.获取StudentMapper接口的实现类对象
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//5.调用实现类对象中的方法,接收结果
Student stu = new Student(4,"赵六",36);
Integer result = mapper.update(stu);
//6.处理结果
System.out.println(result);
//7.释放资源
sqlSession.close();
is.close();
}
@Test
public void delete() throws Exception{
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.获取StudentMapper接口的实现类对象
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//5.调用实现类对象中的方法,接收结果
Integer result = mapper.delete(4);
//6.处理结果
System.out.println(result);
//7.释放资源
sqlSession.close();
is.close();
}
}
4. 注意事项
(1)在使用注解的时候,如果核心配置文件中进行了扫包,那就可以不需要mapper.xml文件
(2)如果核心配置文件中配置了扫包的方式,在不使用注解,而使用mapper.xml的时候,xml文件和mapper文件放在同一个目录下,并且命名要相同
(3)如果配置扫包,注解方式和mapper.xml方式不能同时存在在mapper包内
二. 注解实现多表开发【重要】
实现复杂关系映射之前我们可以在映射文件中通过配置<resultMap>
来实现,使用注解开发后,我们可以使用@Results注解,@Result注解,@One注解,@Many注解组合完成复杂关系的配置
1. 一对一
1.1 CardMapper接口中查询全部
public interface CardMapper {
//查询全部
@Select("SELECT * FROM card")
//指定一对一封装的结果
/*
property:被包含对象的变量名
javaType:被包含对象的实际数据类型
column:根据查询出的card表中的pid字段来查询person表
one=@One()一对一固定写法
select属性:指定调用哪个接口中的哪个方法(一定要使用接口的全类名)
*/
@Results({
@Result(column = "id",property = "id"),
@Result(column = "number",property = "number"),
@Result(
property = "p", //被包含对象的变量名
javaType = Person.class,//被包含对象的实际数据类型
column = "pid", //根据查询出的card表中的pid字段来查询person表
/*
one、@One 一对一固定写法
select属性:指定调用哪个接口中的哪个方法
*/
one = @One(select = "com.itheima.one_to_one.PersonMapper.selectById")
)
})
public abstract List<Card> selectAll();
}
1.2 PersonMaper接口中根据id查询
public interface PersonMapper {
@Select("select * from person where id=#{id}")
Person selectById(Integer id);
}
1.3 测试方法
/*
测试一对一关系:查询所有card的信息,包括每个card对应的person信息
*/
@Test
public void selectAll() throws Exception{
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.获取CardMapper接口的实现类对象
CardMapper mapper = sqlSession.getMapper(CardMapper.class);
//5.调用实现类对象中的方法,接收结果
List<Card> list = mapper.selectAll();
//6.处理结果
for (Card card : list) {
System.out.println(card);
}
//7.释放资源
sqlSession.close();
is.close();
}
2. 一对多
2.1 ClassesMapper接口中查询全部
public interface ClassesMapper {
//查询全部
@Select("SELECT * FROM classes")
//指定一对多封装的结果
/*
property: 被包含对象的变量名
javaType: 被包含对象的实际数据类型
column: 根据查询出的classes表的id字段来查询student表
many=@Many: 一对多查询的固定写法
select属性:指定调用哪个接口中的哪个查询方法
*/
@Results({
@Result(column = "id",property = "id"),
@Result(column = "name",property = "name"),
@Result(
property = "students", //被包含对象的变量名
javaType = List.class, //被包含对象的实际数据类型
column = "id", //根据查询出的classes表的id字段来查询student表
/*
many、@Many 一对多查询的固定写法
select属性:指定调用哪个接口中的哪个查询方法
*/
many = @Many(select = "com.itheima.one_to_many.StudentMapper.selectByCid")
)
})
public abstract List<Classes> selectAll();
}
2.2 StudentMaper接口中根据id查询
public interface StudentMapper {
@Select("select * from student where cid=#{cid}")
List<Student> selectByCid(int cid);
}
2.3 测试方法
/*
测试一对多关系:查询所有班级以及该班级的所有学生信息
*/
@Test
public void selectAll() throws Exception{
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.获取ClassesMapper接口的实现类对象
ClassesMapper mapper = sqlSession.getMapper(ClassesMapper.class);
//5.调用实现类对象中的方法,接收结果
List<Classes> list = mapper.selectAll();
//6.处理结果
for (Classes cls : list) {
System.out.println(cls.getId() + "," + cls.getName());
List<Student> students = cls.getStudents();
for (Student student : students) {
System.out.println("\t" + student);
}
}
//7.释放资源
sqlSession.close();
is.close();
}
3. 多对多
3.1 StudentMapper接口中查询全部
public interface StudentMapper {
//查询全部
@Select("SELECT DISTINCT s.id,s.name,s.age FROM student s,stu_cr sc WHERE sc.sid=s.id")
//指定多对多封装的结果
/*
property: 被包含对象的变量名
javaType: 被包含对象的实际数据类型
column: 根据查询出student表的id来作为关联条件,去查询中间表和课程表
many=@Many 一对多查询的固定写法
select属性:指定调用哪个接口中的哪个查询方法
*/
@Results({
@Result(column = "id",property = "id"),
@Result(column = "name",property = "name"),
@Result(column = "age",property = "age"),
@Result(
property = "courses", //被包含对象的变量名
javaType = List.class,//被包含对象的实际数据类型
column = "id", //根据查询出student表的id来作为关联条件去查询中间表和课程表
/*
many=@Many 一对多查询的固定写法
select属性:指定调用哪个接口中的哪个查询方法
*/
many = @Many(select = "com.itheima.many_to_many.CourseMapper.selectBySid")
)
})
public abstract List<Student> selectAll();
}
3.2 CourseMaper接口中根据id查询
public interface CourseMapper {
@Select("select c.* from stu_cr sc,course c where sc.cid=c.id and sc.sid=#{sid}")
public List<Course> selectBySid(Integer sid);
}
3.3 测试方法
/*
测试多对多关系:查询所有学生及其选课信息
*/
@Test
public void selectAll() throws Exception{
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.获取StudentMapper接口的实现类对象
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//5.调用实现类对象中的方法,接收结果
List<Student> list = mapper.selectAll();
//6.处理结果
for (Student student : list) {
System.out.println(student.getId() + "," + student.getName() + "," + student.getAge());
List<Course> courses = student.getCourses();
for (Course cours : courses) {
System.out.println("\t" + cours);
}
}
//7.释放资源
sqlSession.close();
is.close();
}
三. 构建SQL【了解】
1. 提供类和方法返回Sql语句
public class ReturnSql {
//定义方法,返回查询的sql语句
public String getSelectAll() {
return new SQL() {
{
SELECT("*");
FROM("student");
}
}.toString();
}
//定义方法,返回新增的sql语句
public String getInsert(Student stu) {
return new SQL() {
{
INSERT_INTO("student");
INTO_VALUES("#{id},#{name},#{age}");
}
}.toString();
}
//定义方法,返回修改的sql语句
public String getUpdate(Student stu) {
return new SQL() {
{
UPDATE("student");
SET("name=#{name}","age=#{age}");
WHERE("id=#{id}");
}
}.toString();
}
//定义方法,返回删除的sql语句
public String getDelete(Integer id) {
return new SQL() {
{
DELETE_FROM("student");
WHERE("id=#{id}");
}
}.toString();
}
}
2. 在Mapper接口方法上替换
//利用@XxxxProvider来使用构建的sql
public interface StudentMapper {
//查询全部
//@Select("SELECT * FROM student")
@SelectProvider(type = ReturnSql.class , method = "getSelectAll")
public abstract List<Student> selectAll();
//新增功能
//@Insert("INSERT INTO student VALUES (#{id},#{name},#{age})")
@InsertProvider(type = ReturnSql.class , method = "getInsert")
public abstract Integer insert(Student stu);
//修改功能
//@Update("UPDATE student SET name=#{name},age=#{age} WHERE id=#{id}")
@UpdateProvider(type = ReturnSql.class , method = "getUpdate")
public abstract Integer update(Student stu);
//删除功能
//@Delete("DELETE FROM student WHERE id=#{id}")
@DeleteProvider(type = ReturnSql.class , method = "getDelete")
public abstract Integer delete(Integer id);
}
3. 测试类测试
@Test
public void selectAll() throws Exception{
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.获取StudentMapper接口的实现类对象
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//5.调用实现类对象中的方法,接收结果
List<Student> list = mapper.selectAll();
//6.处理结果
for (Student student : list) {
System.out.println(student);
}
//7.释放资源
sqlSession.close();
is.close();
}
@Test
public void insert() throws Exception{
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.获取StudentMapper接口的实现类对象
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//5.调用实现类对象中的方法,接收结果
Student stu = new Student(4,"赵六",26);
Integer result = mapper.insert(stu);
//6.处理结果
System.out.println(result);
//7.释放资源
sqlSession.close();
is.close();
}
@Test
public void update() throws Exception{
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.获取StudentMapper接口的实现类对象
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//5.调用实现类对象中的方法,接收结果
Student stu = new Student(4,"赵六",36);
Integer result = mapper.update(stu);
//6.处理结果
System.out.println(result);
//7.释放资源
sqlSession.close();
is.close();
}
@Test
public void delete() throws Exception{
//1.加载核心配置文件
InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.获取SqlSession工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.通过工厂对象获取SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.获取StudentMapper接口的实现类对象
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//5.调用实现类对象中的方法,接收结果
Integer result = mapper.delete(4);
//6.处理结果
System.out.println(result);
//7.释放资源
sqlSession.close();
is.close();
}
4. 构建动态sql
public class ReturnSql {
public String getSelectCondition(Student stu){
//select * from student where id=#{id} and name=#{name} and age=#{age}
//创建初始化语句
SQL sql = new SQL().SELECT("*").FROM("student");
//判断
if(stu!=null && stu.getId()!=null){
sql.WHERE("id=#{id}");
}
if(stu!=null && stu.getName()!=null){
sql.WHERE("name=#{name}"); //where方法会自动添加上and关键字
}
if(stu!=null && stu.getAge()!=null){
sql.WHERE("age=#{age}"); //where方法会自动添加上and关键字
}
return sql.toString();
}
/*public String getSelectCondition(Student stu){
//select * from student where id=#{id} and name=#{name} and age=#{age}
//创建初始化语句
StringBuilder sb=new StringBuilder("select * from student where 1=1");
//判断
if(stu!=null && stu.getId()!=null){
sb.append(" and id=#{id}");
}
if(stu!=null && stu.getName()!=null){
sb.append(" and name=#{name}");
}
if(stu!=null && stu.getAge()!=null){
sb.append(" and age=#{age}");
}
return sb.toString();
}*/
}
四. 案例改进
1. 项目环境搭建
(1)执行给定的sql,创建项目需要的数据库和表。
(2)创建动态web项目,项目名为mybatis_sms。
(3)将资料中mybatis_sms中的src目录和web目录中的所有内容复制到自己的mybatis_sms中
(4)修改config.properties中连接数据库的参数
2. mybatis环境搭建
(1)导入Mybatis的jar包和log4j的jar包
(2)导入核心配置问题和log4j配置文件和MyBatisUtils工具类
(3)修改核心配置文件中的数据库配置文件名称,标签中的路径也需要修改
(4)在StudentDao的方法上加上注解查询的sql语句
(5)在StudentServiceImpl中重写findAll()方法,使用接口代理的方式实现
3. 删除StudentDaoImpl,在StudentDao接口中使用注解配置CRUD
/*
Dao层接口
*/
public interface StudentDao {
//查询所有学生信息
@Select("select * from student")
public abstract ArrayList<Student> findAll();
//条件查询,根据id获取学生信息
@Select("select * from student where sid=#{id}")
public abstract Student findById(Integer id);
//新增学生信息
@Insert("insert into student values (#{sid},#{name},#{age},#{birthday})")
public abstract int insert(Student stu);
//修改学生信息
@Update("update student set name=#{name},age=#{age},birthday=#{birthday} where sid=#{sid}")
public abstract int update(Student stu);
//删除学生信息
@Delete("delete from student where sid=#{sid}")
public abstract int delete(Integer id);
}
4. 在utils包下导入编写好的MybatisUtils工具类
public class MyBatisUtils {
//私有构造方法
private MyBatisUtils(){}
//声明工厂对象
private static SqlSessionFactory sqlSessionFactory;
//提供静态代码块,读取核心配置文件,并给工厂对象赋值
static {
try {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsReader("MyBatisConfig.xml"));
} catch (IOException e) {
e.printStackTrace();
}
}
//提供静态方法,获取SqlSession对象
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession(true);
}
}
5. 在StudentServiceImpl中使用mybatis接口代理方式实现dao
public class StudentServiceImpl implements StudentService {
@Override
public List<Student> findAll() {
//获SQLSession对象
SqlSession sqlSession = MyBatisUtils.getSqlSession();
//获取StudentDao接口的实现类对象
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
//调用实现类对象响应的功能
ArrayList<Student> list = mapper.findAll();
//释放资源
sqlSession.close();
//返回结果
return list;
}
@Override
public Student findById(Integer sid) {
//获SQLSession对象
SqlSession sqlSession = MyBatisUtils.getSqlSession();
//获取StudentDao接口的实现类对象
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
//调用实现类对象响应的功能
Student stu = mapper.findById(sid);
//释放资源
sqlSession.close();
//返回结果
return stu;
}
@Override
public void save(Student student) {
//获SQLSession对象
SqlSession sqlSession = MyBatisUtils.getSqlSession();
//获取StudentDao接口的实现类对象
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
//调用实现类对象响应的功能
mapper.insert(student);
//释放资源
sqlSession.close();
}
@Override
public void update(Student student) {
//获SQLSession对象
SqlSession sqlSession = MyBatisUtils.getSqlSession();
//获取StudentDao接口的实现类对象
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
//调用实现类对象响应的功能
mapper.update(student);
//释放资源
sqlSession.close();
}
@Override
public void delete(Integer sid) {
//获SQLSession对象
SqlSession sqlSession = MyBatisUtils.getSqlSession();
//获取StudentDao接口的实现类对象
StudentDao mapper = sqlSession.getMapper(StudentDao.class);
//调用实现类对象响应的功能
mapper.delete(sid);
//释放资源
sqlSession.close();
}
}