1、MyBatis是一个基于Java的持久层框架,而持久化是指数据从瞬时状态变为持久状态,持久层是完成持久化工作的代码块-Dao层。即,MyBatis帮助开发人员将数据存入数据库中和从数据库中取数据。通过框架可以减少重复代码,提高开发效率。MyBatis是一个半自动化的ORM框架。
2、MyBatis使用
>导包:
核心包:mybatis-3.2.7.jar
依赖包:
数据库驱动包:
>编写MyBatis的核心配置文件
<?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>
<!-- 通过读取配置文件db.properties,获取连接数据库时需要的参数
<properties resource="db.properties" />
此时在配置数据源dataSource时value值应该写为value="${driver}"
-->
<!-- 为指定类型指定别名 使得在mapper映射文件中可以简化引用
<typeAliases>
<typeAliases type="com.entity.Tea" alias="User" />
为某个包下的所有类指定别名,默认别名是对应的类名
<package name="com.entity" />
</typeAliases>
-->
<!-- environments 指mybatis可以配置多个环境 default指向默认环境
每个SqlSessionFactory对应一个环境environments
-->
<environments default="development">
<environment id="development">
<!-- 事务管理器:类型:JDBC和MANAGED -->
<transactionManager type="JDBC"/>
<!-- 数据源类型:
UNPOOLED这个类型的数据源实现只是在每次需要的时候简单地打开和关闭连接
POOLED连接池实现缓存JDBC连接对象,用于避免每次创建新的数据库连接时都初始化和进行认证,加快程序响应。
JNDI这个数据源的配置是为了准备与像Spring或应用服务器能够在外部或者内部配置数据源的容器一起使用,然后在JDN上下文中引用它
-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/shop?serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="MySQL1003150748"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 定义映射SQL语句文件,可以有多个 -->
<mapper resource="com/myBatis/entity/tea.mapper.xml"/>
</mappers>
</configuration>
>创建sqlSessionFactory
import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class MyBatisUtil {
/*
* 通过配置文件 创建SqlSessionFactory 是一个SqlSession的工厂类
*/
public static SqlSessionFactory getSqlSessionFactory() throws IOException {
String resource = "mybatis.cfg.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
return sqlSessionFactory;
}
/*
* SqlSession通过映射执行sql语句( 通过id找到对应的sql语句,执行sql语句)
*/
public static SqlSession getSession() throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
return sqlSessionFactory.openSession();
}
}
>创建实体类
package com.myBatis.entity;
public class Tea {
private int id ; //饮品编号
private String gname ; //饮品名称
private double gprice ; //饮品价格
public Tea() {}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getGname() {
return gname;
}
public void setGname(String gname) {
this.gname = gname;
}
public double getGprice() {
return gprice;
}
public void setGprice(double gprice) {
this.gprice = gprice;
}
public Tea(int id, String gname, double gprice) {
super();
this.id = id;
this.gname = gname;
this.gprice = gprice;
}
@Override
public String toString() {
return "TeaBean [id=" + id + ", gname=" + gname + ", gprice=" + gprice + "]";
}
}
>编写sql语句的映射文件
<?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">
<!-- namespace命名空间,防止sql语句的id重名
命名:包名+类名/mapper文件名
-->
<mapper namespace="com.myBatis.entity.TeaMapper">
<!-- id在该文件中唯一
resultType
parameterType
useGeneratedKeys="true/false"使用自增主键(insert)
-->
<select id="selectTea" resultType="com.myBatis.entity.Tea">
select * from goodstable where id = #{id}
</select>
</mapper>
>测试类
package com.myBatis.test;
import java.io.IOException;
import org.apache.ibatis.session.SqlSession;
import com.myBatis.entity.Tea;
import com.myBatis.util.MyBatisUtil;
public class Test {
public static void main(String[] args) throws IOException {
SqlSession session = MyBatisUtil.getSession() ;
Tea tea = session.selectOne("com.myBatis.entity.TeaMapper.selectTea",27) ;
System.out.println(tea.getGname());
session.close();
}
}
3、解决实体类中属性名(password)与数据库列名( pwd)不一致的问题
不一致出现的问题:不一致的属性查询的内容为null
不一致的原因在于:mabatis会根据查询的列名调用其setter方法进行设值(在mapper映射文件中定义)
解决办法一:为列名指定别名,别名和java实体类的属性名一致
<select id="selectTea" resultType="com.myBatis.entity.Tea">
select Name, pwd password from goodstable where id = #{id}
</select>
解决方法:
<select id="selectTea" resultMap="TeaMap">
select Name, pwd from goodstable where id = #{id}
</select>
<resultMap type="Tea" id="TeaMap">
<id column="id" property="id" />主键
<result column="pwd" property="password" />数据库中表的列名和java实体类中的属性名
</resultMap>
4、分页的实现
>limit约束实现
mapper映射中定义:
<!-- 查询所有用户并进行分页 -->
<select id="selectAll" parameterType="Map" resultType="com.myBatis.entity.Tea">
select * from goodstable limit #{startIndex},#{pageSize}
</select>
Dao层方法:
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.session.SqlSession;
import com.myBatis.entity.Tea;
import com.myBatis.util.MyBatisUtil;
public class TeaDao {
//分页查询
public List<Tea> getAll(int currentPage,int pageSize) throws IOException {
SqlSession session = MyBatisUtil.getSession() ;
Map<String,Integer> map = new HashMap<String,Integer>();
map.put("startIndex",(currentPage-1)*pageSize); //当前页第一条记录的下标
map.put("pageSize", pageSize);
List<Tea> list = session.selectList("com.myBatis.entity.TeaMapper.selectAll", map);
session.close();
return list;
}
}
>通过RowBounds实现
在mapper映射中直接查询所有:
<select id="selectTea" resultType="com.myBatis.entity.Tea">
select * from goodstable
</select>
在Dao层方法中通过RowBounds实现查询指定条数的分页数据:
//参数index是下标,size是数据
RowBounds rowBounds = new RowBounds((currentPage-1)*pageSize,pageSize);
List<Tea> list = session.selectList("com.myBatis.entity.TeaMapper.selectTea", null, rowBounds)
5、使用注解(本质通过接口)开发映射mapper语句
//编写Dao接口
public interface UserDao {
@Select("select * from user")
public List<User> getList();
@Insert("insert into user(name,pwd) value(#{name},#{pwd})")
public int insert(User user);
}
//mapper映射
<mappers>
<mapper class="com.dao.UserDao" />
</mappers>
//调用
UserDao userDao = session.getMapper(UserDao.class);
//调用userDao中方法……
会通过动态代理生成该接口的实现类,在测试类调用接口中定义的方法时,其实是调用其实现类中的方法
6、数据库表多对一处理
<mapper namespace="com.entity.student.mapper">
<!--多对一处理:(多个学生有同一个老师)
按结果嵌套处理
按查询嵌套处理
-->
<!--按结果嵌套处理-->
<select id="getStudents" resultMap="StudentTeacher">
select s.id sid,s.name sname,s.tid stid,t.id tid,t.name tname from student s,teacher t where s.tid=t.id
</select>
<resultMap type="Student" id="StudentTeacher">
<id column="sid" property="id" />
<result column="sname" property="name" />
<!--关联对象 property关联对象在Student实体类中的属性-->
<association property="teacher" javaType="Teacher" >
<id column="tid" property="id" />
<result column="tname" property="name" />
</association>
</resultMap>
————————————————————————————————————————————————————————
<!--按查询嵌套处理-->
<select id="getStudents" resultMap="StudentTeacher">
select * from student
</select>
<resultMap type="Student" id="StudentTeacher">
<!--association关联属性 property属性名 javaType属性的类型 column关联属性在多的一方表中列名 select根据"tid"去查询 -->
<association property="teacher" column="tid" javaType="Teacher" select="getTeacher">
</association>
</resultMap>
<selest id="getTeacher" resultType="Teacher">
select * from teacher where id=#{id}
</select>
</mapper>
7、表中一对多处理
<!--一对多(一个老师有多名学生)处理-->
<select id="getStudents" resultMap="TeacherStudent">
select s.id sid,s.name sname,s.tid stid,t.id tid,t.name tname from student s,teacher t where s.tid=t.id
</select>
<resultMap type="Teacher" id="TeacherStudent">
<id column="tid" property="id" />
<result column="tname" property="name" />
<collection property="students" ofType="Student" >
<id column="sid" property="id" />
<result column="sname" property="name" />
</collection>
</resultMap>
————————————————————————————————————————————————————————
<select id="getTeacher" resultMap="TeacherStudent">
select * from teacher where id=#{id}
</select>
<resultMap type="Teacher" id="TeacherStudent">
<collection property="students" column="id" javaType="ArrayList" ofType="student" select="getStudentByTid">
</association>
</resultMap>
<select id="getStudentByTid" resultType="Student">
select * from student where tid=#{id}
</select>
8、动态sql
动态sql指根据不同的查询条件,生成不同的sql语句
Mapper文件
<mapper namespace="">
<select id="" parameterType="" resultType="">
select * from user
<where>
<if test="name!=null">
name like CONCAT('%',#{name},'%')
</if>
</where>
<select>
</mapper>
注:mybatis中like查询要使用CONCAT字符连接