1.Mybatis简述
1.概述:MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
JDBC连接:
//加载驱动
class.forname("com.mysql.cj.jdbc.Driver");
//获取连接对象并获取连接
String url = "";
String user ="root";
String password ="";
Connection connecton = DriverManager.getconnection("url","user","password");
//定义sql语句
String sql = "select * from user";
//获取执行sql对象
PreparedStatement statement=connection.prepareStatement(sql);
//给占位符赋值
prepareStatement.setString(1,name);
prepareStatement.setString(2,password);
//执行命令
ResultSet resultSet = PreparedStatement.executeQuery()
//处理
return resultSet.next()
Mybatis与hibernate的区别
-
hibernate:全自动映射 ORM框架,不需要自己手动去写SQL语句
-
mybatis:半自动ORM框架,需要自己手动去写SQL语句
-
开发速度不同
-
工作量对比: 针对高级查询,Mybatis需要手动编写SQL语句,以及ResultMap。
-
Hibernate有良好的映射机制,开发者无需关心SQL的生成与结果映射,可以更专注于业务流程。
-
-
优化程度
-
MyBatis可以进行更为细致的SQL优化,可以减少查询字段。
-
-
掌握程度
-
MyBatis容易掌握,而Hibernate门槛较高。
-
2.Mybatis 环境搭载
导入maven依赖包
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.9</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/jstl/jstl -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/taglibs/standard -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
</dependencies>
- 创建jdbc.properties文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/manage?
jdbc.username=root
jdbc.password=""
- 配置mybatis核心文件
mybaties-config.xml
<?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>
<!-- MyBatis核心配置文件中的标签必须按照指定顺序配置
(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,
objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?)-->
<!--<!– 引入properties 此后在当前文件中使用${key}的方式访问value -- >-->
<properties resource="jdbc.properties"/>
<!-- typeAliases 设置类型别名,即为某个具体的类型设置一个别名-->
<typeAliases>
<!-- <typeAlias type="entity.dao1.Message" alias="abc"></typeAlias>-->
<!-- 若不设置alias,当前类型拥有默认别名Message,不区分大小写-->
<!-- <typeAlias type="entity.dao1.Message"></typeAlias>-->
<!-- 指定包设置类型别名,指定包下所有的类型将全部拥有,默认别名-->
<package name="entity.dao1"/>
</typeAliases>
<!--environments:配置连接数据库环境
属性:
default:设置默认使用的环境的id
-->
<environments default="development">
<!--
<environment>:设置一个具体的连接数据库的环境
属性:
id:是指环境的唯一标识,不能重复
-->
<environment id="development">
<!-- transactionManager:设置事务管理器
属性:
type:设置事务管理方式
type=“JDBC|MANAGED
JDBC:表示使用JDBC中原生的事务管理方式
MANAGED:被管理,例如spring
-->
<transactionManager type="JDBC"/>
<!--
dataSource:设置数据源的类型
属性:
type="POOLED|UNPOOLED|JNDI"
POOLED:表示使用数据库连接池
UNPOOLED:表示不使用数据库连接池
JNDI:表示使用上下文中的数据源
-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--引入mybaties的映射文件-->
<mappers>
<!-- 以包的方式引入映射文件
1.mapper接口和映射文件所在的包必须一致
2.mapper接口的名字和映射文件的文字必须一致
-->
<package name="dao"/>
<!-- <mapper resource="mappers/UserMapper.xml"/>-->
</mappers>
</configuration>
映射文件UserMapper.xml
映射文件对应了mysql中的sql语句
注意Mybatis中可以面向接口操作数据,但要保证俩个一致:
a>mapper接口的全类名和映射文件的命名空间(namespace)保持一致
b>mapper接口中的方法名和映射文件中编写Sql的标签的id属性保持一致
<?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="dao.UserMapper">
</mapper>
dao包下UserMapper接口
这个Mapper接口跟以前dao包下的接口一样,但是我们不需要创建它的实现类,可以通过mybatis的一些功能来具体实现这个接口,调用这个接口中的方法就可以对应sql语句,实现功能
package dao;
import entity.dao1.Message;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
* mybaties获取参数值的俩种方式:#{} 和${}
* 1.若mapper接口方法的参数为单个的字面量类型
*此时可以通过#{} 和${}以任意内容获取参数值,一定要注意${}的单引号问题
* #{}的本质是占位符赋值,${}的本质是字符串拼接
* 2.若mapper接口方法的参数为多个的字面量类型
* 此时MyBatis会将参数放在map集合中,以俩种方式存储数据
* 以arg0,arg1 ... 为键,以参数为值
* 以param1,param2 ...为键,以参数为值
* 因此,只需要通过#{}和${}访问,一定要注意${}的单引号问题
* 3.若mapper接口方法的参数为map集合类型的参数
* 只需要通过#{}和${}访问,一定要注意${}的单引号问题
* 4.若mapper方法中的接口方法的参数为实体类类型的参数
* 只需要通过#{}和${}访问实体类中的属性名,就可以获取相对应的属性值,一定要注意${}的单引号问题
* 5.可以在mapper接口方法的参数上设置@Param注解
* 此时MyBatis会将参数放在map中,以俩种方式进行存储
* a>以@Param注解的value属性值为键,以参数为值
* b>以param1,param2 ...为键,以参数为值
*/
public interface UserMapper {
/**
* 查询
* @return
*/
List<Message> select();
/**
* 修改用户信息
* @return
*/
int updateUser();
/**
* 删除
* @return
*/
int delete();
/**
* 新增数据
* @return
*/
int insert();
/**
* 根据用户名查询用户信息
* @param name
* @return
*/
Message getUserByUsername(String name);
/**
* 查询用户名密码 验证登录
* @param name
* @param password
* @return
*/
Message checkLogin(String name ,String password);
/**
* 验证登录
* @param map
* @return
*/
Message checklogin1(Map<String,Object> map);
/**
* 添加用户信息
* @param message
* @return
*/
int add(Message message);
/**
* 模糊查询表
* @param username
* @param password
* @return
*/
Message checkLoginByParam(@Param("username") String username, @Param("password")String password);
/**
* 动态设置表名
*/
List<Message> getMessageList(@Param("tableName") String tableName);
/**
* 批量删除
* @param ids
* @return
*/
int delete_table (@Param("ids") String ids);
/**
* 添加用户信息
* 获取自增主键
*/
void insertKey(Message message);
}
entity包下的实体类,数据库中一个表对应一个实体类/
package entity.dao1;
public class Message {
private int id;
private String username;
private String password;
public int getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
创建SqlSession工具类
public static SqlSession getsqlSession(){
SqlSession sqlSession =null;
try {
//获取核心配置文件的输入流
InputStream is = Resources.getResourceAsStream("mybaties-config.xml");
//获取SqlSessionFactoryBuilder对象(Mybatis封装的是jdbc,所以我们需要找到一个执行sql语句的入口,来帮我们执行sql语句的一个对象)
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new
SqlSessionFactoryBuilder();
//SqlSssionFactory是一个工厂对象,帮助我们提供SqlSession,根据核心配置文件输入流获取 SqlSession对象
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
//获取Sql的会话对象SqlSession,是mybatis提供的操作数据库的对象
sqlSession = sqlSessionFactory.openSession(true);
} catch (IOException e) {
e.printStackTrace();
}
return sqlSession;
}
创建测试类
SqlSession sqlSession = SqlSessionUntil.getsqlSession();
//创建mapper对象,但是mapper是接口,不能实例,获取UserMapper的代理实现类对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//底层使用代理模式,帮助我们创建实体类对象,让我们来实现接口中的方法
- 静态sql的增删改查
-
<insert id="add"> insert into message(username,password) values ("yangwenjie","123456") </insert> <update id="update"> update message set username ="qige" where username="yangwenjie" </update> <delete id="delete"> delete from message where username="qige" </delete> <!--resultType 具体的类型 map,double,int,实体类--> <select id="select_all" resultType="entity.abc.User"> select * from message; </select>
静态sql占位符有参
-
1.若mapper接口方法的参数为单个的字面量类型 *此时可以通过#{} 和${}以任意内容获取参数值,一定要注意${}的单引号问题 * #{}的本质是占位符赋值,${}的本质是字符串拼接 * 2.若mapper接口方法的参数为多个的字面量类型 * 此时MyBatis会将参数放在map集合中,以俩种方式存储数据 * 以arg0,arg1 ... 为键,以参数为值 * 以param1,param2 ...为键,以参数为值 * 因此,只需要通过#{}和${}访问,一定要注意${}的单引号问题 * 3.若mapper接口方法的参数为map集合类型的参数 * 只需要通过#{}和${}访问,一定要注意${}的单引号问题 * 4.若mapper方法中的接口方法的参数为实体类类型的参数 * 只需要通过#{}和${}访问实体类中的属性名,就可以获取相对应的属性值,一定要注意${}的单引号问题 * 5.可以在mapper接口方法的参数上设置@Param注解 * 此时MyBatis会将参数放在map中,以俩种方式进行存储 * a>以@Param注解的value属性值为键,以参数为值 * b>以param1,param2 ...为键,以参数为值
-
<select id="checkLogin" resultType="Message"> select username,password from message where username=#{arg0} and password = #{arg1} </select> <insert id="add1"> insert into message(username,password) values ('${username}',"123456") </insert> <update id="update_username"> update message set username =#{username} where id =2; </update>
动态sql
-
<!--模糊查询--> <select id="checkLoginByParam" resultType="Message"> <!-- select * from message where username like "%"#{mohu}"%"--> <!-- select * from message where username like '%${mohu}%'--> </select> <!--动态表名--> <select id="getMessageList" resultType="Message"> select id,username,password from ${tableName}; </select> <!--批量删除 若为#{}得话会自动加上引号导致sql错误--> <delete id="delete_table"> delete from message where id in(${ids}) </delete>
对应的mapper接口
/** * 模糊查询表 * @param username * @param password * @return */ Message checkLoginByParam(@Param("username") String username, @Param("password")String password); /** * 动态设置表名 */ List<Message> getMessageList(@Param("tableName") String tableName); /** * 批量删除 * @param ids * @return */ int delete_table (@Param("ids") String ids);
类型别名(typeAliases)
-
<typeAliases> <!-- <typeAlias type="entity.dao1.Message" alias="abc"></typeAlias>--> <!-- 若不设置alias,当前类型拥有默认别名Message,不区分大小写--> <!-- <typeAlias type="entity.dao1.Message"></typeAlias>--> <!-- 指定包设置类型别名,指定包下所有的类型将全部拥有,默认别名--> <package name="entity.dao1"/> </typeAliases>
mybatis-config.xml引入映射文件的俩种方式
<!--引入mybaties的映射文件--> <mapper resource="dao/UserMapper.xml"></mapper> <!-- 以包的方式引入映射文件 1.mapper接口和映射文件所在的包必须一致 2.mapper接口的名字和映射文件的文字必须一致 --> <package name="dao"/> <!-- <mapper resource="mappers/UserMapper.xml"/>--> </mappers>
-
resultMap
-
<!-- resultMap:设置自定义得映射关系 id:唯一标识 type:处理映射关系得实体类得类型 常用得标签 id标签:处理主键和实体类中实现的映射关系 result:处理普通字段和实体类中属性的映射关系 column:映射关系中的字段名,必须是sql查询出的某个字段 property:设置映射关系中的属性的属性名,必须是处理的实体类类型中的属性名 collection:处理一对多的映射关系(处理集合类型的属性) --> <resultMap id="empresult" type="Emp"> <id column="emp_id" property="emp_id"></id> <result column="emp_name" property="emp_name"></result> <result column="age" property="age"></result> <result column="sex" property="sex"></result> </resultMap> <select id="getEmpByEmpId" resultMap="empresult"> select emp_id,emp_name,age,sex,dept_id from emp where emp_id = #{empid} </select>
<resultMap id="empAndDeptResultMapOne" type="Emp"> <id column="emp_id" property="emp_id"></id> <result column="emp_name" property="emp_name"></result> <result column="age" property="age"></result> <result column="sex" property="sex"></result> <result column="dept_id" property="dept.dept_id"></result> <result column="dept_name" property="dept.dept_name"></result> </resultMap> <resultMap id="empAndDeptResultMap" type="Emp"> <id column="emp_id" property="emp_id"></id> <result column="emp_name" property="emp_name"></result> <result column="age" property="age"></result> <result column="sex" property="sex"></result> <!-- association:处理多对一的映射关系(处理处理实体类类型的属性) property:设置需要处理映射关系的属性的属性名 javaType:设置要处理的属性的类型 --> <association property="dept" javaType="Dept"> <id column="dept_id" property="dept_id"></id> <result column="dept_name" property="dept_name"></result> </association> </resultMap> <select id="getEmpAndDeptByEmpId" resultMap="empAndDeptResultMap"> select emp_id,emp_name,age,sex,a.dept_id,b.dept_name from emp a left join dept b on a.dept_id = b.dept_id where a.emp_id=#{empid} </select>
<resultMap id="deptAndEmpResultMaop" type="Dept"> <id column="dept_id" property="dept_id"></id> <result column="dept_name" property="dept_name"></result> <collection property="emps" ofType="Emp"> <!--ofType:设置集合类型的属性中存储的数据的类型--> <id column="emp_id" property="emp_id"></id> <result column="emp_name" property="emp_name"></result> <result column="age" property="age"></result> <result column="sex" property="sex"></result> </collection> </resultMap> <select id="getDeptAndmpBYDeptId" resultMap="deptAndEmpResultMaop"> select emp_id,emp_name,age,sex,a.dept_id,b.dept_name from dept b left join emp a on a.dept_id =b.dept_id where a.dept_id = 1 </select>
-
动态sql的增删查
-
动态sql <if test="emp_name != null and emp_name !=''"> where 1=1
-
<select id="getEmpByConditionone" resultType="Emp">
select emp_id,emp_name,age,sex,dept_id from emp where 1=1
<if test="emp_name != null and emp_name !=''">
and emp_name = #{emp_name}
</if>
<if test="age != null and age !=''">
and age = #{age}
</if>
<if test="sex != null and sex !=''">
and sex = #{sex}
</if>
</select>
-
2.where标签 a.where标签中有条件成立,会自动生成where关键字 b.会自动将where标签中内容前多余的and去掉 但是其中内容后多余的 and无法去掉 c.若where标签中没有任何一个条件成立,则where标签没有任何功能
<select id="getEmpByConditionone" resultType="Emp">
select emp_id,emp_name,age,sex,dept_id from emp where 1=1
<where>
<if test="emp_name != null and emp_name !=''">
and emp_name = #{emp_name}
</if>
<if test="age != null and age !=''">
and age = #{age}
</if>
<if test="sex != null and sex !=''">
and sex = #{sex}
</if>
</where>
</select>
-
3.trim prefix,suffix:在标签中内容前面或后面添加指定内容 prefixOverrides,suffixOverrides:在标签中内容前面或后面去掉指定内容
<select id="getEmpByConditionone" resultType="Emp">
select emp_id,emp_name,age,sex,dept_id from emp where 1=1
<trim prefix="where" suffixOverrides="and">
<if test="emp_name != null and emp_name !=''">
and emp_name = #{emp_name}
</if>
<if test="age != null and age !=''">
and age = #{age}
</if>
<if test="sex != null and sex !=''">
and sex = #{sex}
</if>
</trim>
</select>
-
4. choose,when,otherwise 相当于java中的if...else if...else when至少设置一个,otherwise最多设置一个
<select id="getEmpByChoose" resultType="Emp">
select emp_id,emp_name,age,sex,dept_id from emp
<where>
<choose>
<when test="emp_name !=null and emp_name !=''">
emp_name = #{emp_name}
</when>
<when test="age !=null and age !=''">
age = #{age}
</when>
<when test="sex !=null and sex !=''">
sex = #{sex}
</when>
</choose>
</where>
</select>
-
5. foreach collection = "empIds" 参数名Param 设置要循环的数组或集合 item = “emp” 实体类名 设置用一个字符串来表示数组或集合中的每一个数据 separator="or" 设置每次循环的数据之间的分隔符 open = “循环的所有内容以什么开始” close = “循环以什么结束”
-
<!--批量添加--> <insert id="insertMoreEmp"> insert into emp values <foreach collection="emps" item="emp" separator=","> (null,#{emp.emp_name},#{emp.age},#{emp.sex},null) </foreach> </insert>
<!--批量删除--> <delete id="deleteMoreEmp1"> delete from emp where empid in <foreach collection="empIds" item="emp_id" separator="," open="(" close=")" > #{emp_id} </foreach> </delete> <delete id="deleteMoreEmp"> delete from emp where <!-- collection = "empIds" 参数名Param 设置要循环的数组或集合 item = “emp” 实体类名 设置用一个字符串来表示数组或集合中的每一个数据 separator="or" 设置每次循环的数据之间的分隔符 open = “循环的所有内容以什么开始” close = “循环以什么结束” --> <foreach collection="empIds" item="emp_id" separator="or" > emp_id = #{emp_id} </foreach> </delete>