Mybatis
概述:
mybatis是一个持久层框架, 用Java编写
它封装了jdbc操作的很多细节, 是开发者只需要关注SQL语句本身,而无需关注注册驱动, 创建连接等繁杂过程
它使用了ORM思想实现了结果集的封装.
ORM:Object Relational Mappging 对象关系映射
简单的说:
就是把数据库表和实体类以及实体类的属性对应起来, 让我们可以操作实体类就实现操作数据库表.
实体类中的属性 数据库表的字段 (需要保存一致)
user user
id id
user_name user_name
mybatis的入门
1.mybatis的环境搭建
步骤
第一步: 创建maven工程并导入坐标
第二步: 创建实体类和dao的接口
第三步: 创建Mybatis的主配置文件
SqlMapConifg.xml
第四步: 创建映射配置文件
IUserDao.xml
环境搭建的注意事项
1. 创建IUserDao.xml 和 IUserDao.java时, 名称是为了和我们之前学的只是一致
在Mybatis中它把持久层的操作接口名称和映射文件也叫做: Mapper
所以: IUserDao 和 IUserMapper 是一样的
2. 在idea中创建目录的时候, 它和包是不一样的(配置文件的目录需要一级一级的创建)
包在创建时: cn.fang.dao它是三级结构
目录在创建时: cn.fang.dao是一级目录
3. mybatis的映射配置文件位置必须和dao接口的包结构一致
4. 映射配置文件的mapper标签namespace属性的取值必须是dao接口的全限定类名
5. 映射配置文件的操作配置, (select标签)id属性的取值必须是dao接口的方法名
4个一致
映射文件的文件名 和 接口的文件名 一致
映射文件的目录接口 和 接口的包路径 一致
映射文件中的namespace属性值要 和 接口的全类名 一致
映射文件中的(select)ID属性 和 接口中的方法名 一致
1个引入
核心配置文件中一定要引入映射文件
<mappers>
<package name="cn.fang.dao"/>
<!--<mapper resource="com/itheima/dao/IUserDao.xml"/>-->
<!--<mapper class="com.itheima.dao.IUserDao"/>-->
</mappers>
当我们遵从上面的几点以后, 我们在开发中就不用写dao的实现类了;
2.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>
<!-- 配置 mybatis 的环境 -->
<environments default="mysql">
<!-- 配置 mysql 的环境 -->
<environment id="mysql">
<!-- 配置事务的类型 -->
<transactionManager type="jdbc"></transactionManager>
<!-- 配置连接数据库的信息:用的是数据源(连接池) 连接数据库的信息 有了就能创建connection对象 -->
<dataSource type="pooled">
<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="78910J"/>
</dataSource>
</environment>
</environments>
<!--告知 mybatis 映射文件配置的位置,指的是每个dao独立的配置文件 作用:告诉核心配置文件使用连接(SqlSession)的文件资源路径-->
<mappers>
<mapper resource="com/itheima/dao/IUserDao.xml"></mapper>
</mappers>
</configuration>
步骤
第一步: 读取配置文件
第二步: 创建SqlSessionFactory工厂
第三步: 创建SqlSession对象
第四步: 创建Dao接口的代理对象
第五步: 执行dao中的方法
第六步: 释放资源
注意事项
不要忘记在映射配置中告知mybatis要封装的哪个实体类
配置方式: 指定实体类的全限定类名
测试代码(固定编写)
/**
*入门案例
*/
public class UserTest {
private InputStream is;
private SqlSession sqlSession;
private UserDao userDao;
@Before //用于在测试方法执行之前执行
public void init() throws Exception {
//1. 读取配置文件
is = Resources.getResourceAsStream("mybatis.xml");
//2. 创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
//3. 使用工厂生产SqlSession对象
sqlSession = factory.openSession();
//4. 使用SqlSession创建Dao接口的代理对象
userDao = sqlSession.getMapper(UserDao.class);
}
@After //用于在测试方法执行之后执行
public void destroy() throws Exception {
//提交事务
sqlSession.commit();
//6. 释放资源
sqlSession.close();
is.close();
}
}
****映射配置
<mapper namespace="cn.fang.dao.UserDao">
<!--配置查询所有-->
<select id="findAll" resultType="cn.fang.domain.User">
select * from user;
</select>
</mapper>
//resultType="cn.fang.domain.User": 表示将数据封装到什么位置, 测试时不要忘记
mybatis基于注解的入门案例
把UserDao.xml移除, 在dao接口的方法上使用@Sellect注解, 并且指定SQL语句
同事需要在SqlMapConfig.xml中的mapper配置时, 使用class属性指定dao接口的全限定类名.
基于代理 Dao 实现 CRUD 操作
增
<!--保存用户-->
<insert id="addUser" parameterType="cn.fang.domain.User">
<!--配置插入操作后,获取插入数据的id-->
<selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
select last_insert_id();
</selectKey>
insert into user (username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
</insert>
删
<!--根据id删除用户-->
<delete id="deleteUser" parameterType="int">
delete from user where id = #{uid}
</delete>
改
<!--根据id更改用户信息-->
<!--下面的属性是设置传进的参数类型-->
<update id="updateUser" parameterType="cn.fang.domain.User">
update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
</update>
查
<!-- 根据 id 查询 -->
<select id="findById" resultType="com.itheima.domain.User" parameterType="int"> select * from user where id = #{uid}
</select>
细节:
resultType 属性: 用于指定结果集的类型。
parameterType 属性: 用于指定传入参数的类型。
实体类属性和数据库列名不一致
resultMap 标签可以建立查询的列名和实体类的属性名称不一致时建立对应关系。从而实现封装。
<!--
建立 User 实体和数据库表的对应关系
type 属性:指定实体类的全限定类名
id 属性:给定一个唯一标识,是给查询 select 标签引用用的。
-->
<resultMap id="userMap" type="cn.fang.domain.User">
<!-- 主键字段的对应 -->
<id property="id" column="id"></id>
<!--
id 标签:用于指定主键字段
result 标签:用于指定非主键字段
column 属性:用于指定数据库列名
property 属性:用于指定实体类属性名称
-->
<!--非主键字段的对应-->
<result property="username" column="username"></result>
<result property="birthday" column="birthday"></result>
<result property="sex" column="sex"></result>
<result property="address" column="address"></result>
</resultMap>
mybatis中的连接池
mybatis连接池的配置方式:
1. UNPOOLED 不使用连接池的数据源
2. POOLED 使用连接池的数据源
3. JNDI 使用JNDI实现的数据源
相应地,MyBatis 内部分别定义了实现了 java.sql.DataSource 接口的 UnpooledDataSource, PooledDataSource 类来表示 UNPOOLED、POOLED 类型的数据源。
在sqlMapConfig.xml中配置如下
<!-- 配置数据源(连接池) -->
<dataSource type="POOLED">
<!-- 配置连接数据库的4个基本信息 -->
<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>
MyBatis 在初始化时,根据<dataSource>的 type 属性来创建相应类型的的数据源 DataSource,即: type="POOLED": MyBatis 会创建 PooledDataSource 实例
type="UNPOOLED": MyBatis 会创建 UnpooledDataSource 实例
type="JNDI": MyBatis 会从 JNDI 服务上查找 DataSource 实例,然后返回使用
mybatis中的事务
mybatis中默认是开启也是,也就是增删改之后需要手动session.commit()方法手动提交事务;但是我们也可以设 置自动提交,在增删改完成之后不需要手动调用session.commit()提交事务。只需要在session = factory.openSession(true);参数true表示自动提交。
mybati中的动态sql语句
if标签&where标签
where标签–>代替了 where 1=1 and
<!--根据添加查询, 运用if和where标签-->
<select id="tiaoJian01" resultMap="userMapper" parameterType="cn.fang.domain.User">
select * from user
<where>
<if test=" username != null">
username = #{username}
</if>
</where>
</select>
foreach标签
foreach元素的属性主要有 item,index,collection,open,separator,close。
item: 循环体中的具体对象。支持属性的点路径访问,如 item.age,item.info.details。具体说明:在 list 和数 组中是其中的对象,在 map 中是 value,该参数为必选。(它是每一个元素进行迭代时的别名)
index:在 list 和数组中,index 是元素的序号;在 map 中,index 是元素的 key。
open :表示该语句以什么开始
separator :表示在每次进行迭代之间以什么符号作为分隔符
close :表示以什么结束
_parameter :不只是方法传递过来的参数可以被用来判断,取值
_parameter:代表整个参数
单个参数:_parameter就是这个参数
多个参数: 1.参数会被封装为一个map:_parameter就是代表这个map 2._parameter 可以get(0)得到第一个参数。
在使用foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须指定的,但是在不同情况 下,该 属性的值是不一样的,主要有一下3种情况:
1.如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
2.如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
3.如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map
遍历list集合
<select id="findByNameTiaoJian02" resultMap="userMapper" parameterType="cn.fang.domain.QueryVO">
select * from user
<where>
<if test="list != null and list.size > 0">
<!--
collection: 从集合中得到的所有id
open: 代表语句的开始部分
close:代表结束部分
item:代表遍历集合的每个元素,生成的变量名
sperator:代表分隔符
-->
<foreach collection="list" open="id in (" close=")" item="uid" separator=",">
#{uid}
</foreach>
</if>
</where>
</select>
遍历map集合
<select id="findByMap" parameterType="map" resultType="cn.itcast.mybatis.pojo.Product"> select * from user
<where>
<foreach collection="_parameter" index="key" item="value" separator="and"> <if test="value !=null">
${key} = #{value}
</if>
</foreach>
</where>
</select> <!-- select * from user where 条件1 and 条件2 -->
mybatis中的多表查询
一对一
实现步骤
1.创建Account实体类以及IAccountDao接口
2.创建IAccountDao.xml映射问题
3.创建AccountDaoTest测试类进行测试
实现类和就扣
public class Account implements Serializable {
private Integer id;
private Integer uid;
private Double money;
//封装对应的user对象
private User user;
get和set自动生成
}
public interface AccountDao {
/**
* 查询所有账号信息同时查询对应用户信息
* @return
*/
List<Account> findAll(); }
映射
<mapper namespace="com.itheima.dao.IAccountDao">
<!--配置account的resultMap映射-->
<resultMap id="accountUserMap" type="account">
<!--配置主键 有别名就使用别名-->
<id column="aid" property="id"/>
<!--配置其他字段-->
<result column="uid" property="uid"/>
<result column="money" property="money"/>
<!--配置user对象的映射
property="user"表示account上的user属性
javaType="user"表示要封装的数据类型,必须要写
-->
<association property="user" javaType="user" column="uid">
<!--配置主键-->
<id column="id" property="id"/>
<!--配置其他字段-->
<result column="username" property="username"/>
<result column="birthday" property="birthday"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
</association>
</resultMap>
<!--查询所有账号信息同时查询对应用户信息-->
<select id="findAll" resultMap="accountUserMap">
/*注意:当多表查询结果有相同字段名时,我们需要取别名区分*/
SELECT u.*,a.id aid,a.UID,a.MONEY FROM user u,account a where u.id=a.UID;
</select>
</mapper>
一对多
实现步骤
1.在user中添加List<Account> accounts属性,在IUserDao中添加新的查询方法
2.在IUserDao.xml中重新配置查询语句
3.在AccountDaoTest测试类进行测试
与一对一一样, 区别在于下面的配置, 一对多用的是collection标签
<!-- 定义User的resultMap-->
<resultMap id="userAccountMap" type="com.itheima.domain.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对象中accounts集合的映射 -->
<collection property="accounts" ofType="com.itheima.domain.Account">
<id column="aid" property="id"></id>
<result column="uid" property="uid"></result>
<result column="money" property="money"></result>
</collection>
</resultMap>
多对多(相当于两个一对多)
实现 Role 到 User 的多对多
实现步骤
1.创建实体类Role以及IRoleDao接口
2.创建IRoleDao.xml映射文件,并配置查询信息
3.创建RoleDaoTest测试类,并测试查询方法
在Role类中定义一个List集合的成员变量
public class Role implements Serializable {
private Integer roleId;
private String roleName;
private String roleDesc;
//多对多的关系映射:一个角色可以赋予多个用户
private List<User> users;
get和set方法要生成
}
人物的映射
<?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.itheima.dao.IRoleDao">
<!--定义role表的ResultMap-->
<resultMap id="roleMap" type="role">
<id property="roleId" column="rid"></id>
<result property="roleName" column="role_name"></result>
<result property="roleDesc" column="role_desc"></result>
<collection property="users" ofType="user">
<id column="id" property="id"></id>
<result column="username" property="username"></result>
<result column="address" property="address"></result>
<result column="sex" property="sex"></result>
<result column="birthday" property="birthday"></result>
</collection>
</resultMap>
<!--查询所有-->
<select id="findAll" resultMap="roleMap">
select r.id rid, r.role_name, r.role_desc, u.*
from role r
left outer join user_role ur on r.id = ur.rid
left outer join user u on u.id = ur.uid;
</select>
</mapper>
实现 User 到 Role 的多对多
实现步骤
1.在实体类User中添加List<Role> roles属性,并在IUserDao中添加新的查询方法
2.在IUserDao.xml中重新配置查询语句
3.在UserDaoTest测试类进行测试
在User类中定义一个List集合的成员变量
public class User implements Serializable {
private Integer id;
private String username;
private String address;
private String sex;
private Date birthday;
//多对多的关系映射:一个用户可以具备多个角色
private List<Role> roles;
get和set方法要生成
}
用户的映射
<?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.itheima.dao.IUserDao">
<!-- 定义User的resultMap-->
<resultMap id="userMap" 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>
<!-- 配置角色集合的映射 -->
<collection property="roles" ofType="role">
<id property="roleId" column="rid"></id>
<result property="roleName" column="role_name"></result>
<result property="roleDesc" column="role_desc"></result>
</collection>
</resultMap>
<!-- 查询所有 -->
<select id="findAll" resultMap="userMap">
select u.*,r.id as rid,r.role_name,r.role_desc from user u
left outer join user_role ur on u.id = ur.uid
left outer join role r on r.id = ur.rid
</select>
</mapper>
mybatis中的延迟加载(懒加载)
概念
1. 立即加载: 只要一调用方法,不管用不用的到数据都立马去关联查询
2. 延迟加载: 只有在用到数据时才去关联查询,不用就不关联查询. 按需求加载
好处:先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能;延迟加载也叫按需加载或懒加载
一般我们查询一个对象时, 跟它关联的数据比较多, 就采用懒加载, 否则使用立即加载
在主配置文件中开启全局延迟加载
延迟默认是不开启的
<settings>
<!--当开启时,所有关联对象都会延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--false表示按需加载-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
开启延迟加载之后, 会根据你要所需要查询的信息输出对应的sql语句,然后根据sql语句查询信息
没有开启时, 会首先把所有的sql语句全部输出, 然后加载所有的信息
可以根据**fetchType=""**设置延迟
其中有两个属性:
eager 表示没有开启延迟
lazy 标识开启延迟
一对一实现延迟加载
映射配置文件中配置延迟加载
<!--配置accountMap结果集映射信息-->
<resultMap id="accountMap" type="account">
<id column="id" property="id"/>
<result column="uid" property="uid"/>
<result column="money" property="money"/>
<!--配置关联查询的user信息,column="uid"必须要有,表示传递给关联表中的参数
一对一的关系映射:配置封装user的内容
select属性指定的内容:查询用户的唯一标识:
column属性指定的内容:用户根据(数据库的)id查询时,所需要的参数的值
-->
<association property="user" javaType="user" column="uid" select="com.itheima.dao.IUserDao.findById"/>
</resultMap>
<!--延迟加载:查询所有账号信息同时查询对应用户信息-->
<select id="findAll" resultMap="accountMap">
select * FROM account
</select>
在关联表的dao中添加findById方法并在IUserDao.xml配置
<!-- 根据id查询用户 -->
<select id="findById" parameterType="INT" resultType="com.itheima.domain.User">
select * from user where id = #{uid}
</select>
一对多实现延迟加载
映射配置文件中配置延迟加载
<!--配置userMap结果集映射信息-->
<resultMap id="userMap" type="user">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="birthday" property="birthday"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
<!-- 配置user对象中accounts集合的映射 -->
<collection property="accounts" ofType="com.itheima.domain.Account" select="com.itheima.dao.IAccountDao.findAccountById" column="id"/>
</resultMap>
<!--查询所有操作-->
<select id="findAll" resultMap="userMap">
SELECT * FROM USER ;
</select>
在关联表的dao中添加findAccountById方法并在IAccountDao.xml配置
<!-- 根据用户id查询账户列表 -->
<select id="findAccountByUid" resultType="com.itheima.domain.Account">
select * from account where uid = #{uid}
</select>
mybatis中的缓存
概念
存在内存中的临时数据就是缓存
一级缓存
概念: 默认存在
它指的是Mybatis中SqlSession对象的缓存。当我们执行查询之后,查询的结果会同时存入到SqlSession为我们提供一块区域中。该区域的结构是一个Map。当我们再次查询同样的数据,mybatis会先去sqlsession中查询是否有,有的话直接拿出来用。当SqlSession对象消失时(close方法被调用),mybatis的一级缓存也就消失了。
作用的范围
一级缓存是SqlSession级别的缓存。在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构用于存储缓存数据。不同的sqlSession之间的缓存数据区域是互相不影响的。也就是他只能作用在同一个sqlSession中,不同的sqlSession中的缓存是互相不能读取的。
代码
@Test
public void testFirstLeverCache(){
User user1 = userDao.findById(43);
System.out.println("user1 = " + user1);
//测试一下关闭session
/*session.close();
session=factory.openSession(true);
userDao=session.getMapper(IUserDao.class);*/
//也可以清除缓存
//session.clearCache();
//再次执行相同的查询
User user2 = userDao.findById(43);
System.out.println("user2 = " + user2);
//判断user1和user2是不是同一个对象
System.out.println("user1==user2 : " + (user1==user2));
}
清除一级缓存
如果是同一个session对象,那么第二次查询的user对象和第一次查询的user对象是同一个user对象,最后打印的结果是true,通过控制台日志可以看出只执行了一次查询;当中间关闭了session或者调用clearCache方法清除缓存之后,那两个user对象就不是同一个对象了,控制台查看日志也会发现执行了两次查询。
二级缓存
概念:
它指的是Mybatis中SqlSessionFactory对象的缓存。由同一个SqlSessionFactory对象创建的SqlSession共享其缓存。
二级缓存的使用步骤:
第一步:让Mybatis框架支持二级缓存(在SqlMapConfig.xml中配置)
第二步:让当前的映射文件支持二级缓存(在IUserDao.xml中配置)
第三步:让当前的操作支持二级缓存(在select标签中配置)
作用范围
二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。
UserMapper有一个二级缓存区域(按namespace分),其它mapper也有自己的二级缓存区域(按namespace分)。每一个namespace的mapper都有一个二级缓存区域,两个mapper的namespace如果相同,这两个mapper执行sql查询到数据将存在相同的二级缓存区域中。
开启二级缓存
1. 在主配置文件中设置
<settings>
<!--开启二级缓存-->
<setting name="cacheEnabled" value="true"/>
</settings>
2. 在需要开启二级缓存的mapper.xml中加入caceh标签
<cache/>
3. 让使用二级缓存的POJO类实现Serializable接口
public class User implements Serializable {
private Integer id;
private String username;
private String address;
}
注意:SqlMapConfig.xml中的 中的 cacheEnabled默认值就是true,可以不用配置。
当我们在使用二级缓存时,所缓存的类一定要实现 java.io.Serializable 接口,这种就可以使用序列化 方式来保存对象
代码
@Test
public void testSecondLeverCache(){
//1.获取第一个sqlSession对象并查询user
SqlSession session1 = factory.openSession(true);
IUserDao userDao1 = session1.getMapper(IUserDao.class);
User user1 = userDao1.findById(43);
System.out.println("user1 = " + user1);
//关闭session1
session1.close();
//2.获取第二个sqlSession对象并查询user
SqlSession session2 = factory.openSession(true);
IUserDao userDao2 = session2.getMapper(IUserDao.class);
User user2 = userDao2.findById(43);
System.out.println("user2 = " + user2);
session2.close();
//判断user1和user2是不是同一个对象
System.out.println("user1==user2 : " + (user1==user2));
}
结果和注意事项
两个对象虽然不是同一个对象,但是通过控制台发现只执行了一次查询
注意:一定要关闭之前的sqlSession对象
禁用二级缓存
对于变化频率较高的sql,需要禁用二级缓存:在statement中设置useCache=false可以禁用当前select语句的二级缓存,即每次查询都会发出sql去查询,默认情况是true,即该sql使用二级缓存。
例如:<select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">
刷新缓存
1、如果sqlsession操作commit操作,对二级缓存进行刷新(全局清空)。
2、设置statement的flushCache是否刷新缓存,默认值是true。
例如:<select id="findOrderListResultMap" resultMap="ordersUserMap" flushCache="true">
mybatis中的注解开发
主配置文件
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--引入外部jdbc配置信息 jdbcConfig.properties文件-->
<properties resource="jdbcConfig.properties"/>
<!--配置domain包中javabean使用的别名-->
<typeAliases>
<package name="com.itheima.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>
<package name="com.itheima.dao"/>
</mappers>
</configuration>
需要配置文件 jdbcConfig.properties
单表的简单CRUD
查询
* @Select("select * from user where username like #{username} ")
修改
* @Update("update user set username=#{username},sex=#{sex},birthday=#{birthday},address=#{address} where id=#{id}")
添加
* @Insert("insert into user(username,address,sex,birthday)values(#{username},#{address},#{sex},#{birthday})")
删除
* @Delete("delete from user where id=#{id} ")
代码
/**
* 查询所有操作
* @return
*/
@Select("select * from user")
List<User> findAll();
/**
* 保存用户
* @param user
* @return 影响数据库记录的行数
*/
@Insert("insert into user values(null,#{username},#{birthday},#{sex},#{address})")
//配置SelectKey将新添加用户的id封装到user中
@SelectKey(keyColumn = "id",keyProperty = "id",resultType =int.class,before = false, statement = "select last_insert_id()")
int saveUser(User user);
/**
* 更新用户
* @param user
* @return 影响数据库记录的行数
*/
@Update("update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}")
int updateUser(User user);
/**
* 根据 id 删除用户
* @param id
* @return 影响数据库记录的行数
*/
@Delete("delete from user where id=#{id}")
int deleteUser(int id);
/**
* 根据 id 查询
* @param id
* @return
*/
@Select("select * from user where id=#{id}")
User findById(Integer id);
/**
* 根据名称模糊查询
* @param username
* @return
*/
@Select("select * from user where username LIKE #{username};")
List<User> findByName(String username);
/**
* 查询总记录条数
* @return 总记录条数
*/
@Select("select count(*) from user;")
int findTotal();
/**
* 根据 QueryVo 中的条件查询用户
* @param vo
* @return
*/
@Select(" select * from user where username like #{user.username}")
List<User> findByVo(QueryVo vo);
mybatis注解开发实例类属性与表列名不一致
/**
* 使用别名,查询所有用户信息;
* @return 所有用户信息
*/
@Select("select * from user")
//id="uMap"表示结果集映射的id,将来可以给其他@ResultMap复用
@Results(id="uMap",value = {
//id=true表示是主键,默认值是false
@Result(id=true,column = "id",property = "userId"),
@Result(id=false,column = "username",property = "userName"),
@Result(column = "birthday",property = "userBirthday"),
@Result(column = "sex",property = "userSex"),
@Result(column = "address",property = "userAddress")
})
List<U> findAllU();
/**
* 使用别名,模糊查询用户信息;
* @return 所有用户信息
*/
@ResultMap("userMap")
@Select("select * from tab_user where username=#{username}")
public List<User> findByUsername(String username);
多表查询
一对一的映射配置
/**
* 立即查询:查询账户信息的同时查询其用户信息
* @return
*/
@Select("select * from account")
@Results(id="accountMap",value = {
@Result(id=true,column = "id",property = "id"),
@Result(column = "uid",property = "uid"),
@Result(column = "money",property = "money"),
@Result(property = "user",column = "uid",
one=@One(select="com.itheima.dao.IUserDao.findById",fetchType= FetchType.EAGER))//立即查询
})
public List<Account> findAll()
一对多的映射配置
/**
* 延时查询:查询用户信息的同时查询其所有账户信息
* @return
*/
@Select("select * from user")
@Results(id = "userMap", value = {
@Result(id = true, column = "id", property = "userId"),
@Result(column = "username", property = "userName"),
@Result(column = "address", property = "userAddress"),
@Result(column = "sex", property = "userSex"),
@Result(column = "birthday", property = "userBirthday"),
@Result(property = "accounts", column = "id",
many = @Many(select = "com.itheima.dao.IAccountDao.findAccountByUid", fetchType = FetchType.LAZY))//延迟查询
})
public List<User> findAll();
缓存配置
- 注解开启二级缓存
@CacheNamespace(blocking = true)
public interface IUserDao
- 在SqlMapConfig.xml中需开启缓存功能,默认开启
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
主配置文件范例
在resources目录下面导入jdbcConfig.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>
<!--读取jdbcConfig.properties配置文件-->
<properties resource="jdbcConfig.properties"/>
<!--设置开启延迟 可以不用, 看情况而定-->
<settings>
<!--当开启时,所有关联对象都会延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--false表示按需加载-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
<!--使用typeAliases配置别名,它只能配置domain中类的别名 -->
<typeAliases>
<package name="cn.fang.domain"/>
</typeAliases>
<!--配置环境-->
<environments default="mysql">
<!-- 配置mysql的环境-->
<environment id="mysql">
<!-- 配置事务的类型-->
<transactionManager type="JDBC"/>
<!-- 配置数据源(连接池) -->
<dataSource type="POOLED">
<!--配置连接数据库的4个基本信息-->
<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>
<!--指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件-->
<mappers>
<package name="cn.fang.dao"/>
</mappers>
</configuration>