day_58 mybatis02

一、常用标签介绍

1.配置属性

properties(属性)

property

settings(全局配置参数)

setting

typeAliases(类型别名)

typeAliase

package

typeHandlers(类型处理器)

objectFactory(对象工厂)

plugins(插件)

environments(环境集合属性对象)

environment(环境子属性对象)

transactionManager(事务管理)

dataSource(数据源)

mappers(映射器)

mapper

package

① Properties属性

在使用 properties 标签配置时,我们可以采用两种方式指定属性配置。

第一种:

<properties>
<property name="jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="jdbc.url" value="jdbc:mysql://localhost:3306/test"/>
<property name="jdbc.username" value="root"/>
<property name="jdbc.password" value="root"/>
</properties>

第二种:

在classpath下创建db.properties文件

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test 
jdbc.username=root
jdbc.password=root

<!--配置连接数据库的信息

resource 属性:用于指定 properties 配置文件的位置,要求配置文件必须在类路径下

resource="db.properties"

url 属性:

URL: Uniform Resource Locator 统一资源定位符

它是可以在 web 应用中唯一定位一个资源的路径-->

properties  url=  file:///D:/workspace/day02_test/src/db.properties">properties>

此时我们的 dataSource 标签就变成了引用上面的配置

<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>

② typeAliases属性

在前面我们讲的 Mybatis 支持的默认别名,我们也可以采用自定义别名方式来开发

在 mybatis-config.xml 中配置:

<typeAliases>
<!-- 单个别名定义 -->
<typeAlias alias="user" type="com.tledu.zrz.pojo.User"/>
<!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以) -->
<package name="com.tledu.zrz.pojo"/>
<package name="其它包"/>
</typeAliases>

③ Mappers属性

Mappers使我们所说的映射器,用于通过mybatis配置文件去找到对应的mapper文件

有三种用法

④Resources

使用相对于类路径的资源

如:

<mapper resource="com/tledu/mjw/mapper/UserMapper.xml" />

⑤class

使用 mapper 接口类路径

如:

<mapper class="com.tledu.mjw.mapper.UserMapper"/>

注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中。

⑥Package

注册指定包下的所有 mapper 接口

如:

<package name="com.tledu.mjw.mapper"/>

注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中。

2.Mapper.xml属性

1.#和$区别

#{}表示一个占位符号

通过#{}可以实现 preparedStatement 向占位符中设置值,自动进行 java 类型和 jdbc 类型转换,

#{}可以有效防止 sql 注入。

举例:select * from user where username = ' ' or 1=1 # and passord=''

#{}可以接收简单类型值或 pojo 属性值。 如果 parameterType 传输单个简单类

型值,#{}括号中可以是 value 或其它名称。

可以自动对值添加 ’ ’ 单引号

${}表示拼接 sql 串

通过${}可以将 parameterType 传入的内容拼接在 sql 中且不进行 jdbc 类型转换, ${}可以接收简

单类型值或 pojo 属性值,如果 parameterType 传输单个简单类型值,${}括号中只能是 value。

比如order by id  这种的,以id排序  那么这个id 是没有单引号的,就是简单的SQL拼接,所以我们应该使用${} 而不是#{}

举例: ALTER TABLE (表名)  ADD  keycode(字段) varchar(500) 

2.parameterType 配置参数

我们在上一章节中已经介绍了 SQL 语句传参,使用标签的 parameterType 属性来设定。该属性的取值可以是基本类型,引用类型(例如:String 类型),还可以是实体类类型(POJO 类)。同时也可以使用实体类的包装类,本章节将介绍如何使用实体类的包装类作为参数传递。

注意事项

基本类型和String我们可以直接写类型名称,也可以使用包名.类名的方式

例如 :

java.lang.String

实体类类型,目前我们只能使用全限定类名。

究其原因,是 mybaits 在加载时已经把常用的数据类型注册了别名,从而我们在使用时可以不写包名,而我们的是实体类并没有注册别名,所以必须写全限定类名。

这些都是支持的默认别名。我们也可以从源码角度来看它们分别都是如何定义出来的。

可以参考 TypeAliasRegistery.class 的源码。

 

3.resultType

