Spring下的Mybatis ibatis Hibernate

MyBatis是一款优秀的持久层框架,提供自定义SQL、存储过程和高级映射。在Spring环境下,通过SqlSessionFactory配置,结合注解或XML映射文件实现ORM。本文介绍了MyBatis的半ORM特性、动态SQL(if、choose、when、otherwise、trim、where、set、foreach)以及如何在Spring中使用MyBatis,包括注解方式和配置文件方法。
摘要由CSDN通过智能技术生成

什么是MyBatis?

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射(ORM)。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

在spring的环境下使用mybatis

配置pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.softeem</groupId>
    <artifactId>spring-mybatis-test</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <java.version>1.8</java.version>

        <spring.version>5.2.0.RELEASE</spring.version>
        <mybatis.version>3.5.4</mybatis.version>
        <mybatis-spring.version>2.0.4</mybatis-spring.version>
        <hikaricp.version>3.4.2</hikaricp.version>
        <hsqldb.version>2.5.0</hsqldb.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>javax.annotation-api</artifactId>
            <version>1.3.2</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>${mybatis.version}</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>${mybatis-spring.version}</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.20</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.21</version>
        </dependency>
    </dependencies>
</project>

SqlSessionFactory

每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例。

在这里我们的运行环境是Spring容器,而容器要管理所有参与业务的bean,自然SqlSeesionFactory对象也可以委托给spring容器来创建

AppConfig

package com.softeem;


import com.alibaba.druid.pool.DruidDataSource;
import com.softeem.service.TextService;
import com.softeem.service.UserService;
import com.softeem.service.impl.UserServiceImpl;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.*;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.io.IOException;

/**
 * @Author fyj 2020/9/18 11:11
 */
@ComponentScan
@Configuration
@PropertySource("jdbc.properties")
@MapperScan("com.softeem.dao")
@EnableTransactionManagement
public class AppConfig {

    @Bean
    public DataSource createDataSource(
            @Value("${user}") String user,
            @Value("${password}") String password,
            @Value("${url}") String url,
            @Value("${driver}") String driver
    ){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(user);
        ds.setPassword(password);
        return ds;
    }

    @Bean
    public PlatformTransactionManager createTransactionManager(@Autowired DataSource dataSource){
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean
    SqlSessionFactoryBean createFactoryBean(@Autowired DataSource dataSource) throws IOException {
        SqlSessionFactoryBean sf = new SqlSessionFactoryBean();
        sf.setDataSource(dataSource);
        return sf;
    }
}

我们引入了数据源,事物管理器。由于SqlSessionFactory是一个接口,而Spring为了能够和Mybatis整合,故而实现了该接口,实现类的名称为SqlSessionFactoryBean, 我们通过@Bean将其加载至容器中

半ORM和优秀灵活的SQL

Mybatis醉的的特点应该是它只是一个半ORM框架,我们依旧需要编写SQL语句,它简化了我们最终将结果集resultSet映射到对象的这一步操作。Mybatis相比较于JDBC,在编写SQL上进行了一些优化,提供了一些例如可以帮助我们实现动态SQL的标签库

mybatis示例

    @Select("select * from user")
    public List<User> listUsers();

    @Select("select * from user where id = #{value}")
    public User getUserById(int id);

使用Mybatis

