MyBatis配置与映射

Scroll Down
MyBatis


配置yml
mapper-locations: classpath:/mapper/Mapper.xml
#实体扫描,多个package用逗号或者分号分隔
typeAliasesPackage: com.lhc.bigdata.fh.model
--
mybatis.mapperLocations: classpath:mapper/*Mapper.xml
  #configuration.log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#logging.level.com.spring.jiminshiro.mapper: debug

扫描XML文件
1、启动类上加@MapperScan("com.lhc.bigdata.fh.dao") 
   配置扫描属性, 用于手动扫描, 可以设置扫描包, 扫描注解等信息
@SpringBootApplication
@MapperScan("com.lhc.bigdata.fh.dao")
@EnableFeignClients(basePackages = {"com.lhc"})
@EnableDiscoveryClient
public class FileHub {
    public static void main(String[] args) {
        SpringApplication.run(FileHub.class, args);
    }
}

如果mapper类没有在Spring Boot主程序可以扫描的包或者子包下面,可以使用如下方式进行配置:  
@SpringBootApplication
@MapperScan({"com.kfit..mapper","org.kfit..mapper"})
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}
--
@MapperScan("com.demo.mapper"):扫描指定包中的接口
@MapperScan("com.demo..mapper"):一个   代表一级包;比如可以扫到com.demo.aaa.mapper,不能扫到com.demo.aaa.bbb.mapper
@MapperScan("com.demo..mapper"):两个 * 代表任意个包;比如可以扫到com.demo.aaa.mapper,也可以扫到com.demo.aaa.bbb.mapper
--
@ComponentScan是组件扫描注解,用来扫描@Controller  @Service  @Repository这类,主要就是定义扫描的路径从中找出标志了需要装配的类到Spring容器中其次,@MapperScan 是扫描mapper类的注解,就不用在每个mapper类上加@Mapper

2、或者mapper类上加@Mapper // 此注解是 Mybatis 自动配置时, 默认扫描的注解类
@Repository
@Mapper
public interface JobMapper {
  int transferJob(@Param("jobIdList") List<Integer> jobIdList,
                  @Param("newUser") String newUser);

}

问题
如果@MapperScan 默认扫描了全部, @SpringBoot 也扫描全部, 那么这里面的对象是MapperFactoryBean 还是真正的对象?
一个为@Service 扫描, 一个为MybatisScan 扫描注入的 MapperFactoryBean

Mybatis架构Image.png


mybati的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.bx.meta.mapper.JobMapper"> # 指定命名空间 xml 对应的实体 类

    <resultMap id="BaseResultMap" type="com.bx.triangle.entity.Job">
      # resultMap  实体类与数据库字段进行映射
        <id column="id" property="id" jdbcType="INTEGER"/>
        <result column="run_script" property="runScript" jdbcType="VARCHAR"/>
        <result column="run_frequency" property="runFrequency" jdbcType="INTEGER"/>
        <result column="trigger_time" property="triggerTime" jdbcType="TIMESTAMP"/>
    </resultMap>

  # 通过include进行sql复用 
    <sql id="Base_Column_List">
        id, name, description, location, run_script, status, trigger_mode, dependency_id, time_type, run_frequency,
        trigger_time, stream_id, user_name, belong_type, failed_retries, email_list, running_timeout,
        last_start_time, last_end_time,create_time, update_time, run_engine, parameter, expired_time, custom_script,
        proxy_user, is_first, batch_num, file_source
    </sql>
</mapper>


resultMap结果映射集详解Image.png


id,result 语句属性配置细节Image.png

JDBC Type          Java Type
CHAR                String
VARCHAR             String
LONGVARCHAR         String
NUMERIC             java.math.BigDecimal
DECIMAL             java.math.BigDecimal
BIT                boolean
BOOLEAN             boolean
TINYINT             byte
SMALLINT            short
INTEGER             int
BIGINT              long
REAL                float
FLOAT               double
DOUBLE              double
BINARY              byte[]
VARBINARY           byte[]
LONGVARBINARY       byte[]
DATE                java.sql.Date
TIME                java.sql.Time
TIMESTAMP           java.sql.Timestamp
CLOB                Clob
BLOB                Blob
ARRAY               Array
DISTINCT            mapping of underlying type
STRUCT              Struct
REF                 Ref
DATALINK            java.net.URL[color=red][/color]



CONSTRUCTOR 构造器
       在resultMap中,通常使用id、result子元素把Java实体类的属性映射到数据库表的字段上。但是如果在遇到JavaBean没有无参构造函数时,我还需要使用构造器元素实现一个JavaBean的实例化和数据注入。
<constructor>
     <idArg column="user_id" javaType="long"/> 
     <arg column="name" javaType="String"/> 
</constructor>
     定义java实体类的属性映射到数据库表的字段上。我们也可以使用实体类的构造方法来实现值的映射,这是通过构造方法参数的书写的顺序来进行赋值的。这样MyBatis就知道需要用这个构造方法构造了。


结果集的处理方法:
1. 使用map储存结果集
一般情况下,所有select语句都可以使用map储存,但是使用map就意味着可读性的下降,所以这不是推荐的方式。
<select id="findUserById" parameterType="long" resultType="map">
     select user_id ,name form user where user_id=#
</select>
2. 使用POJO储存结果集(推荐
一般我们都使用POJO储存查询结果。我们可以使用select自动映射,还可以使用select语句中的resultMap属性配置映射集合,不过需要提前定义resultMap。
<select id="findUserById" parameterType="long" resultMap="userMap">
        select user_id ,name form user where user_id=#
</select>
resultType 与 resultMap的区别
基本映射 :(resultType)使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。(数据库,实体,查询字段,,这些全部都得一一对应)
高级映射 :(resultMap) 如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。(高级映射,字段名称可以不一致,通过映射来实现)
一、resultType
使用resultType进行输出映射,只有查询出来的列名和pojo(实体bean)中的属性名一致,该列才可以映射成功。
如果查询出来的列名和pojo中的属性名全部不一致,没有创建pojo对象。
只要查询出来的列名和pojo中的属性有一个一致,就会创建pojo对象。


级联操作
 一对一
@Data
@Alias("card")
public class Card {
    private Long id;
    private Long userId;
    private String name;
    private String address;
}
————————————————
@Data
@Alias("user")
public class User {
private Long id;
private String username;
private String password;
private String email;
private Card card;
mybatis配置别名的方式可以在配置文件中包扫描,也可以使用@Alias注解
# 定义单个别名
<typeAliases>
  <typeAlias alias="User" type="cn.lxc.vo.User" />
</typeAliases>
# 包扫描
<typeAliases>
  <package name="cn.lxc.vo" />
</typeAliases>
# 注解开发
@Alias


CardMapper
<?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.changzhen.mybatis.mapper.CardMapper">
    <resultMap id="cardMap" type="card">
        <id property="id" column="id"></id>
        <result property="userId" column="user_id"/>
        <result property="name" column="name"/>
        <result property="address" column="address"/>
    </resultMap>
    <select id="findCardByUserId" parameterType="long" resultMap="cardMap">
           SELECT id, user_id, name, address FROM card WHERE user_id = #
  </select>
</mapper>
    

                     
UserMapper
<?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.changzhen.mybatis.mapper.UserMapper">
<select id="getUser" resultMap="userMap" parameterType="long">
    SELECT id,username,password,email FROM USER WHERE id=#
</select>
<resultMap id="userMap" type="user">
    <id property="id" column="id"/>
    <result property="password" column="password"/>
    <result property="email" column="email"/>
    <association property="card" column="id"  select="com.changzhen.mybatis.mapper.CardMapper.findCardByUserId"/>
</resultMap>
---
  通过关联处理,其中select元素指定的sql查询,而column则是指定传递给select的参数,是user对象id。当取出User的时候,MyBatis就知道下面的sql取出我们需要的级联信息。

一对多 Collection
这一对多的级联,一个身份证可以办理多张银行卡。每个用户对应一个身份证,每个身份证对应多个银行卡。所以这两个级联,分别使用association和collection完成。
@Alias("bankCard")  //银行卡
@Data
public class BankCard {
    private Long id;
    private Long userId;
    private String bankName;
    private int type;
}
-----------------------------------
@Data               //身份证   user对应一个card,一个card对应多个bankCard
@Alias("card")
public class Card {
    private Long id;
    private Long userId;
    private String name;
    private String address;
    private List<BankCard> bankCards;
}
BankCardMapper
@Mapper
public interface BankCardMapper {
    public List findCreditCardsByUserId(Long userId);
}

------------------------------------------------------
<?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.changzhen.mybatis.mapper.CreditCardMapper">
        <select id="findCreditCardsByUserId" parameterType="long" resultType="creditCard">
            SELECT id, user_id, bank_name, type FROM bank_card WHERE user_id = #
        </select>
    </mapper>
--------------------------------------------------------------------------------------------
#一对多级联
<mapper namespace="com.changzhen.mybatis.mapper.CardMapper">
    <resultMap id="cardMap" type="card">
        <id property="id" column="id"></id>
        <result property="userId" column="user_id"/>
        <result property="name" column="name"/>
        <result property="address" column="address"/>
        <collection property="creditCards" column="id"         select="com.changzhen.mybatis.mapper.BankCardMapper.findBankCardsByUserId"/>
    </resultMap>

    <select id="findCardByUserId" parameterType="long" resultMap="cardMap">
        SELECT id, user_id, name, address FROM card WHERE user_id = #
    </select>
</mapper>


    
discriminator 鉴别器级联
     鉴别器级联是在不同情况下使用不同的POJO。例如,在本例中我们每个人都有好多银行卡,但是银行卡的种类却不同,比如有借记卡(DebitCard)和信用卡(CreditCard),我们需要按需来创建不同的POJO。这时我们就需要在BankCard中添加types属性进行判断,确定使用哪个POJO。
接下来需要创建DebitCard和CreditCard两个继承BankCard的子类
@Data
public class CreditCard extends BankCard {
/
      消费额度
     /
    private String creditLine;
}
@Data
public class DebitCard extends BankCard {
    /**
     * 存款金额
     */
    private String deposit;
}
    通过BankCard中types的属性判断使用哪种银行卡,例如types等于1为借记卡,等于2为信用卡。接下来需要修改bankCard.xml,添加discriminator鉴别器,它相当于java中的switch语句。
