Mybatis
mybatis为持久层(Dao层)的使用框架
通过xml或注解的方式将statement配置起来
将java对象和statement中的sql参数进行映射生成最终执行的sql语句
一、原始jdbc
1.1、原始jdbc查询操作
-
查询:
//注册驱动 Class.forName("com.mysql.jsbc.Driver"); //获得连接 Connection conn = DriverManager.getConnection("jdbc:mysql:///test","root","root"); //获得statement PreparedStatement sta = conn.prepareStatement("select * from user"); //执行查询 ResultSet rs = sta.executeQuery(); //遍历结果 while(rs.next()){ //数据操作 } //释放资源 rs.close(); sta.cloae(); conn.close();
-
插入
//模拟实体对象 User user = new User(); user.setId("1"); user.setName("xxx"); ---------------------------------------------------------------- ---------------------------------------------------------------- //注册驱动 Class.forName("com.mysql.jsbc.Driver"); //获得连接 Connection conn = DriverManager.getConnection("jdbc:mysql:///test","root","root"); //获得statement PreparedStatement sta = conn.prepareStatement("insert into user (id,name) values (?,?)"); //设置占位符参数 sta.setString(1,user,getId()); sta.setString(2,user.getName()); //插入操作 int num = sta.executeUpdate(); //释放资源 sta.cloae(); conn.close();
1.2、原始jdbc的额问题
- 数据库连接创建、释放频繁,影响系统性能
- sql语句在代码中为硬编码,不易维护
- 查询操作时,需要手动将结果集中的数据封装到实体中。插入时,需要手动设置占位符数据
1.3、解决方案
- 使用数据库连接池初始化连接资源
- 将sql语句抽取到xml文件中
- 使用反射、内省等底层奇数,自动将实体与表进行属性与字段的映射
Mybatis可实现
二、Mybatis开发步骤
-
添加Mybatis的坐标
<dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.22</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.5</version> </dependency> </dependencies>
-
创建user数据表
-
编写User实体类
public class userEntity { private String id; private String username; private String password; private String hobby; private String email; //get... //set... }
-
编写映射文件UserMapper.xml
<?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="userMapper"> <!--需要设置命名空间--> <!--删除--> <delete id="deleteUser" parameterType="com.zjj.mybatis01.Entity.userEntity"> delete from t_user where id = #{id} </delete> <!--更新--> <update id="updateUser" parameterType="com.zjj.mybatis01.Entity.userEntity"> update t_user set username = #{username} where id = #{id} </update> <!--添加--> <insert id="addUser" parameterType="com.zjj.mybatis01.Entity.userEntity"> insert into t_user values (#{id},#{username},#{password},#{hobby},#{email}) </insert> <!--查询--> <select id="selectAll" resultType="com.zjj.mybatis01.Entity.userEntity"> /*id自取;resultType为结果集封装对象*/ select * from t_user /*sql语句*/ </select> </mapper>
-
编写核心文件SqlMapConfig,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> <environments default="environment1"> <environment id="environment1"> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/student?serverTimezone=UTC&useSSL=false"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <!--加载映射文件--> <mappers> <mapper resource="com\zjj\mybatis01\Mapper\UserMapper.xml"/> </mapprs> </configuration>
-
测试(测试用例中部分代码重复,可抽取优化,这里不做处理)
public class MybatisTest { /*删除*/ @Test public void test3() throws IOException { //模拟实体对象 userEntity userEntity = new userEntity(); userEntity.setId("12"); userEntity.setUsername("updateName"); /*获得核心配置文件*/ InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml"); /*获得session工厂*/ SqlSessionFactory SessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); /*获得会话对象*/ SqlSession sqlSession = SessionFactory.openSession(); //执行操作 sqlSession.delete("userMapper.deleteUser",userEntity); //提交事务 sqlSession.commit(); sqlSession.close(); } /*更新*/ @Test public void test2() throws IOException { //模拟实体对象 userEntity userEntity = new userEntity(); userEntity.setId("12"); userEntity.setUsername("updateName"); /*获得核心配置文件*/ InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml"); /*获得session工厂*/ SqlSessionFactory SessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); /*获得会话对象*/ SqlSession sqlSession = SessionFactory.openSession(); //执行操作 sqlSession.update("userMapper.updateUser",userEntity); //提交事务 sqlSession.commit(); sqlSession.close(); } /*添加*/ @Test public void test1() throws IOException { //模拟实体对象 userEntity userEntity = new userEntity(); userEntity.setId("88"); userEntity.setUsername("yyyy"); userEntity.setPassword("123456"); userEntity.setHobby("none"); userEntity.setEmail("none"); /*获得核心配置文件*/ InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml"); /*获得session工厂*/ SqlSessionFactory SessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); /*获得会话对象*/ SqlSession sqlSession = SessionFactory.openSession(); //执行操作 sqlSession.insert("userMapper.addUser",userEntity); //提交事务 sqlSession.commit(); sqlSession.close(); } /*查询*/ @Test public void test0() throws IOException { /*获得核心配置文件*/ InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml"); /*获得session工厂*/ SqlSessionFactory SessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); /*获得会话对象*/ SqlSession sqlSession = SessionFactory.openSession(); //执行操作 List<userEntity> userlist = sqlSession.selectList("userMapper.selectAll"); System.out.println(userlist); sqlSession.close(); } }
三、映射文件(UserMapper.xml)
3.1、根标签(mapper)
<mapper namespace=""></mapper>
映射文件的根标签为,标签属性“namespace”为命名空间,与下文语句的id一起组成查询标识
3.2、操作标签
- 操作变迁共有四种:select、update、delete、insert
- "id"为语句标识,与上面的命名空间组成查询标识;
- 变迁中间为具体的操作sql语句
-
查
<select id="selectAll" resultType="com.zjj.mybatis01.Entity.userEntity"> select * from t_user </select>
"resultType"为查询结果对应的实体类型
-
增
<insert id="addUser" parameterType="com.zjj.mybatis01.Entity.userEntity"> insert into t_user values (#{id},#{username},#{password},#{hobby},#{email}) </insert>
"parameterType"为需要传入参数的实体类全限定名
占位符的参数使用#{}来标识,打括号内为实体的"属性",与数据库表一一对应
-
改
<!--更新--> <update id="updateUser" parameterType="com.zjj.mybatis01.Entity.userEntity"> update t_user set username = #{username} where id = #{id} </update>
与增类似
-
删
<!--删除--> <delete id="deleteUser" parameterType="com.zjj.mybatis01.Entity.userEntity"> delete from t_user where id = #{id} </delete>
与增、改类似。如果根据某一个参数删除(如id),可以将parameterType中的全限定名改为java.lang.Integer等,此类型{}内可以为如何值
3.3、动态SQL
-
if标签
*使用if条件判断来确定传入的对象属性是否为空,如果为空则不以此为条件,否则将其拼接至sql语句;以此动态设置sql语句
*where标签代表使用条件判断
*场景:当根据传入实体的属性值(不确定哪些属性具有值)来动态查询
<!--映射文件--> <select id="findByConditions" parameterType="userEntity" resultType="userEntity"> select * from t_user <where> <if test="id!=null"> and id=#{id} </if> <if test="username!=null"> and username=#{username} </if> <if test="password!=null"> and password=#{password} </if> <if test="hobby!=null"> and hobby=#{hobby} </if> <if test="email!=null"> and email=#{email} </if> </where> </select>
测试:
//测试 @Test public void test01() throws IOException { userEntity user = new userEntity(); user.setUsername("test1"); user.setEmail("none"); InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig2.xml"); SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = build.openSession(true); userMapper mapper = sqlSession.getMapper(userMapper.class); //将根据user对象的属性值来确定sql语句,此例中即为:select * from t_user where username = 'test1' and email = 'none' List<userEntity> userList = mapper.findByConditions(user); System.out.println(userList); }
-
foreach 标签
场景:当根据同台个数的属性值来查询时(where id in (1,2,3,4) )
<!--foreach使用--> <select id="findByIds" resultType="userEntity" parameterType="list"> select * from t_user <where> <foreach collection="list" open="id in (" close=")" item="id" separator=","> #{id} </foreach> </where> </select>
*collection :传入的集合/数组
*open:where 关键词之后开始时不变的部分
*close : where关键词之后结束时不变的部分
*item:变量,代表list中每一个值
*separator:分隔符
测试
@Test public void test02() throws IOException { List<Integer> list = new ArrayList<>(); list.add(1); list.add(3); list.add(5); InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig2.xml"); SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = build.openSession(true); userMapper mapper = sqlSession.getMapper(userMapper.class); List<userEntity> userList = mapper.findByIds(list); System.out.println(userList); }
-
sql语句片段抽取
*使用sql标签设置sql语句片段,并设置id;在后面可直接使用include标签应用即可
<!--sql片段抽取--> <sql id="selectUser">select * from t_user</sql> <!--if判断--> <select id="findByConditions" parameterType="userEntity" resultType="userEntity"> <include refid="selectUser"></include> </select>
四、Mybatis核心配置文件(SqlMapConfig.xml)
4.1、基础
-
根标签:
<configuration></configuration>
-
内部标签
-
properties 属性
<!--properties: 加载外部配置properties文件;内部调用使用${}--> <properties resource="jdbc.properties"></properties>
-
setting 设置
-
typeAliases 类型别名
<!--typeAliases: 配置别名--> <typeAliases> <!--type为全限定名,alias为别名;通过该配置可以在映射文件中简写--> <typeAlias type="com.zjj.mybatis01.Entity.userEntity" alias="userEntity"/> </typeAliases>
<!--映射文件中 UserMapper.xml--> <!--查询--> <select id="selectAll" resultType="userEntity"> /*resultType只需要写别名即可*/ select * from t_user </select>
在Mybatis中,一默认为String、int等数据类取别名,可直接使用
-
typeHandlers 类型处理器
-
objectFactory 对象工厂
-
plugins 插件
-
environments 环境
- environment 环境变量
- transactionManager 事务管理器
- 事务管理器有两种类型(type 属性)
- JDBC :直接使用JDBC的提交和回滚设置,依赖于数据源的连接来管理事务
- MANAGED
- 事务管理器有两种类型(type 属性)
- dataSouce 数据源
- 数据源有三种类型 (type 属性)
- UNPOOLED:该数据源的实现只是每次请求时打开或关闭连接
- POOLED:使用数据源方式
- JNDI
- 数据源有三种类型 (type 属性)
- transactionManager 事务管理器
<!--environments --> <environments default="environment1"> <environment id="environment1"> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/student?serverTimezone=UTC&useSSL=false"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments>
- environment 环境变量
-
databaseIdProvider 数据库厂商标识
-
mappers 映射器
<!--mappers :加载映射文件--> <mappers> <mapper resource="com\zjj\mybatis01\Mapper\UserMapper.xml"/> <!--相对路径来加载意映射文件--> </mappers>
-
4.2、深入
-
typeHandlers标签
该标签可以重写或自定义类型处理器
实现步骤:
-
定义转换类型继承类BaseTypeHandler
-
覆盖4个为实现的方法,其中setNonNullParameter为将java数据类型转换为数据库数据类型;getNullableResult为将数据库数据类型转换为Java数据类型
public class typeHandler extends BaseTypeHandler<Date> { //将java数据类型转换为数据库数据类型 @Override public void setNonNullParameter(PreparedStatement ps, int i, Date parameter, JdbcType jdbcType) throws SQLException { long time = parameter.getTime(); ps.setLong(i,time); } //将数据库类型转换为java数据类型 @Override public Date getNullableResult(ResultSet rs, String columnName) throws SQLException { long aLong = rs.getLong(columnName); Date date = new Date(aLong); System.out.println("----------------"+columnName+"----------------"); return date; } //将数据库类型转换为java数据类型 @Override public Date getNullableResult(ResultSet rs, int columnIndex) throws SQLException { long aLong = rs.getLong(columnIndex); Date date = new Date(aLong); System.out.println("----------------"+columnIndex+"----------------"); return date; } //将数据库类型转换为java数据类型 @Override public Date getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { long aLong = cs.getLong(columnIndex); Date date = new Date(aLong); System.out.println("----------------"+columnIndex+"----------------"); return date; } }
-
在mybatis核心配置文件中进行注册
可使用resultMap代替resultType,好处在于resultMap可以使数据库字段名称与实体类属性名称不一致
<mapper namespace="com.zjj.mybatis03.Usermapper"> <!-- <resultMap id="resMao" type="userEntity"> <id column="id" property="id"/> <result column="username" property="username"/> <result column="password" property="password"/> <result column="hobby" property="hobby"/> <result column="email" property="email"/> <result column="date" property="lodate"/> </resultMap>--> <!--可使用resultMap代替resultType,好处在于resultMap可以使数据库字段名称与实体类属性名称不一致--> <insert id="insertUser" parameterType="userEntity"> insert into t_user values (#{id},#{username},#{password},#{hobby},#{email},#{date}) </insert> <select id="selectUserById" parameterType="int" resultType="userEntity"> select * from t_user where id = #{id} </select> </mapper>
-
测试转换是否正常
public class typeHandlerTest { //测试查 @Test public void test02() throws IOException { InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig3.xml"); SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = build.openSession(); Usermapper mapper = sqlSession.getMapper(Usermapper.class); userEntity userEntity = mapper.selectUserById(8); System.out.println(userEntity.getDate()); } /**输出: ==> Preparing: select * from t_user where id = ? ==> Parameters: 8(Integer) <== Columns: id, username, password, hobby, email, date <== Row: 8, wangwu, 123456, yy, 121@, 1611994843687 ----------------date---------------- <== Total: 1 Sat Jan 30 16:20:43 CST 2021 */ //测试增 @Test public void test01() throws IOException { userEntity userEntity = new userEntity(); userEntity.setId("12"); userEntity.setUsername("wangwu"); userEntity.setPassword("123456"); userEntity.setHobby("yy"); userEntity.setEmail("121@"); userEntity.setDate(new Date()); InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig3.xml"); SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = build.openSession(true); Usermapper mapper = sqlSession.getMapper(Usermapper.class); mapper.insertUser(userEntity); } } /**输出: ==> Preparing: insert into t_user values (?,?,?,?,?,?) ==> Parameters: 13(String), wangwu(String), 123456(String), yy(String), 121@(String), 1612000600318(Long) <== Updates: 1 */
-
-
plugins标签
plugins标签可以使用第三方插件来对功能进行扩展
开发步骤(以分页为例):
-
导入通用PageHelper的坐标
<dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.1.2</version> </dependency> <dependency> <groupId>com.github.jsqlparser</groupId> <artifactId>jsqlparser</artifactId> <version>1.0</version> </dependency>
-
在mybatis核心配置文件中配置PageHelper插件
<plugins> <plugin interceptor="com.github.pagehelper.PageInterceptor"> <!--<property name="dialect" value="mysql"/>--> </plugin> </plugins>
注意,不同的pagehelper版本实现的接口不一样,所以配置不一样,具体如下:
- 4.0.0以前配置为:com.github.pagehelper.PageHelper;以后为:com.github.pagehelper.PageInterceptor
- 4.0.0以前需要写方言(“dialect”)识别数据库;4.0.0以后自动识别不需要写方言,写了反而报错
-
测试
@Test public void test03() throws IOException { InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig3.xml"); SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = build.openSession(); Usermapper mapper = sqlSession.getMapper(Usermapper.class); //配置相关参数信息;当前页+每页数据个数 PageHelper.startPage(1,3); List<userEntity> userEntities = mapper.selectAll(); System.out.println("----------"); for (userEntity u : userEntities){ System.out.println(u); } //获取pageBean中的相关信息 PageInfo<userEntity> pageInfo = new PageInfo<>(userEntities); System.out.println("当前页:" + pageInfo.getPageNum()); System.out.println("下一页:" + pageInfo.getNextPage()); System.out.println("上一页:" + pageInfo.getPageNum()); System.out.println("总页数:" + pageInfo.getPages()); System.out.println("总条数:" + pageInfo.getTotal()); System.out.println("是否为第一页:" + pageInfo.isIsFirstPage()); System.out.println("是否为最后页:" + pageInfo.isIsLastPage()); sqlSession.close(); }
-
五、Mybatis相关API
5.1、SqlSession工厂构建器(SqlSessionFactoryBuilder)
具有方法:builder(Stream s)
/*配置文件路径*/
String resource = "SqlMapConfig.xml";
/*获得核心配置文件,可有多种方式加载*/
InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
/*获得session工厂构造器*/
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
/*获得工厂*/
SqlSessionFactory factory = builder.build(resourceAsStream);
5.2、SqlSession对象构建器(SqlSessionFactory)
具有方法:
- openSession() :默认开启事务,但不会自动提交,需要手动提交
- openSession(boolean autoCommit) :传入参数为true,则自动提交
/*获得会话对象*/
SqlSession sqlSession = factory.openSession();
5.3、sqlSession对象
List<Object> objects = sqlSession.selectList(String Statement,Object o); //查询多个
Object o = sqlSession.selectOne(String Statement,Object o); //查询一个
int update = sqlSession.update(String Statement,Object o); //更新
int insert = sqlSession.insert(String Statement,Object o); //添加
int delete = sqlSession.delete(String Statement,Object o); //删除
sqlSession.commit(); //事务提交
sqlSession.close(); //关闭绘画
六、Mybatis的Dao实现
6.1、传统方法
即通过new 对象的方式手动实现
6.2、代理开发方式
Mybatis通过mapper接口的定义创建动态代理对象
规范:
- Mapper.xml文件中的namespace与mapper接口的全限定名必须一致
- Mapper接口方法名称和Mapper.xml文件中定义的每个statement的id相同
- Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql的parameterType的类型相同
- Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql的resultType的类型相同
实例:
mapper接口:
//mapper接口
public interface userDao {
//查询
public List<userEntity> selectAll();
//添加
public void addUser(userEntity u);
}
mapper.xml映射文件
<!--mapper.xml-->
<mapper namespace="com.zjj.mybatis01.Dao.userDao">
<select id="selectAll" resultType="userEntity">
select * from t_user
</select>
<insert id="addUser" parameterType="userEntity">
insert into t_user values (#{id},#{username},#{password},#{hobby},#{email})
</insert>
</mapper>
测试
@Test
public void test01() throws IOException {
userEntity user = new userEntity();
user.setId("100");
user.setUsername("test1");
user.setPassword("123456");
user.setHobby("none");
user.setEmail("none");
InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = build.openSession(true);
//获取映射
userDao mapper = sqlSession.getMapper(userDao.class);
//查
List<userEntity> userList = mapper.selectAll();
System.out.println(userList);
//增
mapper.addUser(user);
}
七、Mybatis多表查询
7.1、一对一查询
-
设置一对一的数据库(这里为订单order对用户user的关系。订单中的orders.userid对于用户中的t_user.id)
-
创建订单实体orderEntity
//主要包含了order表中的字段,以及一个user包含用户信息 private String id; private String num; private userEntity user;
-
创建OrderMapper接口
public interface OrderMapper { public List<orderEntity> selectOrder(); }
-
配置映射文件
<resultMap id="resOrder" type="orderEntity"> <id column="id" property="id"/> <!--查询获得的表中订单信息字段--> <result column="oerdernum" property="num"/> <result column="userid" property="user.id"/> <result column="username" property="user.username"/> <!--查询获得的表中用户信息字段--> <result column="password" property="user.password"/> <result column="hobby" property="user.hobby"/> <result column="email" property="user.email"/> <result column="date" property="user.date"/> </resultMap> <select id="selectOrder" resultMap="resOrder"> <!--resultMap对应上面的resultMapId--> select *,o.id oid from t_user u, orders o where o.userid = u.id </select>
使用resultMap配置来封装查询的数据;column为数据库中字段名称,property为实体类中属性名称
-
测试
7.2、一对多查询
-
设置一对多的数据库(这里为用户user对订单order的关系。用户中的t_user.id对于订单中的orders.userid,一个用户可存在多个订单)
-
创建用户实体userAndOrder
private String id; private String username; private String password; private String hobby; private String email; private Date date; //用于存放用户订单信息 private List<orderEntity> orderList;
-
创建OrderMapper接口
public List<userAndOrderEntity> selectUsreAndOrder();
-
配置映射文件
<resultMap id="userAndOrder" type="userAndOrder"> <id column="userid" property="id"/> <result column="username" property="username"/> <result column="password" property="password"/> <result column="hobby" property="hobby"/> <result column="email" property="email"/> <result column="date" property="date"/> <!--设置集合封装;property为userAndOrder中集合的名称,ofType为集合的类型--> <collection property="orderList" ofType="orderEntity"> <!--封装order数据--> <id column="oid" property="id"/> <result column="oerdernum" property="num"/> </collection> </resultMap> <select id="selectUsreAndOrder" resultMap="userAndOrder"> select *,o.id oid from t_user u, orders o where u.id = o.userid </select>
-
测试
总结:在本例中,一对一与一对多的查询结果一致,但是封装的方式不同。订单对于商品为一对一,所以order实体中只需要保存订单信息和用户信息即可,用户信息使用一个user对象来保存;而用户对于订单为一对多,所以一个user实体中除了保存用户信息,还需要保存多个订单信息,所以使用集合保存订单信息。以此,有这两个差别之后,在映射文件中的配置(resultMap)也会不同,具体可见上面配置。
7.3、多对多查询
开发思想于一对多基本一致
八、注解开发
8.1、常用注解
- @Insert:实现增
- @Update:实现更新
- @Delete:实现删除
- @Select:实现查询
- @Result:实现结果集封装
- @Results:可以与@Result一起使用,封装多多个结果
- @One:实现一对一结果集封装
- @Many:实现一对多结果集封装
8.2、基本CRUD开发步骤
-
为mapper接口中的方法添加注释(参数为value:即xml映射配置文件中的sql语句)
public interface userMapper { /*查询所有*/ @Select("select * from t_user") public List<userEntity> selectAll(); /*查询单个*/ @Select("select * from t_user where id = #{id}") public userEntity selectById(int id); /*新增*/ @Insert("insert into t_user values (#{id},#{username},#{password},#{hobby},#{email})") public void addUser(userEntity u); /*更新*/ @Update("update t_user set hobby = #{hobby} where id = #{id}") public void updateUser(userEntity u); /*删除*/ @Delete("delete from t_user where id=#{int}") public void deleteUserById(int id);
-
扫描mapper接口所在的包,以获取相关注释
<mappers> <!--扫描接口所在的包--> <package name="com.zjj.mybatis01.Mapper"/> </mappers>
-
测试
public class Mybatis { private userMapper mapper; @Before public void Before() throws IOException { InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig3.xml"); SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSession = build.openSession(true); mapper = sqlSession.getMapper(userMapper.class); } /*删除*/ @Test public void test05(){ mapper.deleteUserById(11); } /*更新*/ @Test public void test04(){ userEntity user = new userEntity(); user.setId("15"); user.setHobby("updateHobby"); mapper.updateUser(user); } /*新增*/ @Test public void test03(){ userEntity user = new userEntity(); user.setId("15"); user.setUsername("laoliu"); user.setPassword("123789"); user.setHobby("dodo"); user.setEmail("7899@123"); mapper.addUser(user); } /*查询单个有*/ @Test public void test02(){ userEntity userEntity = mapper.selectById(5); System.out.println(userEntity); } /*查询所有*/ @Test public void test01(){ List<userEntity> userEntities = mapper.selectAll(); for (userEntity u : userEntities){ System.out.println(u); } } }
8.3、复杂映射注解(代替《resultMap》标签)
- @Result :代替标签和标签;其中属性有:
- column:数据库列名
- property:实体属性名
- one:需要使用的@One注解(@Result(one=@One)())
- many:需要使用到的@Many注解(@Result(many=@Many)())
- @Results:代替标签;其中可以使用单个@Result注解,也可以使用@Result集合。@Results({@Result(), @Result()})或@Results(@Result())
- @One(一对一):代替标签,是多表查询的关键在注解中用来指定子查询返回单一对象;其属性有:
- select:用来指定多表查询的sqlmapper
- @Many(多对多):代替标签,是多对多表查询的关键,在注解中用来指定返回对象集合
8.4、一对一多表查询
一个订单对一个用户
order实体属性
private String id;
private String num;
private userEntity user;
user实体属性
private String id;
private String username;
private String password;
private String hobby;
private String email;
方法一:
/*一对一查询*/
@Select("select *,o.id oid from orders o, t_user u where o.userid = u.id") //多表夺标查询语句
@Results({
@Result(column = "oid",property = "id"), //order实体属性封装3
@Result(column = "oerdernum",property = "num"),
@Result(column = "userid",property = "user.id"), //user实体属性封装
@Result(column = "username",property = "user.username"),
@Result(column = "password",property = "user.password"),
@Result(column = "hobby",property = "user.hobby"),
@Result(column = "email",property = "user.email")
})
public List<orderEntity> selectOrders();
方法二:
/*一对一查询*/
@Select("select * from orders") //查询一个单表orders
@Results({
@Result(column = "id",property = "id"), //order实体属性封装
@Result(column = "oerdernum",property = "num"),
@Result( //封装oerder实体中的user实体
property = "user", //order实体中user实体的对象名称
column = "userid", //查询得到orders表中外键的值useid,用来查询user表
javaType = userEntity.class, //查询结果类类
//使用参数为查询user表方法所在的全限定名;方法查询语句为:select * from t_user where id = #{id}
one = @One(select = "com.zjj.mybatis01.Mapper.userMapper.selectById")
)
})
public List<orderEntity> selectOrders();
//查询user表方法
/*查询单个*/
@Select("select * from t_user where id = #{id}")
public userEntity selectById(int id);
8.5、一对多表查询
一个用户有多个订单,先查绚user表,再根据user的id查询order表中的数据
用户实体
private String id;
private String username;
private String password;
private String hobby;
private String email;
private List<orderEntity> orderlist;
order实体
private String id;
private String oerdernum;
Mapper接口方法
/*一对多表查询*/
@Select("select * from t_user")
@Results({
@Result(id = true,column = "id", property = "id"), //user实体属性
@Result(column = "username", property = "username"),
@Result(column = "password", property = "password"),
@Result(column = "hobby", property = "hobby"),
@Result(column = "email", property = "email"),
@Result( //List集合
column = "id", //待查询条件字段
property = "orderlist", //集合名称
javaType = List.class,
many = @Many(select = "com.zjj.mybatis01.Mapper.orderMapper.selectOrderById")
)
})
public List<userEntity> selectUserAndOrder();
selectOrderById方法
@Select("select * from orders where userid = #{uid}")
public List<orderEntity> selectOrderById(int uid);
测试
/*一对多表查询*/
@Test
public void test02(){
List<userEntity> userEntities = mapper2.selectUserAndOrder();
for (userEntity u : userEntities) {
System.out.println(u);
}
}
8.6、多对多表查询
于一对多查询操作步骤类似,区别在于:
多对多查询在 many = @Many(select = “com.zjj.mybatis01.Mapper.orderMapper.selectOrderById”)中的selectOrderById方法中的sql语句不同
@Select("select * from table1 t1,order where t1.userid = #{uid} and t1.orderid = order.id ")
public List<orderEntity> selectOrderById(int uid);
三表关系为:user表、t1为中间表(包含字段:id、userid、orderid)、order表通过中间表联系起来