  • 引用相关的pom支持
  • 在Configuration(AppConfig.java)中配置SqlSessionFaction到容器,该对象需要传入一个DataSource数据源
  • 编写Mapper接口,定义对应得方法
  • 添加注解,写入SQL语句
  • 在Configuration类中添加注解@MapperScan去扫描mybatis的mapper
  • 运行

注解方式

如果是简单的sql语句使用注解方法很容易,但是如果是比较复杂的sql语句那么使用注解的方式就比较困难了
例如

@Select("<script>" +
        "select * from user" +
        " where 1=1 " +
        "<if test='username!=null'>" +
        "and username = #{username}" +
        "</if>" +
        "<if test='password!=null'>" +
        "and password = #{password}" +
        "</if>" +
        "</script>")
public List<User> listUsersByUserNameOrPassword(@Param("username") String username,@Param("password") String password);

这样的可读性太差了,所以非常不推荐在有一些复杂的需求的情况下使用这种方法

配置文件方法

上面比较复杂的sql语句,我们可以采用配置文件的形式来实现
实例

<?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.softeem.mapper.BookMapper">
  <resultMap id="BaseResultMap" type="com.softeem.entity.Book">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="cover" jdbcType="VARCHAR" property="cover" />
    <result column="title" jdbcType="VARCHAR" property="title" />
    <result column="author" jdbcType="VARCHAR" property="author" />
    <result column="date" jdbcType="VARCHAR" property="date" />
    <result column="press" jdbcType="VARCHAR" property="press" />
    <result column="abs" jdbcType="VARCHAR" property="abs" />
    <result column="cid" jdbcType="INTEGER" property="cid" />
  </resultMap>
  <sql id="Base_Column_List">
    id, cover, title, author, `date`, press, `abs`, cid
  </sql>
  <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List" />
    from book
    where id = #{id,jdbcType=INTEGER}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
    delete from book
    where id = #{id,jdbcType=INTEGER}
  </delete>
  <insert id="insert" keyColumn="id" keyProperty="id" parameterType="com.softeem.entity.Book" useGeneratedKeys="true">
    insert into book (cover, title, author,
      `date`, press, `abs`, cid
      )
    values (#{cover,jdbcType=VARCHAR}, #{title,jdbcType=VARCHAR}, #{author,jdbcType=VARCHAR},
      #{date,jdbcType=VARCHAR}, #{press,jdbcType=VARCHAR}, #{abs,jdbcType=VARCHAR}, #{cid,jdbcType=INTEGER}
      )
  </insert>
  <insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="com.softeem.entity.Book" useGeneratedKeys="true">
    insert into book
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="cover != null">
        cover,
      </if>
      <if test="title != null">
        title,
      </if>
      <if test="author != null">
        author,
      </if>
      <if test="date != null">
        `date`,
      </if>
      <if test="press != null">
        press,
      </if>
      <if test="abs != null">
        `abs`,
      </if>
      <if test="cid != null">
        cid,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="cover != null">
        #{cover,jdbcType=VARCHAR},
      </if>
      <if test="title != null">
        #{title,jdbcType=VARCHAR},
      </if>
      <if test="author != null">
        #{author,jdbcType=VARCHAR},
      </if>
      <if test="date != null">
        #{date,jdbcType=VARCHAR},
      </if>
      <if test="press != null">
        #{press,jdbcType=VARCHAR},
      </if>
      <if test="abs != null">
        #{abs,jdbcType=VARCHAR},
      </if>
      <if test="cid != null">
        #{cid,jdbcType=INTEGER},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="com.softeem.entity.Book">
    update book
    <set>
      <if test="cover != null">
        cover = #{cover,jdbcType=VARCHAR},
      </if>
      <if test="title != null">
        title = #{title,jdbcType=VARCHAR},
      </if>
      <if test="author != null">
        author = #{author,jdbcType=VARCHAR},
      </if>
      <if test="date != null">
        `date` = #{date,jdbcType=VARCHAR},
      </if>
      <if test="press != null">
        press = #{press,jdbcType=VARCHAR},
      </if>
      <if test="abs != null">
        `abs` = #{abs,jdbcType=VARCHAR},
      </if>
      <if test="cid != null">
        cid = #{cid,jdbcType=INTEGER},
      </if>
    </set>
    where id = #{id,jdbcType=INTEGER}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.softeem.entity.Book">
    update book
    set cover = #{cover,jdbcType=VARCHAR},
      title = #{title,jdbcType=VARCHAR},
      author = #{author,jdbcType=VARCHAR},
      `date` = #{date,jdbcType=VARCHAR},
      press = #{press,jdbcType=VARCHAR},
      `abs` = #{abs,jdbcType=VARCHAR},
      cid = #{cid,jdbcType=INTEGER}
    where id = #{id,jdbcType=INTEGER}
  </update>
</mapper>

<?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.softeem.mapper.BookMapper">
  <resultMap id="BaseResultMap" type="com.softeem.entity.Book">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="cover" jdbcType="VARCHAR" property="cover" />
    <result column="title" jdbcType="VARCHAR" property="title" />
    <result column="author" jdbcType="VARCHAR" property="author" />
    <result column="date" jdbcType="VARCHAR" property="date" />
    <result column="press" jdbcType="VARCHAR" property="press" />
    <result column="abs" jdbcType="VARCHAR" property="abs" />
    <result column="cid" jdbcType="INTEGER" property="cid" />
  </resultMap>
  <sql id="Base_Column_List">
    id, cover, title, author, `date`, press, `abs`, cid
  </sql>
  <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List" />
    from book
    where id = #{id,jdbcType=INTEGER}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
    delete from book
    where id = #{id,jdbcType=INTEGER}
  </delete>
  <insert id="insert" keyColumn="id" keyProperty="id" parameterType="com.softeem.entity.Book" useGeneratedKeys="true">
    insert into book (cover, title, author,
      `date`, press, `abs`, cid
      )
    values (#{cover,jdbcType=VARCHAR}, #{title,jdbcType=VARCHAR}, #{author,jdbcType=VARCHAR},
      #{date,jdbcType=VARCHAR}, #{press,jdbcType=VARCHAR}, #{abs,jdbcType=VARCHAR}, #{cid,jdbcType=INTEGER}
      )
  </insert>
  <insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="com.softeem.entity.Book" useGeneratedKeys="true">
    insert into book
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="cover != null">
        cover,
      </if>
      <if test="title != null">
        title,
      </if>
      <if test="author != null">
        author,
      </if>
      <if test="date != null">
        `date`,
      </if>
      <if test="press != null">
        press,
      </if>
      <if test="abs != null">
        `abs`,
      </if>
      <if test="cid != null">
        cid,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="cover != null">
        #{cover,jdbcType=VARCHAR},
      </if>
      <if test="title != null">
        #{title,jdbcType=VARCHAR},
      </if>
      <if test="author != null">
        #{author,jdbcType=VARCHAR},
      </if>
      <if test="date != null">
        #{date,jdbcType=VARCHAR},
      </if>
      <if test="press != null">
        #{press,jdbcType=VARCHAR},
      </if>
      <if test="abs != null">
        #{abs,jdbcType=VARCHAR},
      </if>
      <if test="cid != null">
        #{cid,jdbcType=INTEGER},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="com.softeem.entity.Book">
    update book
    <set>
      <if test="cover != null">
        cover = #{cover,jdbcType=VARCHAR},
      </if>
      <if test="title != null">
        title = #{title,jdbcType=VARCHAR},
      </if>
      <if test="author != null">
        author = #{author,jdbcType=VARCHAR},
      </if>
      <if test="date != null">
        `date` = #{date,jdbcType=VARCHAR},
      </if>
      <if test="press != null">
        press = #{press,jdbcType=VARCHAR},
      </if>
      <if test="abs != null">
        `abs` = #{abs,jdbcType=VARCHAR},
      </if>
      <if test="cid != null">
        cid = #{cid,jdbcType=INTEGER},
      </if>
    </set>
    where id = #{id,jdbcType=INTEGER}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.softeem.entity.Book">
    update book
    set cover = #{cover,jdbcType=VARCHAR},
      title = #{title,jdbcType=VARCHAR},
      author = #{author,jdbcType=VARCHAR},
      `date` = #{date,jdbcType=VARCHAR},
      press = #{press,jdbcType=VARCHAR},
      `abs` = #{abs,jdbcType=VARCHAR},
      cid = #{cid,jdbcType=INTEGER}
    where id = #{id,jdbcType=INTEGER}
  </update>
</mapper>

准确的说,这个叫映射文件,用来和mapper相对应,mapper接口中定义的方法,在该文件中进行实现。上面的例子基于idea插件的自动生成,同时为我们生成了基本的增删改查语句

那么我们是使用当下大火的注解还是使用传统的配置文件方法呢?
当然是两者都用啊!