bankCard.xml修改为如下:
<mapper namespace="com.changzhen.mybatis.mapper.BankCardMapper">
<resultMap id="bankCardMapper" type="bankCard">
    <id property="id" column="id"/>
    <result property="userId" column="user_id"/>
    <result property="bankName" column="bank_name"/>
    <result property="types" column="types"/>
    <discriminator javaType="int" column="types">
        <case value="1" resultMap="debitCardMapper"></case>
        <case value="2" resultMap="creditCardMapper"></case>
    </discriminator>
</resultMap>

<select id="findBankCardsByUserId" parameterType="long" resultMap="bankCardMapper">
    SELECT id, user_id, bank_name, types FROM bank_card WHERE user_id = #
</select>

<resultMap id="debitCardMapper" type="debitCard" extends="bankCardMapper"/>

<resultMap id="creditCardMapper" type="creditCard" extends="bankCardMapper"/>
-----------------------------------------------------------
  <discriminator javaType="int" column="types">
        <case value="1" resultMap="debitCardMapper"></case>
        <case value="2" resultMap="creditCardMapper"></case>
  </discriminator>

首先定义了 discriminator ,它对应的column为types,java类型(jdbcType)为int。case配置了不同的resultMap,如value=1时,引入debitCardMapper,value=2时,引入creditCardMapper他们都扩展了bankCardMapper。就像继承关系一样,resultMap也可以继承,加入自己的属性。借记卡添加deposit属性,信用卡添加creditLine属性。


多对多
<collection property="children"
            ofType="com.lhc.bigdata.fh.model.FileInfo"
            column="{id=id,systemCode=system_code}"
            select="getAllChildren">
</collection>
ofType全限定类名


 









]]>20201119T123906Z20201119T124656Z2451308995@qq.comdesktop.winabout:blankyinxiang.win32