resultType 属性可以指定结果集的类型,它支持基本类型和实体类类型。

我们在前面的 CRUD 案例中已经对此属性进行过应用了。

需要注意的是,它和 parameterType 一样,如果注册过类型别名的,可以直接使用别名。没有注册过的必须使用全限定类名。

例如:我们的实体类此时必须是全限定类名

同时,当是实体类名称时,还有一个要求,实体类中的属性名称必须和查询语句中的列名保持一致,否则无法实现封装(不区分大小写)

4.resultMap

我们在resultType ,提到在声明返回值类型为实体类型之后,实体中的属性必须和查询语句中的属性对应上,但是我们在开发的过程中也难免会遇到无法对应的情况。比如说我们在进行数据库设计的时候,多个单词往往是用_连接,但是在实体类中的属性往往采用小驼峰的方式命名。这就导致字段名无法对应上,这个时候我们就需要配置resultMap来解决这个问题了。

通过resultMap,我们可以指定查询结果字段和实体属性字段的映射关系。

<resultMap id="userResult" type="User">
    <id column="id" property="id" />
    <result property="nickname" column="nickname" />
    <result property="schoolName" column="school_name" />
</resultMap>

二、单元测试介绍

1、应用项目中导包

2、测试代码示例

//在所有@Test所标注的方法前都会先运行
@After
public void after(){
    System.out.println("after");
}

//具体测试方法
@Test
public void test1(){
    System.out.println("test");
}

//在所有@Test所标注的方法运行完后会运行
@Before
public void before(){
    System.out.println("before");
}

三、实现分页查询

分页是展示页面中常见的一种技术,就是把数据在页面分开显示,这样可以提高执行效率和用户的流量

比如我们有100条数据,用户在打开这个页面的时候需要加载100条数据,而后台需要处理100条数据

但是如果我们规定每页显示10条,也就是需要10页,这样每次只需要处理10条数据,客户每次只需要加载10条数据

那好像10页加起来也不会提高效率...

但是如果第二页就出现了你想要的数据,你还会查看第三页吗?

1、分页思想

看图分析:

 

如上图所示,t_user表共7条数据,如果按每页显示3条来算,共分3页

总条数 totalCount:select count(*) from t_user;

每页条数 pageSize: 3

共有几页 totalPage: totalCount / pageSize + (totalCount % pageSize == 0 ? 0 : 1)

通过分页limit查询参数变化规律 可以 发现

select * from t_user limit 起始值,分页单位

起始值一直在变化 ,而分页单设定好后是不变的

起始值 = (当前页-1)*分页单位

这样我们就可以根据以上规律实现sql的分页查询了

2、在UserMapper.xml中添加分页相关sql

 <!-- 获取分页数据 -->
    <select id="findPageList" resultType="User" parameterType="map">
       select * from t_user limit #{pageOffset},#{pageSize}
    </select>
    <!-- 获取总条数 -->
    <select id="getListCount" resultType="int">
    	select count(*) from t_user;
    </select>

3、测试

@Test
public void test1(){
    SqlSession session = MybatisUtil.getSession();
    Map<String,Object> map = new HashMap<>();
    int cpage = 2;
    int pageSize = 3;
    int start = (cpage-1)*pageSize;
    map.put("start",start);
    map.put("pageSize",pageSize);
    List<User> list = session.selectList("User.getList", map);
    for (User user : list) {
        System.out.println(user);
    }
    session.close();
}

分页插件的使用:

PageHelper是一款犀利的Mybatis分页插件,使用了这个插件之后,分页开发起来更加简单容易。因为是第三方插件,所以需要额外的jar包

配置插件

在mybatis-config.xml中,添加plugins标签配置,表示开启PageHelper插件

<?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>
    <settings> 
            <!-- 打开延迟加载的开关 --> 
            <setting name="lazyLoadingEnabled" value="true" /> 
            <!-- 将积极加载改为消息加载即按需加载 --> 
            <setting name="aggressiveLazyLoading" value="false"/> 
        </settings>   
    <typeAliases>
      <package name="com.how2java.pojo"/>
    </typeAliases>
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>     
    <environments default="development">
 .....
    </environments>
    <mappers>
...
    </mappers>
</configuration>

