一.初步搭建Mbatis和使用
我当前使用的是:IDEA 2019, jdk 1.8 , mysql 5.1
1.需要的jar包
2.搭建结构
(a).mybatis-config.xml文件是配置运行环境,数据源,事务,等
<!--mybatis配置文件主要编写:连接数据库配置、加载映射文件,整合spring之后,该配置文件可以不用编写-->
<settings>
<!-- 配置log4j日志信息 -->
<setting name="logImpl" value="log4j"/>
</settings>
<!--配置插件-->
<plugins>
<!--配置分页插件-->
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
<!--连接数据库-->
<environments default="mysql">
<!--该配置环境可以有多个-->
<environment id="mysql">
<!--事务管理器类型:JDBC,Manager-->
<transactionManager type="JDBC"></transactionManager>
<!--数据源:POOLED、jndi、unpooled-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/smbms?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC"></property>
<property name="username" value="root"></property>
<property name="password" value=""></property>
</dataSource>
</environment>
</environments>
<!--加载映射文件-->
<mappers>
<mapper resource="com/bdqn/dao"/>
</mappers>
(b).log4j.properties是日志
log4j.rootLogger=DEBUG,CONSOLE,file
#log4j.rootLogger=ERROR,ROLLING_FILE
log4j.logger.cn.smbms.dao=debug
log4j.logger.com.ibatis=debug
log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=debug
log4j.logger.com.ibatis.common.jdbc.ScriptRunner=debug
log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=debug
log4j.logger.java.sql.Connection=debug
log4j.logger.java.sql.Statement=debug
log4j.logger.java.sql.PreparedStatement=debug
log4j.logger.java.sql.ResultSet=debug
log4j.logger.org.tuckey.web.filters.urlrewrite.UrlRewriteFilter=debug
######################################################################################
# Console Appender \u65e5\u5fd7\u5728\u63a7\u5236\u8f93\u51fa\u914d\u7f6e
######################################################################################
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.Threshold=error
log4j.appender.CONSOLE.Target=System.out
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern= [%p] %d %c - %m%n
######################################################################################
# DailyRolling File \u6bcf\u5929\u4ea7\u751f\u4e00\u4e2a\u65e5\u5fd7\u6587\u4ef6\uff0c\u6587\u4ef6\u540d\u683c\u5f0f:log2009-09-11
######################################################################################
log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.DatePattern=yyyy-MM-dd
log4j.appender.file.File=log.log
log4j.appender.file.Append=true
log4j.appender.file.Threshold=error
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-M-d HH:mm:ss}%x[%5p](%F:%L) %m%n
log4j.logger.com.opensymphony.xwork2=error
(c).MaBtisUtil工具类
private static SqlSessionFactory factory;
static{//在静态代码块下,factory只会被创建一次
System.out.println("static factory===============");
try {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
factory = new SqlSessionFactoryBuilder().build(is);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static SqlSession createSqlSession(){
return factory.openSession(false);//true 为自动提交事务
}
public static void closeSqlSession(SqlSession sqlSession){
if(null != sqlSession)
sqlSession.close();
}
(d).创建的实体类,映射文件,测试类,工具类
* 在userMapper.xml编写sql
```
<!--
mapper:映射文件主要编写sql
namespace:命名空间(一般填写对应接口的全限定名)
select标签:查询
delete标签:删除
insert标签:添加
update标签:修改
id:方法名
parameterType:参数类型
resultType:返回值类型
#{}:占位符,防止sql注入,参数名任意命名
${}:会引发sql注入
-->
<select id="findList" parameterType="string" resultType="com.bdqn.entity.User">
select * from smbms_user where userName like concat('%',#{name},'%')
</select>
```
- mapper写需要实现的方法
/**
* 根据名称模糊查询
* @param name
* @return
*/
List<User> findList(String name);
- userTest 执行
二.SQL映射文件
- 多条件查询(多参数需要使用注解@param)
(a).mapper接口
/**
* 根据用户名模糊查询和性别查询
* @param name
* @param sex
* @return
*/
List<User> findUserList(@Param("name") String name, @Param("sex") int sex);
(b).mapper.xml映射文件
<select id="findUserList" parameterType="string" resultType="user">
select * from smbms_user where userName like concat('%',#{name},'%') and gender=#{sex}
</select>
(c).userTest
@Test
public void test2(){
SqlSession session=MyBatisUtil.createSqlSession();
//通过动态代理模式UserMapper
UserMapper userMapper=session.getMapper(UserMapper.class);
try{
//调用查询方法
List<User> list =userMapper.findUserList("a",1);
for (User user:list) {
System.out.println(user);
}
}catch (Exception e){
e.printStackTrace();
}finally {
MyBatisUtil.closeSqlSession(session);
}
}
- mabtis实现高级结果映射(一对一,一对多,多对多)就需要使用resultMap来作为statement的输出映射类型
(a).mapper接口
/**
* 查询所有用户
* @return
*/
List<User> findAllUser();
(b).mapper.xml映射
<!--
查询所有用户
type:相关类的数据类型,例如:配置user类的属性,type就填写User类的全局路劲
id:配置主键名
property:实体类的属性名
column:数据库字段
-->
<resultMap id="userResultMap" type="com.bdqn.entity.User">
<id property="id" column="id"></id>
<result property="userCode" column="code"></result>
<result property="userName" column="name"></result>
</resultMap>
<!--使用resultMap代替resultType-->
<select id="findAllUser" resultMap="userResultMap">
select id,userCode code,userName name from smbms_user
</select>
(c).userTest
@Test
public void test8(){
SqlSession session=MyBatisUtil.createSqlSession();
//通过动态代理模式UserMapper
UserMapper userMapper=session.getMapper(UserMapper.class);
try{
List<User> list =userMapper.findAllUser();
for (User user:list) {
System.out.println(user);
}
}catch (Exception e){
e.printStackTrace();
}finally {
MyBatisUtil.closeSqlSession(session);
}
}
三.复杂关联关系映射
添加实体类
- 一对一
(a)mapper接口
/**
* 使用resultMap实现一对一
* @return
*/
List<Orders> findOrdersByResultMap();
(b)mapper.xml映射
<!--resultMap的方式配置一对一-->
<resultMap id="orderUserResultMap" type="com.bdqn.entity.Orders">
<id property="id" column="id"/>
<result column="user_id" property="userId"/>
<result column="number" property="number"/>
<result column="createTime" property="createTime"/>
<result column="note" property="note"/>
<!--配置关联的用户信息-->
<association property="user" javaType="com.bdqn.entity.User">
<!--配置User类的属性-->
<id column="user_id" property="id"/>
<result column="user_id" property="id"/>
<result column="username" property="username"/>
</association>
</resultMap>
<!--u.id user_id:user_id是u.id的别名-->
<select id="findOrdersByResultMap" resultMap="orderUserResultMap">
SELECT o.*,u.id user_id,u.username,u.address FROM orders o
INNER JOIN USER u ON o.`user_id`=u.`id`
</select>
(c)UserTest
@Test
public void test2(){
//获取session
SqlSession session=MyBatisUtil.createSqlSession();
//通过动态代理模式获取对象
OrdersMapper mapper= session.getMapper(OrdersMapper.class);
//调用查询方法
List<Orders> list=mapper.findOrdersByResultMap();
System.out.println(list.size());
}
- 一对多
(a)mapper
/**
* 使用resultMap实现一对多
* @return
*/
List<Orders> findOrderAndOrderdetailResultMap();
(b)mapper.xml
<!--配置一对多-->
<!--定义orderAndOrderdetailResultMap-->
<resultMap id="orderAndOrderdetailResultMap" type="com.bdqn.entity.Orders" extends="orderUserResultMap">
<!--配置订单明细-->
<!--collection:配置一对多,关联订单明细-->
<!--property:填写实体类的属性名 ofType:填写该属性类的数据类型-->
<collection property="orderdetailList" ofType="com.bdqn.entity.Orderdetail">
<!--property:填写实体类的属性名,column:填写数据库的属性名-->
<id property="id" column="orderdetail_id"></id>
<result property="ordersId" column="items_id"></result>
<result property="itemsId" column="items_num"></result>
<result property="itemsNum" column="orders_id"></result>
</collection>
</resultMap>
<select id="findOrderAndOrderdetailResultMap" resultMap="orderAndOrderdetailResultMap">
SELECT
o.*,
u.username ,
u.`address`,
u.`id` user_id,
d.`id` orderdetail_id,
d.`items_id`,
d.`items_num`,
d.`orders_id`
FROM
orders o
INNER JOIN `user` u ON o.`user_id` = u.`id`
INNER JOIN orderdetail d ON d.`orders_id` = o.`id`
</select>
(c)UserTest
@Test
public void test3(){
//获取session
SqlSession session=MyBatisUtil.createSqlSession();
//通过动态代理模式获取对象
OrdersMapper mapper= session.getMapper(OrdersMapper.class);
//调用查询方法
List<Orders> list=mapper.findOrderAndOrderdetailResultMap();
System.out.println(list.size());
}
- 多对多
- (a)mapper
/**
* 使用result实现多对多
* @return
*/
List<User> findUserAndItemsResultMap();
(b)mapper.xml
<!--配置多对多-->
<!--定义userAndItemsResultMap-->
<resultMap id="userAndItemsResultMap" type="com.bdqn.entity.User">
<!--1、配置用户信息-->
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="birthday" column="birthday"></result>
<result property="sex" column="sex"></result>
<result property="address" column="address"></result>
<!--2、用户关联订单信息,一对多-->
<collection property="ordersList" ofType="com.bdqn.entity.Orders">
<!--property:这个是放实体类的名称 column:这个是放别名或者数据库名的-->
<id property="id" column="order_id"/>
<result property="userId" column="order_user_id"/>
<result property="number" column="order_number"/>
<!--3、订单关联明细,一对多-->
<collection property="orderdetailList" ofType="com.bdqn.entity.Orderdetail">
<id property="id" column="orderdetail_id"></id>
<result property="ordersId" column="orders_id"></result>
<result property="itemsId" column="items_id"></result>
<result property="itemsNum" column="items_num"></result>
<!--4、订单明细关联商品信息,一对一-->
<association property="items" javaType="com.bdqn.entity.Items">
<id property="id" column="items_item_id"></id>
<result property="name" column="items_name"></result>
<result property="price" column="items_price"></result>
</association>
</collection>
</collection>
</resultMap>
<select id="findUserAndItemsResultMap" resultMap="userAndItemsResultMap">
select
u.*,
o.`id` order_id,
o.`user_id` order_user_id,
o.`number` order_number,
d.`id` orderdetail_id,
d.`items_id`,
d.`items_num`,
d.`orders_id`,
i.`id` items_item_id,
i.`name` items_name,
i.`price` items_price
from User u
inner join orders o on u.`id`=o.`user_id`
inner join orderdetail d on d.`orders_id`=o.`id`
inner join items i on i.`id`=d.`items_id`
</select>
(c)UserTest
@Test
public void test4(){
//获取session
SqlSession session=MyBatisUtil.createSqlSession();
//通过动态代理模式获取对象
OrdersMapper mapper= session.getMapper(OrdersMapper.class);
//调用查询方法
List<User> list=mapper.findUserAndItemsResultMap();
System.out.println(list.size());
}
- resultMap总结
resultType:
作用:
将查询结果按照sql列名pojo属性名一致性映射到pojo中。
场合:
常见一些明细记录的展示,比如用户购买商品明细,将关联查询信息全部展示在页面时,此时可直接使用resultType将每一条记录映射到pojo中,在前端页面遍历list(list中是pojo)即可。
resultMap:
使用association和collection完成一对一和一对多高级映射(对结果有特殊的映射要求)。
association:
作用:
将关联查询信息映射到一个pojo对象中。
场合:
为了方便查询关联信息可以使用association将关联订单信息映射为用户对象的pojo属性中,比如:查询订单及关联用户信息。
使用resultType无法将查询结果映射到pojo对象的pojo属性中,根据对结果集查询遍历的需要选择使用resultType还是resultMap。
collection:
作用:
将关联查询信息映射到一个list集合中。
场合:
为了方便查询遍历关联信息可以使用collection将关联信息映射到list集合中,比如:查询用户权限范围模块及模块下的菜单,可使用collection将模块映射到模块list中,将菜单列表映射到模块对象的菜单list属性中,这样的作的目的也是方便对查询结果集进行遍历查询。
如果使用resultType无法将查询结果映射到list集合中。
四.动态SQl
- 使用if+where查询,使用if+trim查询,使用if+set修改
(a)mapper
/**
* 多条件查询 使用 if+where
* @param map
* @return
*/
List<User> findUserByCondition(Map<String,Object> map);
/**
* trim标签动态查询 使用 if+trim
* @param map
* @return
*/
List<User> findUserWithTrim(Map<String,Object> map);
/**
* if + set修改
* @param user
* @return
*/
int updateUser(User user);
(b)mapper.xml
<!--1.where标签替换SQL语句中的where关键字-->
<select id="findUserByCondition" parameterType="map" resultType="com.bdqn.entity.User">
select * from smbms_user
<where>
<if test="userCode!=null and userCode!=''">
and userCode like concat('%',#{userCode},'%')
</if>
<if test="roleId!=null">
and userRole =#{roleId}
</if>
</where>
</select>
<select id="findUserWithTrim" parameterType="map" resultType="com.bdqn.entity.User">
select * from smbms_user
<!--prefix:前缀 prefixOverrides:剔除前面的and-->
<trim prefix="where" prefixOverrides="and">
<if test="userCode!=null and userCode!=''">
and userCode like concat('%',#{userCode},'%')
</if>
<if test="roleId!=null">
and userRole =#{roleId}
</if>
</trim>
</select>
<update id="updateUser" parameterType="com.bdqn.entity.User">
update smbms_user
<set>
<if test="userName!=null and userName!=''">
username=#{userName},
</if>
<if test="gender!=null and gender!=''">
gender=#{gender}
</if>
</set>
where id=#{id}
</update>
(c)UserTes
@Test
public void test1(){
SqlSession session=MyBatisUtil.createSqlSession();
UserMapper mapper=session.getMapper(UserMapper.class);
Map<String,Object> map=new HashMap<String,Object>();
map.put("userCode","1");
map.put("roleId",2);
List<User> list=mapper.findUserByCondition(map);
for (User user: list) {
System.out.println(user.getUserCode());
}
}
@Test
public void test2(){
SqlSession session=MyBatisUtil.createSqlSession();
UserMapper mapper=session.getMapper(UserMapper.class);
Map<String,Object> map=new HashMap<String,Object>();
map.put("userCode","a");
map.put("roleId",3);
List<User> list=mapper.findUserWithTrim(map);
for (User user: list) {
System.out.println(user.getUserCode());
}
}
@Test
public void test3(){
SqlSession session=MyBatisUtil.createSqlSession();
UserMapper mapper=session.getMapper(UserMapper.class);
User user=new User();
user.setUserName("玛丽");
user.setGender(2);
user.setId(21);
int count=mapper.updateUser(user);
if (count>0){
System.out.println("成功");
}else {
System.out.println("失败");
}
session.commit();
}
- 小结
if+where
1. where标签替换SQL语句中的where关键字
2. where标签能够剔除第一个and或or关键字
3. 占位符的内容就是条件表达式的变量
if+trim
1.prefix:前缀
2.prefixoverrides:去掉第一个and或者是or
- MyBatis分页
(a)maper
/**
* 分页查询
* @param map
* @return
*/
List<User> findUserListWithPage(Map<String,Object> map);
(b)mapper.xml
<select id="findUserListWithPage" parameterType="map" resultType="com.bdqn.entity.User">
select * from smbms_user order by id limit #{start},#{size}
</select>
(c)UserTest
@Test
public void test7(){
SqlSession session=MyBatisUtil.createSqlSession();
UserMapper mapper=session.getMapper(UserMapper.class);
Map<String,Object> map=new HashMap<String,Object>();
int pageIndex=1;
int pageSize=5;
map.put("start",(pageIndex-1)*pageSize);
map.put("size",pageSize);
List<User> list=mapper.findUserListWithPage(map);
for (User user: list) {
System.out.println(user.getUserCode());
}
}
- 使用PageHelper分页
(a)修改mybatis-config.xml
<!--配置插件-->
<plugins>
<!--配置分页插件-->
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
(b)mapper
/**
* 使用PageHelper做分页
* @return
*/
List<User> findAllUserList();
(c)mapper.xml
<select id="findAllUserList" parameterType="map" resultType="com.bdqn.entity.User">
select * from smbms_user
</select>
(d)UserTes
@Test
public void test8(){
SqlSession session=MyBatisUtil.createSqlSession();
UserMapper mapper=session.getMapper(UserMapper.class);
PageHelper.startPage(1,5);
List<User> list=mapper.findAllUserList();
PageInfo<User> page = new PageInfo<User>(list);
System.out.println("当前页码"+page.getPageNum());
System.out.println("总页数"+page.getPages());
System.out.println("总记录数"+page.getTotal());
System.out.println("每页显示数量"+page.getPageSize());
for (User user: list) {
System.out.println(user.getUserCode()+","+user.getUserName());
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。