  • 保留原有的mapperScan注解,Spring容器会继续扫描mybatis的注解
  • 对mybatis的核心对象SQLSessionFactory进行配置
    @Bean
    public SqlSessionFactoryBean createSqlSessionFactory(@Autowired DataSource dataSource) throws IOException {
        SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
        sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath:/mapper/*.xml"));
        sqlSessionFactory.setDataSource(dataSource);
        return sqlSessionFactory;
    }

也就是说加一句代码就可以了

sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(“classpath:/mapper/*.xml”));

动态SQl

动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。

使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach
if

使用动态 SQL 最常见情景是根据条件包含 where 子句的一部分。比如:

<select id="findActiveBlogWithTitleLike"
     resultType="Blog">
  SELECT * FROM BLOG
  WHERE state = ‘ACTIVE’
  <if test="title != null">
    AND title like #{title}
  </if>
</select>

这条语句提供了可选的查找文本功能。如果不传入 “title”,那么所有处于 “ACTIVE” 状态的 BLOG 都会返回;如果传入了 “title” 参数,那么就会对 “title” 一列进行模糊查找并返回对应的 BLOG 结果(细心的读者可能会发现,“title” 的参数值需要包含查找掩码或通配符字符)。

如果希望通过 “title” 和 “author” 两个参数进行可选搜索该怎么办呢?首先,我想先将语句名称修改成更名副其实的名称;接下来,只需要加入另一个条件即可。

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG WHERE state = ‘ACTIVE’
  <if test="title != null">
    AND title like #{title}
  </if>
  <if test="author != null and author.name != null">
    AND author_name like #{author.name}
  </if>
</select>
choose、when、otherwise

有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

还是上面的例子,但是策略变为:传入了 “title” 就按 “title” 查找,传入了 “author” 就按 “author” 查找的情形。若两者都没有传入,就返回标记为 featured 的 BLOG(这可能是管理员认为,与其返回大量的无意义随机 Blog,还不如返回一些由管理员挑选的 Blog)。

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG WHERE state = ‘ACTIVE’
  <choose>
    <when test="title != null">
      AND title like #{title}
    </when>
    <when test="author != null and author.name != null">
      AND author_name like #{author.name}
    </when>
    <otherwise>
      AND featured = 1
    </otherwise>
  </choose>
</select>
trim、where、set

前面几个例子已经合宜地解决了一个臭名昭著的动态 SQL 问题。现在回到之前的 “if” 示例,这次我们将 “state = ‘ACTIVE’” 设置成动态条件,看看会发生什么。

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG
  WHERE
  <if test="state != null">
    state = #{state}
  </if>
  <if test="title != null">
    AND title like #{title}
  </if>
  <if test="author != null and author.name != null">
    AND author_name like #{author.name}
  </if>
</select>

如果没有匹配的条件会怎么样?最终这条 SQL 会变成这样:

SELECT * FROM BLOG
WHERE

这会导致查询失败。如果匹配的只是第二个条件又会怎样?这条 SQL 会是这样:

SELECT * FROM BLOG
WHERE
AND title like ‘someTitle’

这个查询也会失败。这个问题不能简单地用条件元素来解决。这个问题是如此的难以解决,以至于解决过的人不会再想碰到这种问题。

MyBatis 有一个简单且适合大多数场景的解决办法。而在其他场景中,可以对其进行自定义以符合需求。而这,只需要一处简单的改动:

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG
  <where>
    <if test="state != null">
         state = #{state}
    </if>
    <if test="title != null">
        AND title like #{title}
    </if>
    <if test="author != null and author.name != null">
        AND author_name like #{author.name}
    </if>
  </where>
</select>

where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。

如果 where 元素与你期望的不太一样,你也可以通过自定义 trim 元素来定制 where 元素的功能。比如,和 where 元素等价的自定义 trim 元素为:

<trim prefix="WHERE" prefixOverrides="AND |OR ">
  ...
</trim>

prefixOverrides 属性会忽略通过管道符分隔的文本序列(注意此例中的空格是必要的)。上述例子会移除所有 prefixOverrides 属性中指定的内容,并且插入 prefix 属性中指定的内容。

用于动态更新语句的类似解决方案叫做 setset 元素可以用于动态包含需要更新的列,忽略其它不更新的列。比如:

<update id="updateAuthorIfNecessary">
  update Author
    <set>
      <if test="username != null">username=#{username},</if>
      <if test="password != null">password=#{password},</if>
      <if test="email != null">email=#{email},</if>
      <if test="bio != null">bio=#{bio}</if>
    </set>
  where id=#{id}
</update>


set user=#{user},pwd=#{pwd}    (1,23,45)
<trim prefix="(" suffixOverrides="," suffix=")">
</trim>
<trim prefix="set" suffixOverrides=",">
    <if test="user!=null"> 
    	user = #{user}
    </if>
      <if test="pwd!=null"> 
    	pwd = #{pwd}
    </if>
</trim>

这个例子中,set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)。

来看看与 set 元素等价的自定义 trim 元素吧:

<trim prefix="SET" suffixOverrides=",">
  ...
</trim>

注意,我们覆盖了后缀值设置,并且自定义了前缀值。

foreach

动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)。比如:

<select id="selectPostIn" resultType="domain.blog.Post">
  SELECT *
  FROM POST P
  WHERE ID in
  <foreach item="item" index="index" collection="list"
      open="(" separator="," close=")">
        #{item}
  </foreach>
</select>

foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。

提示 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。

关于ORM

ORM一般称为对象关系映射,将数据库中的关系转移到JavaBean,在表与表的关系中,大多数情况下都是多对一/一对多关系,多对多,像这种关系我们可以使用外键来建立联系,且永远由多方来维护关系

假如有图书类Book,图书类型类Category,在数据库中图书与图书类型是多对一的关系(一般由多的一方来维护两方的关系);那么在Java里 我们在Book类中加一个Category属性。即:

package com.softeem.entity;

import java.io.Serializable;

/**
 * book
 * @author
 */
public class Book implements Serializable {
    private Integer id;

    private String cover;

    private Category category;

    public Category getCategory() {
        return category;
    }

    public void setCategory(Category category) {
        this.category = category;
    }

    private String title;

    private String author;

    private String date;

    private String press;

    private String abs;

    private Integer cid;

    private static final long serialVersionUID = 1L;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getCover() {
        return cover;
    }

    public void setCover(String cover) {
        this.cover = cover;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public String getPress() {
        return press;
    }

    public void setPress(String press) {
        this.press = press;
    }

    public String getAbs() {
        return abs;
    }

    public void setAbs(String abs) {
        this.abs = abs;
    }

    public Integer getCid() {
        return cid;
    }

    public void setCid(Integer cid) {
        this.cid = cid;
    }
}

在mapper下的BookDao.xml中,添加

<association property="category" javaType="com.softeem.entity.Category">
      <id column="id" jdbcType="INTEGER" property="id" />
      <result column="name" jdbcType="VARCHAR" property="name" />
    </association>

注意是在图书的内部添加
即我们在查询图书的同时 查询了category对象(图书类型)
当然如果数据库里属性名一样的话会产出冲突,即查询数据只有一条,且相同属性名查询的值会变成一样。所以我们会将相同的属性名取别名来查询,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值