修改CategoryMapper.xml

limit注释掉,因为分页相关工作,会由PageHelper去做掉,不需要自己去写了

<?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.how2java.pojo">
        <select id="listCategory" resultType="Category">
            select * from   t_category
<!--                 <if test="start!=null and count!=null"> -->
<!--                     limit #{start},#{count} -->
<!--                 </if> -->
        </select>    
    </mapper>

分页查询测试

查询很有意思,只需要在执行查询所有的调用之前,执行一条语句即可:

PageHelper.offsetPage(0, 5);

public class TestMybatis {
    public static void main(String[] args) throws IOException, InterruptedException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = newSqlSessionFactoryBuilder().build(inputStream);
        SqlSession session = sqlSessionFactory.openSession();
      
        PageHelper.offsetPage(0, 5);
 
        List<Category> cs = session.selectList("listCategory");
        for (Category c : cs) {
            System.out.println(c.getName());
        }
 
        session.commit();
        session.close();
    }
}

获取总数

public class TestMybatis {
    public static void main(String[] args) throws IOException, InterruptedException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = newSqlSessionFactoryBuilder().build(inputStream);
        SqlSession session = sqlSessionFactory.openSession();
      
        PageHelper.offsetPage(0, 5);
 
        List<Category> cs = session.selectList("listCategory");
        for (Category c : cs) {
            System.out.println(c.getName());
        }
         
        PageInfo pageInfo = new PageInfo<>(cs);
        System.out.println("总数:"+pageInfo.getTotal());
        System.out.println(pageInfo);
 
        session.commit();
        session.close();
    }
}

四、完成模糊查询

模糊查询

