2、常用配置介绍使用MyBatis是⼀款优秀的基于ORM的半⾃动轻量级持久层框架,它⽀持定制化SQL、存储过程以及⾼级映射。MyBatis避免了⼏乎所有的JDBC代码和⼿动设置参数以及获取结果集。MyBatis可以使⽤简单的XML或注解来配置和映射原⽣类型、接⼝和Java的POJO (Plain Old Java Objects,普通⽼式Java对 象)为数据库中的记录。
官网地址 : 官网地址
为了方面后续学习使用,先搭建一个maven工程,引入mybatis 依赖,另外因为要连接数据库,还需要引入jdbcdriver,为方便测试引入junit, 具体pom 配置如下:
4.0.0 com.example mybatis_quickstart 1.0-SNAPSHOT UTF-8 UTF-8 1.8 1.8 1.8 org.mybatis mybatis 3.4.5 mysql mysql-connector-java 5.1.6 junit junit 4.11
搭建项目结构如下,其中jdbc.properties 存储数据库连接配置信息(可以配置在sqlmapconfig中,但因为数据库信息每个环境都不一样,常见方式是单独放在与环境相关的文件中,为此单独放在jdbc.properties),sqlmapConfig.xml 是mybatis 核心配置文件,usermapper.xml是 mybatis sql映射配置文件存储信息
文件内容如下:
sqlmapConfig.xml中
jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/de?useUnicode=true&characterEncoding=UTF-8 jdbc.username=root jdbc.password=root
usermapper.xml
select * from user insert into user(id,username) values (#{id},#{username}) update user set username=#{username} where id = #{id} delete from user where id = #{id}
User 类
package com.example.pojo;
public class User {
private Integer id;
private String username;
//省略 get set 方法
}
至此,项目核心配置搭建完成
编写测试类
import java.util.List;
public class Mybayis_test {
@Test
public void test() throws Exception{
//RESOURCE 工具类,配置文件加载,把配置文件加载到字节输入流
InputStream is= Resources.getResourceAsStream("SqlMapConfig.xml");
// 2 解析配置文件,并创建sql session工厂
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(is);
//3、 生产sqlsession
SqlSession sqlSession = sqlSessionFactory.openSession(); // 默认开启事务,但是 该事务不会自动提交,所以增删改 需要提交事务
//设置为 true 自动提交事务
//SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4 sqlsession 调用方法,查询所有 selectlist 查询一个 selectone 更新 update 删除 delete 添加 insert
List uSers=sqlSession.selectList("User.findAll");
for (User user : uSers) {
System.out.println(user);
}
sqlSession.close();
}
}
如上面代码所示,通过mybatis实现单表的增删改查可以通过不同的标签,再通过mapper文件的namespace 以及sql id,指定到具体的一个sql ,mybatis帮我们实现参数转换和结果集封装。
有几个注意事项:
1、mappee.xml 中的paramtertype 指的是参数类型,retulttype 是返回值类型,两个都要写类的全限定名(别名例外,typealias )
2、sql 语句中,使用#{实体属性名}引用实体中的属性值
3、增删改涉及数据库变化,要使用sqlsession 提交事务,即sqlsession.commit()
4、通过sqlsession 提供的相关api完成对数据库的操作
5、映射mapper文件要有通用的文件头
按照经典三层模型数据结构,在我们企业实际开发中,通常会将和数据的交互放在dao层实现
这样,我们可以调整代码如下:
新建dao 层接口
public interface IUserDao {
public List findAll() throws Exception;
}
新建实现类,实现dao层接口
public class UserDaoImpl implements IUserDao {
//传统开发方式
@Override
public List findAll() throws Exception{
//RESOURCE 工具类,配置文件加载,把配置文件加载到字节输入流
InputStream is= Resources.getResourceAsStream("SqlMapConfig.xml");
// 2 解析配置文件,并创建sql session工厂
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(is);
//3、 生产sqlsession
SqlSession sqlSession = sqlSessionFactory.openSession(); // 默认开启事务,但是 该事务不会自动提交,所以增删改 需要提交事务
//设置为 true 自动提交事务
//SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4 sqlsession 调用方法,查询所有 selectlist 查询一个 selectone 更新 update 删除 delete 添加 insert
List uSers=sqlSession.selectList("User.findAll");
sqlSession.close();
return uSers;
}
}
测试
@Test
public void testdao() throws Exception{
IUserDao userDao=new UserDaoImpl();
List all = userDao.findAll();
for (User user : all) {
System.out.println(user);
}
}
以上代码可以完成和数据库的正常交互,但是当有成百上千个交互要实现的时候,就会比较痛苦,每个sql 都要有自己的实现类,直观上看我们实现类的代码交互都类似,初始化相关解析配置信息,获取sqlsession, 获取对应的statementid,找到对应的脚本并执行,有事务的时候提交事务 为此,mybatis 提供了第二种方式:代理方式
采⽤ Mybatis 的代理开发⽅式实现 DAO 层的开发,这种⽅式是主流开发方式。
Mapper 接⼝开发⽅法只需要程序员编写Mapper 接⼝(相当于Dao 接⼝),由Mybatis 框架根据接⼝
定义创建接⼝的动态代理对象,代理对象的⽅法体同上边Dao接⼝实现类⽅法。
Mapper 接⼝开发需要遵循以下规范:
- Mapper.xml⽂件中的namespace与mapper接⼝的全限定名相同
- Mapper接⼝⽅法名和Mapper.xml中定义的每个statement的id相同
- Mapper接⼝⽅法的输⼊参数类型和mapper.xml中定义的每个sql的parameterType的类型相同
- Mapper接⼝⽅法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
我们可以先注释上面的实现类
@Test
@Test
public void testdao2() throws Exception{
InputStream is= Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = sqlSessionFactory.openSession();
IUserDao mapper = sqlSession.getMapper(IUserDao.class);
List all = mapper.findAll();
for (User user : all) {
System.out.println(user);
}
}
关于mybatis 动态sql 如if ,where ,foreach,sql 等标签的使用,可以参考上面的demo。
3、复杂映射上面提到,当我们对单表操作时,通过sql 属性,resulttype指定对应的返回结果类型,这样mybatis 会自动帮我们做封装,那么问题来了,如果是对多个表操作,那么我们如果封装结果集,这里引入resultMap
这里我们以用户和订单的关系为例:
通常在我们电商系统中,一个用户有多笔订单,每个订单对应一个用户,如果这样,那么
新建订单类
package com.example.pojo;
public class Order {
private Integer id;
private String orderTime;
private Double total;
//表明该订单属于哪个用户
private User user;
//省略 get set方法
}
订单表维护如下
DROP TABLE IF EXISTS `orders`; CREATE TABLE `orders` ( `id` int(11) NOT NULL AUTO_INCREMENT, `ordertime` varchar(255) DEFAULT NULL, `total` double DEFAULT NULL, `uid` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `uid` (`uid`), CONSTRAINT `orders_ibfk_1` FOREIGN KEY (`uid`) REFERENCES `user` (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;3.1 一对一查询结果映射
如果我们查询订单对应的用户:
select * from user u,orders o where o.uid=u.id;
public interface IOrderMapper {
//查询订单的同时,查询所属的用户 一对一
public List findOrderAndUSer();
}
3.2 一对多查询结果映射
一个人对应多个订单,为此:用户表新增订单列表集合
public class User implements Serializable {
private Integer id;
private String username;
private List orderList;
private List roleList;
// 省略 set get 方法
}
核心代码如下
3.3 多对多查询结果映射select u.*,o.id oid,o.ordertime,o.total,o.uid from user u left join orders o on u.id = o.uid
在一个系统中有用户和角色两个模块,一个用户可以担任多个角色,一个角色可以有多个用户担任,为此,用户和角色是一对一的关系。如果要查询一个用户有哪些角色,为此
用户表新增角色list
package com.example.pojo;
import com.sun.org.apache.xpath.internal.operations.Or;
import javax.persistence.*;
import java.io.Serializable;
import java.util.List;
public class User implements Serializable {
private Integer id;
private String username;
private List orderList;
private List roleList;
//省略get set方法
}
select * from user left join sys_user_role sur on user.id = sur.userid left join sys_role sr on sur.roleid = sr.id
以上可以发现,resultmap维护的就是sql 字段和 实体类的映射关系,这里要注意,因为常规开发中,我们经常列名是下划线命名,字段名是驼峰命名,为此,resultMap 在我们实际开发中实际上是一个很常用的标签。
4、注解开发近年来随着注解开发越来越流行,mybatis也可以使用注解开发,不过这个只是个趋势,笔者自己的公司 实际上还是用的mapper 配置文件比较多,当时这种方式还是值得 学习了解。
4.1 使用注解完成简单增删改查因为注解就不需要配置文件了,为此,调整mybatis sqlmap.xml mapper引入方式,调整后就能扫描到包下所有mapper
Iusermapper 新增注解方法
@CacheNamespace (implementation = RedisCache.class)//开启二级缓存
public interface IUserMapper {
//添加用户
@Insert("insert into user value(#{id},#{username})")
public void addUser(User user);
//更新用户
@Update("update user set username=#{username} where id=#{id}")
public void updateUser(User user);
@Select("select * from user")
public List selectUser();
@Delete("delete from user where id=#{id}")
public void deleteUser(User user);
@Select("select * from user where id =#{id}")
public User findUserById(Integer id);
}
测试类测试
@Before
public void befo() throws Exception{
InputStream is= Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
userMapper = sqlSession.getMapper(IUserMapper.class);
orderMapper=sqlSession.getMapper(IOrderMapper.class);
}
@Test
public void addUSer(){
User user=new User();
user.setId(6);
user.setUsername("testadd");
userMapper.addUser(user);
}
@Test
public void updateUSer(){
User user=new User();
user.setId(6);
user.setUsername("testudpate");
userMapper.updateUser(user);
}
@Test
public void deleteUSer(){
User user=new User();
user.setId(6);
user.setUsername("testudpate");
userMapper.deleteUser(user);
}
@Test
public void selectUSer(){
User user=new User();
user.setId(1);
user.setUsername("testudpate");
userMapper.selectUser();
}
4.2 使用注解实现复杂映射开发
实现复杂关系映射之前我们可以在映射⽂件中通过配置来实现,使⽤注解开发后,我们可以使⽤
@Results注解,@Result注解,@One注解,@Many注解组合完成复杂关系的配置
- 一对一映射开发
usermapper 新增注解查询方法
package com.example.mapper;
import com.example.pojo.Order;
import com.example.pojo.User;
import org.apache.ibatis.annotations.*;
import java.util.List;
public interface IOrderMapper {
//查询订单的同时,查询所属的用户 一对一
public List findOrderAndUSer();
@Results({
@Result(property = "id",column = "id"),
@Result(property = "orderTime",column = "orderTime"),
@Result(property = "total",column = "total"),
@Result(property = "user",column = "uid",javaType = User.class,one = @One(select = "com.example.mapper.IUserMapper.findUserById"))
})
@Select("select * from orders")
public List findOrderAndUSerbyAnnotation();
@Options(useCache = true) //使用二级缓存
@Select("select * from orders where uid = #{id}")
public List findOrderByUId(Integer id);
}
- 一对多,多对多
public interface IUserMapper {
//查询所有用户信息,同时查询所有用户所属订单信息
@Select("select * from user")
@Results({
@Result(property = "id",column = "id"),
@Result(property = "username",column = "username"),
@Result(property = "orderList",column = "id",javaType = List.class,many = @Many(
select = "com.example.mapper.IOrderMapper.findOrderByUId"
))
})
public List findUserAndOrdersByAnnotation();
//查询所有用户,同时查询所有用户关联角色信息
@Select("select * from user")
@Results({
@Result(property = "id",column = "id"),
@Result(property = "username",column = "username"),
@Result(property = "roleList",column = "id",javaType = List.class,many = @Many(
select = "com.example.mapper.IRoleMapper.findRoleByid"
))
})
public List findUserAndRoleByAnnotation();
}
public interface IRoleMapper {
@Select("select sys_role.* from sys_role,sys_user_role where sys_role.id=sys_user_role.roleid and sys_user_role.userid=#{id}")
public List findRoleByid(Integer id);
}
5、缓存原理
5.1 缓存概念
mybatis 提供了缓存机制,以便部分不会频繁更新的热点数据能更高效的查询,减少与数据库的交互次数,针对不同的数据有不同的缓存级别
5.2 一级缓存一级缓存是 会话级别的,一级缓存又叫查询缓存,因为对同一个sqlSession,查询完执行 commit操作,会将缓存中的数据清空。一级缓存底层是一个map, value 是对象地址,一级缓存默认开启
Override public5.3 二级缓存List query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { BoundSql boundSql = ms.getBoundSql(parameter); //创建缓存 CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql); return query(ms, parameter, rowBounds, resultHandler, key, boundSql); } @SuppressWarnings("unchecked") Override public List query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { ... list = resultHandler == null ? (List ) localCache.getObject(key) : null; if (list != null) { //这个主要是处理存储过程⽤的。 handleLocallyCachedOutputParameters(ms, key, parameter, boundSql); } else { list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql); } ... // queryFromDatabase ⽅法 private List queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { List list; localCache.putObject(key, EXECUTION_PLACEHOLDER); try { list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql); } finally { localCache.removeObject(key); } localCache.putObject(key, list); if (ms.getStatementType() == StatementType.CALLABLE) { localOutputParameterCache.putObject(key, parameter); } return list; } } private Map
二级缓存是namespace 级别的,多个sqlSession可以共享⼀个mapper中的⼆级缓存区域
开启二级缓存,需要在sqlmapConfig.xml中加入如下配置:
对应mapper文件中加入下面配置
针对每次查询都需要最新的数据sql,要设置成useCache=false,禁⽤⼆级缓存,直接从数据库中获取。在mapper的同⼀个namespace中,如果有其它insert、update, delete操作数据后需要刷新缓 存,如果不执⾏刷新缓存会出现脏读。设置statement配置中的flushCache="true”属性,默认情况下为true,即刷新缓存,如果改成false则不会刷新。使⽤缓存时如果⼿动修改数据库表中的查询数据会出现脏读。
mybatis除了默认实现,也对redis有个实现,pom 添加依赖
org.mybatis.caches mybatis-redis 1.0.0-beta2
resource 新增配置文件 redis.properties
host=localhost port=6379 connectionTimeout=5000 password= database=0
缓存注解调整,指定使用redis实现
@CacheNamespace (implementation = RedisCache.class)//开启二级缓存
mybatis-redis在存储数据的时候,是使⽤的hash结构,把cache的id作为这个hash
的key (cache的id在mybatis中就是mapper的namespace);这个mapper中的查询缓存数据作为 hash
的field,需要缓存的内容直接使⽤SerializeUtil存储,SerializeUtil和其他的序列化类差不多,负责 对象
的序列化和反序列化;
| 底层结构 | 默认开启 | 级别 | 存储 | 额外处理 | |
|---|---|---|---|---|---|
| 一级缓存 | hashmap | 是 | 会话级别 | 对象地址(可以用==比较) | |
| 二级缓存 | hashmap | 否 | namespace | 对象拷贝 | 存储对象实现序列号接口,sqlmapconfig.xml mapper文件要加额外配置,缓存才能生效,可以通过实现Cache 接口自定义缓存处理类(mybatis 有默认实现,也针对redis有个包) |
我们可基于MyBati s插件机制实现分⻚、分表,监控等功能。由于插件和业务⽆关,业务也⽆法感知插件的存在。因此可以⽆感植⼊插件,在⽆形中增强功能
Mybati s作为⼀个应⽤⼴泛的优秀的ORM开源框架,这个框架具有强⼤的灵活性,在四⼤组件(Executor、StatementHandler、ParameterHandler、ResultSetHandler)处提供了简单易⽤的插件扩展机制。Mybatis对持久层的操作就是借助于四⼤核⼼对象。MyBatis⽀持⽤插件对四⼤核⼼对象进⾏拦截,对mybatis来说插件就是拦截器,⽤来增强核⼼对象的功能,增强功能本质上是借助于底层的 动
态代理实现的,换句话说,MyBatis中的四⼤对象都是代理对象
MyBatis所允许拦截的⽅法如下:
执⾏器Executor (update、query、commit、rollback等⽅法);
SQL语法构建器StatementHandler (prepare、parameterize、batch、updates query等⽅ 法);
参数处理器ParameterHandler (getParameterObject、setParameters⽅法);
结果集处理器ResultSetHandler (handleResultSets、handleOutputParameters等⽅法);
在四⼤对象创建的时候
1、每个创建出来的对象不是直接返回的,⽽是interceptorChain.pluginAll(parameterHandler);
2、获取到所有的Interceptor (拦截器)(插件需要实现的接⼝);调⽤ interceptor.plugin(target);返 回 target 包装后的对象
3、插件机制,我们可以使⽤插件为⽬标对象创建⼀个代理对象;AOP (⾯向切⾯)我们的插件可 以
为四⼤对象创建出代理对象,代理对象就可以拦截到四⼤对象的每⼀个执⾏;
public ParameterHandler newParameterHandler(MappedStatement mappedStatement,
Object object, BoundSql sql, InterceptorChain interceptorChain) {
ParameterHandler parameterHandler =
mappedStatement.getLang().createParameterHandler(mappedStatement, object, sql);
parameterHandler = (ParameterHandler)
interceptorChain.pluginAll(parameterHandler);
return parameterHandler;
}
public Object pluginAll(Object target) {
for (Interceptor interceptor : interceptors) {
target = interceptor.plugin(target);
}
return target;
}
interceptorChain保存了所有的拦截器(interceptors),是mybatis初始化的时候创建的。调⽤拦截器链中的拦截器依次的对⽬标进⾏拦截或增强。interceptor.plugin(target)中的target就可以理解为mybatis中的四⼤对象。返回的target是被重重代理后的对象,如果我们想要拦截StatementHandler的prepare⽅法,那么可以这样定义插件:
package com.example.plugin;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.*;
import java.sql.Connection;
import java.util.Properties;
@Intercepts({//注意看这个⼤花括号,也就这说这⾥可以定义多个@Signature对多个地⽅拦截,都⽤
这个拦截器
@Signature(type = StatementHandler.class,//这是指拦截哪个接⼝
method = "prepare",//接⼝内的哪个⽅法名
args = {Connection.class,Integer.class})//这是拦截的⽅法的⼊参,按
顺序写到这,不要多也不要少,如果⽅法重载,可是要通过⽅法名和⼊参来确定唯⼀的
})
public class MyPlugin implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
System.out.println("对方法进行了增强");
return invocation.proceed(); //原方法执行
}
@Override
public Object plugin(Object o) {
Object wrap = Plugin.wrap(o, this);
return wrap;
}
@Override
public void setProperties(Properties properties) {
System.out.println("获取到的配置文件到的参数"+properties);
}
}
在sqlmapConfig.xml 中配置插件
这样MyBatis在启动时可以加载插件,并保存插件实例到相关对象(InterceptorChain,拦截器链) 中。
待准备⼯作做完后,MyBatis处于就绪状态。我们在执⾏SQL时,需要先通过DefaultSqlSessionFactory
创建 SqlSession。StatementHandler实例会在创建 SqlSession 的过程中被创建, StatementHandler实例创建完毕后,MyBatis会通过JDK动态代理为实例⽣成代理类。这样,插件逻辑即可在StatementHandler相关⽅法被调⽤前执⾏。
Mybatis 插件接⼝-Interceptor
- Intercept⽅法,插件的核⼼⽅法
- plugin⽅法,⽣成target的代理对象
- setProperties⽅法,传递插件所需参数
示例代码如上
public class Plugin implements InvocationHandler {
private final Object target;
private final Interceptor interceptor;
private final Map, Set> signatureMap;
public static Object wrap(Object target, Interceptor interceptor) {
Map, Set> signatureMap = getSignatureMap(interceptor);
Class> type = target.getClass();
Class>[] interfaces = getAllInterfaces(type, signatureMap);
return interfaces.length > 0 ? Proxy.newProxyInstance(type.getClassLoader(), interfaces, new Plugin(target, interceptor, signatureMap)) : target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
Set methods = (Set)this.signatureMap.get(method.getDeclaringClass());
return methods != null && methods.contains(method) ? this.interceptor.intercept(new Invocation(this.target, method, args)) : method.invoke(this.target, args);
} catch (Exception var5) {
throw ExceptionUtil.unwrapThrowable(var5);
}
}
从mybatis 源码可以看到,Plugin实现了invocationHandler接口,通过warp 接口返回代理对象,在我们调用目标对象的invoke 方法时,会判断方法有没有被代理,如果被代理,会调用对应拦截器的intercept方法,否则调用原方法
6.3 常用插件 6.3.1 pagehelper插件MyBati s可以使⽤第三⽅的插件来对功能进⾏扩展,分⻚助⼿PageHelper是将分⻚的复杂操作进⾏封
装,使⽤简单的⽅式即可获得分⻚的相关数据
开发步骤:
- 导⼊通⽤PageHelper的坐标
- 在mybatis核⼼配置⽂件中配置PageHelper插件
- 测试分⻚数据获取
1、 导入坐标
com.github.pagehelper pagehelper 3.7.5 com.github.jsqlparser jsqlparser 0.9.1
2、配置pagehelper插件
*
@Test
public void pageHelperTest(){
PageHelper.startPage(1,1);
List users = userMapper.selectUser();
for (User user : users) {
System.out.println(user);
}
PageInfo pageInfo=new PageInfo<>(users);
System.out.println("总条数"+pageInfo.getTotal());
System.out.println("总页数"+pageInfo.getPages());
System.out.println("当前页"+pageInfo.getPageNum());
System.out.println("每页显示条数"+pageInfo.getPageSize());
}
6.3.2 通用mapper 插件
通⽤Mapper就是为了解决单表增删改查,基于Mybatis的插件机制。开发⼈员不需要编写SQL,不需要
在DAO中增加⽅法,只要写好实体类,就能⽀持相应的增删改查⽅法
1、导入坐标
tk.mybatis mapper 3.1.2
2、配置插件
3、实体类设置主键
@Table(name = "user")
public class User implements Serializable {
//public long serialVersionUID =1;
@Id //对应主键 id
@GeneratedValue(strategy = GenerationType.IDENTITY) //设置主键生成策略
private Integer id;
@Column // 列名和实体类名字 不一样时候,使用
private String username;
}
这里演示个别框架封装的方法,其他方法类似
@Test
public void mappperTest() throws Exception{
InputStream is= Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user=new User();
user.setId(1);
//(1)mapper基础接⼝
//select 接⼝
User user1 = userMapper.selectOne(user); //根据实体中的属性进⾏查询,只能有—个返回值
List users = userMapper.select(null); //查询全部结果
userMapper.selectByPrimaryKey(1); //根据主键字段进⾏查询,⽅法参数必须包含完整的主键属性,查询条件使⽤等号
userMapper.selectCount(user); //根据实体中的属性查询总数,查询条件使⽤等号
// insert 接⼝
int insert = userMapper.insert(user); //保存⼀个实体,null值也会保存,不会使⽤数据库默认值
int i = userMapper.insertSelective(user); //保存实体,null的属性不会保存,会使⽤数据库默认值
// update 接⼝
int i1 = userMapper.updateByPrimaryKey(user);//根据主键更新实体全部字段,null值会被更新
// delete 接⼝
int delete = userMapper.delete(user); //根据实体属性作为条件进⾏删除,查询条件 使⽤等号
userMapper.deleteByPrimaryKey(1); //根据主键字段进⾏删除,⽅法参数必须包含完整的主键属性
//(2)example⽅法
Example example=new Example(User.class);
example.createCriteria().andEqualTo("id",1);
List users = userMapper.selectByExample(example);
for (User user1 : users) {
System.out.println(user1);
}
}



