一.Mybatis入门
1.什么是Mybatis
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。
MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis
可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs
(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
2.为什么要用Mybatis
首先大家知道传统JDBC对数据库的操作:
1.加载驱动
2.获取连接
3.获取预处理对象
4.执行SQL语句
5.获取结果集
6.释放资源
而MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
大家都知道ORM思想吗
ORM:将关系数据库中表中的记录映射成为对象,以对象的形式展现,程序员可以把对数据库的操作转化为对对象的操作。(也就是数据库的表对应对象的名,表的字段对应对象的属性)
3.Mybatis快速入门
1.先通过maven创建一个普通项目,在pom.xml中配置相关jar包
2.现在我们可以先准备数据库中的表,程序中的实体类
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
public Integer 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 Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
3.配置mybatis主配置文件,映射配置文件
主配置文件(SqlMapConfig.xml)和映射配置文件(UserDao.xml)放在main下的resource下
<?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">
<!-- Mybatis主配置文件-->
<configuration>
<!-- 配置环境 -->
<environments default="mysql">
<!--配置mysql环境-->
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源(连接池)-->
<dataSource type="POOLED">
<!--配置连接数据库的4个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!--指定映射配置文件的位置,映射配置文件是每个dao独立的配置文件-->
<mappers>
<mapper resource="com/baidu/dao/UserDao.xml"/>
</mappers>
</configuration>
<?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.baidu.dao.UserDao">
<!--配置查询所有-->
<select id="findAll" resultType="com.baidu.domain.User">
select * from user
</select>
</mapper>
namespace:作用在哪儿个dao层接口
resultType:查询出来的结果封装在哪儿个实体类中
4.创建dao层的UserDao出来,Mybatis入门的准备配置的也差不多了,就可以测试了,在test编写测试类
public class MybatisTest {
public static void main(String[] args) throws Exception {
//1.读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3.使用工厂生产SqlSession对象
SqlSession session = factory.openSession();
//4.使用SqlSession创建Dao接口代理对象
UserDao dao = session.getMapper(UserDao.class);
//5.使用代理对象执行方法
List<User> users = dao.findAll();
for (User user: users) {
System.out.println(user);
}
//6.释放资源
session.close();
in.close();
}
}
查询结果:
二.Mybatis进阶(xml配置)
单表操作
1.主配置文件
细心地人会发现入门的配置代码还是有些许繁琐,这样我们对入门代码改进一下,并且认识新的标签
<?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>
<!-- properties标签 -->
<!--可以在内部配置数据库的信息,也可以通过属性引入外部配置信息
1:resource:用于指定配置文件的位置,是按照类路径写的,并且必须存在类路径下
2: url:是要求按照url写法来写地址:协议+主机+端口+URI
-->
<properties resource="jdbcConfig.properties">
<!--<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>-->
</properties>
<typeAliases>
<!-- typeAlias用于配置别名,type是实体类全限定类名,alias是别名,设置里别名不区分大小写 -->
<!-- package指定配置别名的包,当指定后,该包下的实体类都会注册别名,类名就是别名,不区分大小写-->
<!-- <typeAlias type="com.baidu.domain.User" alias="user"></typeAlias>-->
<package name="com.baidu.domain"/>
</typeAliases>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<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>
<mappers>
<!--<mapper resource="com/baidu/dao/UserDao.xml"/>-->
<!-- package标签用于指定dao接口所在的包,当指定了,就不需要在写mapper以及resource和class了-->
<package name="com.baidu.dao"/>
</mappers>
</configuration>
外部配置文件:
properties :通过引入外部配置文件来配置数据库信息,这样在改数据库时不用改代码,直接改配置文件,显得更方便
typeAliases:typeAlias用于配置别名,type是实体类全限定类名,alias是别名,设置里别名不区分大小写
typeAliases下的package:指定配置别名的包,当指定后,该包下的实体类都会注册别名,类名就是别名,不区分大小写
mappers下的package:用于指定dao接口所在的包,当指定了,就不需要在写mapper以及resource和class了
2.在UserDao中增加几个操作数据库的方法,于是配置映射文件UserDao.xml进行单表操作
</select>
<!--添加用户-->
<insert id="addUser" parameterType="user">
insert into user (username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address})
</insert>
<!--更新用户-->
<update id="updateUser" parameterType="user">
update user set username = #{username},birthday = #{birthday},sex = #{sex},address = #{address} where id = #{id}
</update>
<!--删除用户-->
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id = #{id}
</delete>
<!--根据id查询用户-->
<select id="findById" parameterType="int" resultType="user">
select * from user where id = #{id}
</select>
<!--根据姓名模糊查询-->
<select id="findByName" parameterType="string" resultType="user">
select * from user where username like #{name}
</select>
parameterType:指定传入的参数类型
注意:#{}和${}区别
#{}:相当于占位符
${}:相当于字符串
3.单表操作中的动态SQL
<!-- 根据给的条件查询所有-->
<select id="findByCondition" parameterType="user" resultType="user">
<!--select * from user where 1=1
<if test="username != null">
and username = #{username}
</if>
<if test="address != null">
and address like #{address}
</if>-->
select * from user
<where>
<if test="username != null">
and username = #{username}
</if>
<if test="address != null">
and address like #{address}
</if>
</where>
</select>
<!-- 根据QueryVo中的id集合查询对象-->
<select id="findByInIds" parameterType="queryVo" resultType="user">
select * from user
<where>
<if test="ids!=null and ids.size()>0">
<foreach collection="ids" open="and id in(" close=")" item="id" separator=",">
#{id}
</foreach>
</if>
</where>
</select>
if标签: 当不确定传入的参数条件时,可以使用if标签进行拼接字符串 ,但是查询语句后要加where 1=1 这个恒成立的式子,
where标签:无需加where 1=1 ,where标签包含if标签更为方便
foreach标签:collection:集合,open:开始,close:结束,item:查询的参数,separator:分隔符
多表操作
1. 多对一(mybatis中称之为一对一)
先再建立一个数据库表(account)和实体类(Account)
并生成相应的get/set方法,并重写toString方法
配置映射文件AccountDao.xml
<mapper namespace="com.baidu.dao.AccountDao">
<!--定义封装account和user的resultMap-->
<resultMap id="accountUser" type="account">
<id property="id" column="id"></id>
<result property="uid" column="uid"></result>
<result property="money" column="money"></result>
<!--一对一的关系映射,配置封装user的内容-->
<association property="user" column="uid" javaType="user" select="com.baidu.dao.UserDao.findById"></association>
</resultMap>
<!-- 查询所有账户信息并带有用户信息-->
<select id="findAll" resultMap="accountUser" >
select * from account
</select>
<!--根据用户uid查询账户信息-->
<select id="findByUid" parameterType="int" resultType="account">
select * from account where uid = #{uid}
</select>
</mapper>
resultMap :封装结果。id:指定唯一标识,用来引用,type:封装的类型,property:对应的是实体类属性,column:对应的是表的列名
association :一对一的关系映射,配置封装user的内容。javaType:封装的类型,select:查询user方法的全限定类名
2. 一对多
生成相应的get/set方法,并重写toString方法
配置映射文件UserDao.xml
<mapper namespace="com.baidu.dao.UserDao">
<resultMap id="userAccount" type="user">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="address" column="address"></result>
<result property="sex" column="sex"></result>
<result property="birthday" column="birthday"></result>
<!-- 配置user对象中account集合映射-->
<collection property="accounts" ofType="account" select="com.baidu.dao.AccountDao.findByUid" column="id"></collection>
</resultMap>
<!--查询所有并且带有所有账户信息-->
<select id="findAll" resultMap="userAccount" >
select * from user
</select>
<!-- 根据id查询 -->
<select id="findById" parameterType="int" resultType="user">
select * from user where id = #{uid}
</select>
</mapper>
collection :配置user对象中account集合映射,property:实体类中的属性,ofType:集合中的对象类型,select:查询account的方法全限定类名
关于延迟加载:
延迟加载又叫按需加载,就是什么时候想要就什么时候查询。当一对一的时候,一般为立即加载,但是一对多时,当我们查询用户时,有时需要账户信息,有时不需要。在实际开发中,如果可以单表查询的东西绝不用多表去查询,因为单表查询性能会比多表查询性能要好。
所以当操作一对多时,就可以在主配置文件中打开延迟加载
<!-- 配置参数:延迟加载-->
<settings>
<!-- 开启mybatis支持延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
3. 多对多
多对多关系映射:两表互相包含对方实体的集合
多对多本质上和一对多差不多,需要互相配置
如果你能跟着上述步骤做完,你的Mybatis也算入门了,这只是我的一个小小学习记录,并不是什么教学,希望大家如果进来就点个赞吧!