1. 修改UserMapper.xml,提供listUserByName查询语句

  <select id="listUserByName"  parameterType="string" resultType="User">
      select * from t_user where username like concat('%',#{0},'%')
    </select>

2. 测试

@Test
public void listUserByName() {
	SqlSession session = null;
	try {
	session = MybatisUtil.getSession();
	List<User> list = session.selectList("User.listUserByName","d");
		for (User user : list) {
                  System.out.println(user);
		}
	} catch (Exception e) {
		e.printStackTrace();
	} finally {
		MybatisUtil.closeSession(session);
	}
}

多条件查询

结合前面的模糊查询,多一个id大于多少的条件

1. UserMapper.xml 准备sql语句

<select id="listUserByIdAndName"  parameterType="map" resultType="User">
 select * from t_user  where id> #{id} and username like concat('%',#{username},'%')
</select>

2. 测试代码

因为是多个参数,而session.selectList()方法又只接受一个参数对象,所以需要把多个参数放在Map里,然后把这个Map对象作为参数传递进去

  Map<String,Object> params = new HashMap<>();
    params.put("id", 8);
    params.put("username", "d");
    List<User> ulist= session.selectList("User.listUserByIdAndName",params);

五、掌握动态SQL

动态SQL是MyBatis的一个强大特性之一,如果你有使用 JDBC 或其他 相似框架的经验,你就明白条件地串联 SQL 字符串在一起是多么的痛苦,确保不能忘了空 格或在列表的最后省略逗号。动态 SQL 可以彻底处理这种痛苦。 

动态 SQL 元素和使用 JSTL 或其他相似的基于 XML 的文本处理器相似。在 MyBatis 之 前的版本中,有很多的元素需要来了解。MyBatis 3 大大提升了它们,现在用不到原先一半 的元素就能工作了。MyBatis 采用功能强大的基于 OGNL 的表达式来消除其他元素。

· if

· choose (when, otherwise)

· where等

创建产品表

create table t_product(
id int NOT NULL AUTO_INCREMENT,
name varchar(30)  DEFAULT NULL,
price float  DEFAULT 0,
cid int ,
PRIMARY KEY (id)
)AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

新增6条产品数据

INSERT INTO t_product VALUES (1,'product a', 88.88, 1);
INSERT INTO t_product VALUES (2,'product b', 88.88, 1);
INSERT INTO t_product VALUES (3,'product c', 88.88, 1);
INSERT INTO t_product VALUES (4,'product x', 88.88, 2);
INSERT INTO t_product VALUES (5,'product y', 88.88, 2);
INSERT INTO t_product VALUES (6,'product z', 88.88, 2);

创建Product实体类

public class Product {
    private int id;
    private String name;
    private float price;

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public float getPrice() {
        return price;
    }
    public void setPrice(float price) {
        this.price = price;
    }
    @Override
    public String toString() {
        return "Product [id=" + id + ", name=" + name + ", price=" + price + "]";
    }

动态SQL导入

执行不同的条件限定,需要准备两条sql语句

假设需要对Product执行两条sql语句,一个是查询所有,一个是根据名称模糊查询。

那么按照现在的方式,必须提供两条sql语句:listProduct和listProductByName

然后在调用的时候,分别调用它们来执行。

在ProductMapper.xml添加如下代码

    <select id="listProduct" resultType="Product">
         select * from t_product         
    </select>
    <select id="listProductByName" resultType="Product">
          select * from t_product where name like concat('%',#{name},'%')        
    </select>

在测试类进行测试

    System.out.println("查询所有的");
    List<Product> ps = session.selectList("listProduct");
    for (Product p : ps) {
         System.out.println(p);
    }
         
    System.out.println("模糊查询");
    Map<String,Object> params = new HashMap<>();
    params.put("name","a");
    List<Product> ps2 = session.selectList("listProductByName",params);
    for (Product p : ps2) {
         System.out.println(p);
    } 

if标签

如果Product的字段比较多的话,为了应付各个字段的查询,那么就需要写多条sql语句,这样就变得难以维护。这个时候,就可以使用Mybatis 动态SQL里的if标签

<select id="listProduct" resultType="Product">
	select * from t_product
	<if test="name!=null">
		where name like concat('%',#{name},'%')
	</if>		 	
</select>

在测试类进行测试

    System.out.println("查询所有的");
    List<Product> ps = session.selectList("listProduct");
    for (Product p : ps) {
         System.out.println(p);
    }
         
    System.out.println("模糊查询");
    Map<String,Object> params = new HashMap<>();
    params.put("name","a");
    List<Product> ps2 = session.selectList("listProductByName",params);
    for (Product p : ps2) {
         System.out.println(p);
    } 

where标签

基于上一个知识点if 标签进行

在ProductMapper.xml添加如下代码

如果要进行多条件判断,就会写成这样

<select id="listProduct" resultType="Product">
	select * from t_product
	<if test="name!=null">
		where name like concat('%',#{name},'%')
	</if>		 	
	<if test="price!=0">
		and price > #{price}
	</if>		 	
</select>

这么写的问题是:当没有name参数,却有price参数的时候,执行的sql语句就会是:

select * from t_product and price > 10

这样执行就会报错

这个问题可以通过标签来解决,如代码所示

<select id="listProduct" resultType="Product">
    select * from t_product
      <where>
    	<if test="name!=null">
    	   and name like concat('%',#{name},'%')
    	</if>		 	
    	<if test="price!=null and price!=0">
    	   and price > #{price}
    	</if>	
      </where>	 	
</select>

标签会进行自动判断

如果任何条件都不成立,那么就在sql语句里就不会出现where关键字

如果有任何条件成立,会自动去掉多出来的 and 或者 or。

所以在测试代码里

     Map<String,Object> params = new HashMap<>(); 
     //params.put("name","a");
     params.put("price","10");

这个参数map,无论是否提供值都可以正常执行

set标签

where标签类似的,在update语句里也会碰到多个字段相关的问题。 在这种情况下,就可以使用set标签:

   <update id="updateProduct" parameterType="Product" >
        update t_product
        <set>
            <if test="name != null">name=#{name},</if>
            <if test="price != null">price=#{price}</if>
        </set>
         where id=#{id}   
    </update>

其效果与where标签类似,有数据的时候才进行设置。

测试:

        Product p = new Product();
        p.setId(6);
        p.setName("product zz");
        p.setPrice(99.99f);
        session.update("updateProduct",p);

trim标签

trim 用来定制想要的功能,比如where标签就可以用

prefix :内容之前加的前缀 

suffix :内容之后加的后缀 

prefixOverrides:  属性会忽略通过管道分隔的文本序列

...

来替换

set标签就可以用

...

来替换

测试ProductMapper.xml

<select id="listProduct" resultType="Product">
        select * from t_product
        <trim prefix="WHERE" prefixOverrides="AND |OR ">
            <if test="name!=null">
                name like concat('%',#{name},'%')
            </if>        
            <if test="price!=null and price!=0">
                price > #{price}
            </if>
        </trim>      
 </select>
<update id="updateProduct" parameterType="Product" >
        update t_product
        <trim prefix="SET" suffixOverrides=",">
            <if test="name != null">name=#{name},</if>
            <if test="price != null">price=#{price},</if>
        </trim>
        where id=#{id}   
 </update>

choose、when、otherwise

类似于Java中的switch case default

在ProductMapper.xml文件中添加如下代码

<select id="listProduct" resultType="Product">
	  SELECT * FROM t_product 
	  <where>
	  	<choose>
		  <when test="name != null">
		    and name like concat('%',#{name},'%')
		  </when>			  
		  <when test="price !=null and price != 0">
		    and price > #{price}
		  </when>			  		
	  	  <otherwise>
	  	  	and id >1
	  	  </otherwise>
	  	</choose>
	  </where>
</select>

在测试类中添加如下代码测试

      Map<String,Object> params = new HashMap<>();
//    params.put("name","a");
//    params.put("price","10");
      List<Product> ps = session.selectList("listProduct",params);
      for (Product p : ps) {
          System.out.println(p);
      }

foreach标签

ProductMapper.xml

foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合。

foreach元素的属性主要有 item,index,collection,open,separator,close。

item集合中每一个元素进行迭代时的别名,

open该语句以什么开始,

separator在每次进行迭代之间以什么符号作为分隔 符,

close以什么结束,

在使用foreach的时候最关键的也是最容易出错的就是collection属性,

该属性是必须指定的,但是在不同情况下,该属性的值是不一样的,

主要有一下3种情况:

1.     如果传入的是单参数且参数类型是一个List的时候,collection属性值为list

2.     如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array

3.     如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了

 <select id="listProduct" resultType="Product">
       SELECT * FROM t_product
           WHERE ID in 
               <foreach item="item" index="index" collection="list"
                   open="(" separator="," close=")">
                   #{item}
               </foreach>
 </select>

在测试类中添加如下代码测试

List<Integer> ids = new ArrayList();
        ids.add(1);
        ids.add(3);
        ids.add(5);
         
 List<Product> ps = session.selectList("listProduct",ids);
      for (Product p : ps) {
          System.out.println(p);
      }

bind标签

ProductMapper.xml

     <!-- 本来的模糊查询方式 -->
<!--    <select id="listProduct" resultType="Product"> -->
<!--             select * from  t_product  where name like concat('%',#{0},'%') -->
<!--    </select> -->
             
        <select id="listProduct" resultType="Product">
            <bind name="likename" value="'%' + name + '%'" />
            select * from  t_product where name like #{likename}
        </select>

在测试类中添加如下代码测试

Map<String, String> params =new HashMap();
    params.put("name", "product");
        
List<Product> ps = session.selectList("listProduct",params);
       for (Product p : ps) {
           System.out.println(p);
       }

六、关联查询

在项目中,某些实体类之间肯定有关联关系,比如一对一、多对一、一对多、多对多等,在mybatis 中可以通过association和collection,来处理这些关联关系。

1、一对多

对于产品类型来说,一种产品类型就对应了多个产品,那么在mybatis中我们可以通过collections解决。

1.1、创建产品表

create table t_product( 
id int NOT NULL AUTO_INCREMENT,
name varchar(30) DEFAULT NULL, 
price float DEFAULT 0, 
cid int , 
PRIMARY KEY (id) 
)AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

1.2、创建产品类型表

create table t_category ( 
id int(11) NOT NULL AUTO_INCREMENT, 
name varchar(32) DEFAULT NULL, 
PRIMARY KEY (id) 
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

1.3、清空t_category 和 t_product_ 表 新增2条分类数据,id分别是1,2 ;新增6条产品数据,分

别关联上述2条分类数据

delete from t_category;
INSERT INTO t_category VALUES (1,'category1');
INSERT INTO t_category VALUES (2,'category2');
delete from t_product;
INSERT INTO t_product VALUES (1,'product a', 88.88, 1);
INSERT INTO t_product VALUES (2,'product b', 88.88, 1);
INSERT INTO t_product VALUES (3,'product c', 88.88, 1);
INSERT INTO t_product VALUES (4,'product x', 88.88, 2);
INSERT INTO t_product VALUES (5,'product y', 88.88, 2);
INSERT INTO t_product VALUES (6,'product z', 88.88, 2);

1.4、创建Product实体类

public class Product {
    private int id;
    private String name;
    private float price;

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public float getPrice() {
        return price;
    }
    public void setPrice(float price) {
        this.price = price;
    }
    @Override
    public String toString() {
        return "Product [id=" + id + ", name=" + name + ", price=" + price + "]";
    }

1.5、创建Category实体

public class Category {
    private int id;
    private String name;
    List<Product> products;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public List<Product> getProducts() {
        return products;
    }
    public void setProducts(List<Product> products) {
        this.products = products;
    }
    @Override
    public String toString() {
        return "Category [id=" + id + ", name=" + name + "]";
    }
}

1.6、创建CategoryMapper.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="com.test.pojo">
        <resultMap type="Category" id="categoryBean">
            <id column="cid" property="id" />
            <result column="cname" property="name" />
            <!-- 一对多的关系 -->
            <!-- property: 指的是集合属性的值, ofType:指的是集合中元素的类型 -->
            <collection property="products" ofType="Product">
                <id column="pid" property="id" />
                <result column="pname" property="name" />
                <result column="price" property="price" />
            </collection>
        </resultMap>
     
        <!-- 关联查询分类和产品表 -->
        <select id="listCategory" resultMap="categoryBean">
            select c.*, p.*, c.id 'cid', p.id 'pid', c.name 'cname', p.name 'pname' from t_category c left join t_product p on c.id = p.cid
        </select>   
    </mapper>

1.7、创建MyBatis测试类

 public static void main(String[] args) throws IOException {
    String resource = "mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    SqlSessionFactory sqlSessionFactory = newSqlSessionFactoryBuilder().build(inputStream);
    SqlSession session = sqlSessionFactory.openSession();
  
        List<Category> cs = session.selectList("listCategory");
        for (Category c : cs) {
            System.out.println(c);
            List<Product> ps = c.getProducts();
            for (Product p : ps) {
                System.out.println("\t"+p);
            }
        }
        session.commit();
        session.close();
    }

2、多对一

对于产品类型来说,一种类型就对应了多个产品,但对于产品来说只能对应一种产品类型,这种情况,在mybatis中就可以通过association 解决。本知识点建立在一对多的基础上讲解多对一关系。

2.1、修改Product.java 添加Category对象属性

public class Product {
    private int id;
    ......
    private Category category;
     
    public Category getCategory() {
        return category;
    }
    public void setCategory(Category category) {
        this.category = category;
    }
    ......
    @Override
    public String toString() {
        return "Product [id=" + id + ", name=" + name + ", price=" + price + "]";
    }
}

2.2、创建ProductMapper.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="com.hanlin.pojo">
        <resultMap type="Product" id="productBean">
            <id column="pid" property="id" />
            <result column="pname" property="name" />
            <result column="price" property="price" />
     
            <!-- 多对一的关系 -->
            <!-- property: 指的是属性名称, javaType:指的是属性的类型 -->
            <association property="category" javaType="Category">
                <id column="cid" property="id"/>
                <result column="cname" property="name"/>
            </association>
        </resultMap>
     
        <!-- 根据id查询Product, 关联将Orders查询出来 -->
        <select id="listProduct" resultMap="productBean">
            select c.*, p.*, c.id 'cid', p.id 'pid', c.name 'cname', p.name 'pname' from t_category c left join t_product p on c.id = p.cid
        </select>   
    </mapper>

2.3、修改mybatis-config.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>
    <typeAliases>
      <package name="com.mjw.pojo"/>
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
            <property name="driver" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/ssm?characterEncoding=UTF-8"/>
            <property name="username" value="root"/>
            <property name="password" value="admin"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/mjw/pojo/Category.xml"/>
        <mapper resource="com/mjw/pojo/Product.xml"/>
    </mappers>
</configuration>

2.4、在测试类中测试

public static void main(String[] args) throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = newSqlSessionFactoryBuilder().build(inputStream);
        SqlSession session = sqlSessionFactory.openSession();
        List<Product> ps = session.selectList("listProduct");
        for (Product p : ps) {
            System.out.println(p+" 对应的分类是 \t "+ p.getCategory());
        }
        session.commit();
        session.close();
    }

ParameterType常见传入参数

2.1.   传入简单类型

    Java代码:

public User get(Long id) {    
    return (User) getSqlSession().selectOne("com.mjw.get" , id);  
}  

 MAPPER :

<select id="findUserListByIdList" parameterType="java.lang.Long" resultType="User">  
        select * from user where  id = #{id};  
</select>  

2.2.   传入List

    JAVA代码:

public List<Area> findUserListByIdList(List<Long> idList) {  
 return getSqlSession().selectList("com.mjw.findUserListByIdList", idList);  
}

MAPPER :

<select id="findUserListByIdList" parameterType="java.util.ArrayList" resultType="User">  
    select * from user user  
    <where>  
        user.ID in (  
        <foreach item="guard" index="index" collection="list"  separator=","> 
              #{guard} 
       </foreach>  
        )  
    </where>  
</select>   

单独传入list时,foreach中的collection必须是list,不不管变量的具体名称是什么。比如这里变量名为idList,collection却是是list。 

2.3.  传入数组

  JAVA代码:

 public List<Area> findUserListByIdList(int[] ids) {  
  return getSqlSession().selectList("com.mjw.findUserListByIdList", ids);  
 }  

 MAPPER :

 <select id="findUserListByIdList" parameterType="java.util.HashList" resultType="User">  
    select * from user user  
    <where>  
        user.ID in (  
        <foreach item="guard" index="index" collection="array" separator=","> 
           #{guard} 
        </foreach>  
        )  
    </where>  
</select>     

 单独传入数组时,foreach中的collection必须是array,不不管变量的具体名称是什么。比如这里变量名为ids,collection却是是array

2.4.  传入map

 JAVA代码:

public boolean exists(Map<String, Object> map){  
        Object count = getSqlSession().selectOne("com.mjw.exists", map);  
        int totalCount = Integer.parseInt(count.toString());  
        return totalCount > 0 ? true : false;  
    }  

 MAPPER :

<select id="exists" parameterType="java.util.HashMap" resultType="java.lang.Integer">  
        SELECT COUNT(*) FROM USER user  
        <where>  
            <if test="code != null">   
                and user.CODE = #{code}   
            </if>  
            <if test="id != null">   
                and user.ID = #{id}   
            </if>  
            <if test="idList !=null ">  
                and user.ID in (  
                <foreach item="guard" index="index" collection="idList"  
                    separator=","> #{guard} </foreach>  
                )  
            </if>  
        </where>  
    </select>

 MAP中有list或array时,foreach中的collection必须是具体list或array的变量名。比如这里MAP含有一个名为idList的list,所以MAP中用idList取值,这点和单独传list或array时不太一样。

2.5. 传入JAVA对象

 JAVA代码:

public boolean findUserListByDTO(UserDTO userDTO){  
        Object count = getSqlSession().selectOne("com.mjw.exists", userDTO);  
        int totalCount = Integer.parseInt(count.toString());  
        return totalCount > 0 ? true : false;  
    }  

 MAPPER :

<select id="findUserListByDTO" parameterType="UserDTO" resultType="java.lang.Integer">  
        SELECT COUNT(*) FROM USER user  
        <where>  
            <if test="code != null">   
                and user.CODE = #{code}   
            </if>  
            <if test="id != null">   
                and user.ID = #{id}   
            </if>  
            <if test="idList !=null ">  
                and user.ID in (  
                <foreach item="guard" index="index" collection="idList"  
                    separator=","> #{guard} </foreach>  
                )  
            </if>  
        </where>  
    </select>

JAVA对象中有list或array时,foreach中的collection必须是具体list或array的变量名。比如这里UserDTO含有一个名为idList的list,所以UserDTO中用idList取值,这点和单独传list或array时不太一样。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值