面试题 关于SelectKey

来源:互联网 发布:外汇收入 知乎 编辑:程序博客网 时间:2024/06/06 01:39

题目:

Xml映射文件中,除了常见的select|insert|updae|delete标签之外,还有哪些标签?

注:这道题是京东面试官面试我时问的。

答:还有很多其他的标签,<resultMap><sql><include><selectKey>,加上动态sql9个标签trim|where|set|foreach|if|choose|when|otherwise|bind等,其中<sql>sql片段标签,通过<include>标签引入sql片段,<selectKey>为不支持自增的主键生成策略标签。

 

 

讲解:

在使用MyBatis做持久层时,insert语句默认是不返回记录的主键值,而是返回插入的记录条数;如果业务层需要得到记录的主键时,可以通过配置SelectKey的方式来完成这个功能。SelectKeyMybatis中是为了解决Insert数据时不支持主键自动生成的问题,他可以很随意的设置生成主键的方式。

 

selectKey Attributes

属性

描述

keyProperty

selectKey 语句结果应该被设置的目标属性。

resultType

结果的类型。MyBatis通常可以算出来,但是写上也没有问题。MyBatis允许任何简单类型用作主键的类型,包括字符串。

order

这可以被设置为 BEFOREAFTER。如果设置为BEFORE,那么它会首先选择主键,设置keyProperty 然后执行插入语句。如果设置为AFTER,那么先执行插入语句,然后是selectKey 元素-这和如Oracle 数据库相似,可以在插入语句中嵌入序列调用。

statementType

和前面的相 同,MyBatis支持 STATEMENT ,PREPAREDCALLABLE语句的映射类型,分别代表PreparedStatement CallableStatement类型。

 

 

SelectKey需要注意order属性,像MySQL一类支持自动增长类型的数据库中,order需要设置为after才会取到正确的值。

 

步骤:

一:创建maven项目

Maven默认的Java版本是1.6,无法使用lambda表达式(1.8)和钻石运算符(1.7

 

代码片段:pom.xmlpom.xml中,添加mybatis依赖,mysql-jdbc依赖,把编译版本改为1.8
你问,为啥mybatis不会自动依赖mysql-jdbc,需要手动写明?答:因为mysql驱动是通过字符串动态加载的,这是一种“动态依赖”,Maven只能推导出“静态依赖”。“动态依赖”是一种更加灵活的依赖

 

 

<!--MyBatis核心jar-->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.2.2</version>
</dependency>

<!--MySQL配置-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.25</version>
</dependency>

 

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <encoding>utf8</encoding>
            </configuration>
        </plugin>
    </plugins>
</build>

 

 

最终的目录结构

 

 

 

二:配置MyBatis

代码片段:mybatis.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>
    <propertiesresource="config.properties">
    </properties>
    <environmentsdefault="development">
        <environmentid="development">
            <transactionManagertype="JDBC"/>
            <dataSourcetype="POOLED">
                <propertyname="driver"value="${driver}"/>
                <propertyname="url"value="${url}"/>
                <propertyname="username"value="${username}"/>
                <propertyname="password"value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapperclass="haha.UserDao"/>
        <mapperresource="user.xml"/>
    </mappers>
</configuration>

 

三:创建实体类User

User有三个属性:nameageid,重写toString()方法便于调试。

 

public class User {
    String name;
    Integer age;
    Integer id;

    public User(){}
public User(String name,intage){
    this.name=name;
    this.age=age;
}

 


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name= name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age= age;
    }

    public Integer getId() {
        return id;
    }

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

    @Override
    publicString toString() {
        return String.format("(id:%d,name:%s,age:%d)",id, name,age);
    }
}

 

相应的,在数据库中建立一个表user

CREATE TABLE `user` (

  `id` INT(11) NOT NULL AUTO_INCREMENT,

  `name` VARCHAR(10) DEFAULT NULL,

  `age` INT(11) DEFAULT NULL,

  PRIMARY KEY (`id`)

) ENGINE=INNODB AUTO_INCREMENT=119 DEFAULT CHARSET=utf8mb4

 

四:实现UserDao接口

UserDao接口有两个功能:插入、查询全部

 

public interface UserDAO {
    @Insert("insert into user(name,age) value (#{name},#{age})")
    int insert_withoutPrimaryKey(@Param("name") String name,@Param("age")int age);

    int insert_useGeneratedKey(@Param("user") User user);

    int insert_selectKey(@Param("user") User user);

    @Insert("insert into user(name,age) value(#{user.name},#{user.age})")
    @SelectKey(statement = "select last_insert_id()",keyProperty = "user.id",before = false,resultType =int.class)
    int insert_selectKeyAnotation(@Param("user") User user);

    @Select("select*from user")
    List<User> getAll();
}

 

MybatisSQL语句有两种方式:1、使用注解;2、使用xml
对于比较长的SQL语句放在xml中,对于比较短的SQL语句放在注解中

在上面定义的UserDao中,insert_userGeneratedKey()insert_selectKey()两个函数没有给出对应的SQL语句,需要在xml文件中进行定义。

 

代码片段:user.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">
<mappernamespace="haha.UserDao">
    <insertid="insert_useGeneratedKey"parameterType="haha.User"
            useGeneratedKeys="true"keyProperty="user.id"
>
        insert into user set id=#{user.id},name=#{user.name},age=#{user.age}
    </insert>
    <insertid="insert_selectKey"parameterType="haha.User">
        <selectKeykeyProperty="user.id"keyColumn="id"order="AFTER"resultType="int">
            SELECT last_insert_id()
        </selectKey>
        insert into user(name,age) VALUE (#{user.name},#{user.age})
    </insert>
</mapper>

 

五:测试

编写一个UserService类测试一下

 

package haha;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class UserService {

public static void main(String[] args)throws IOException {
    String resource = "mybatis.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    SqlSessionFactoryBuilder builder = newSqlSessionFactoryBuilder();
    SqlSessionFactory factory = builder.build(inputStream);
    SqlSession session = factory.openSession();
    UserDao dao = session.getMapper(UserDao.class);

    //使用默认主键
    
intaffectedRows = dao.insert_withoutPrimaryKey("张三",25);
    System.out.println(affectedRows);

    //使用useGeneratedKey,将主键注入到user.id
    
User u = newUser("李四",17);
    affectedRows = dao.insert_useGeneratedKey(u);
    System.out.println(affectedRows +" " + u.getId());

    //使用selectKey执行在插入之前或之后执行查询语句
    
affectedRows = dao.insert_selectKey(u);
    System.out.println(affectedRows +" " + u.getId());

    //使用selectKey注解的方式
    
affectedRows = dao.insert_selectKeyAnotation(u);
    System.out.println(affectedRows +" " + u.getId());
    session.commit();
    List<User> a = dao.getAll();
    a.forEach(System.out::println);
}
}

 

六:关于SelectKey

下面介绍一个重要注解

@SelctKey(statement="SQL语句",keyProperty="SQL语句查询结果存放到keyProperty中去",before="true表示先查询再插入,false反之",resultType=int.class)

 

· statement是要运行的SQL语句,它的返回值通过resultType来指定

· before表示查询语句statement运行的时机

· keyProperty表示查询结果赋值给代码中的哪个对象,keyColumn表示将查询结果赋值给数据库表中哪一列

· keyPropertykeyColumn都不是必需的,有没有都可以

· before=true,插入之前进行查询,可以将查询结果赋给keyPropertykeyColumn,赋给keyColumn相当于更改数据库

· befaore=false,先插入,再查询,这时只能将结果赋给keyProperty

· 赋值给keyProperty用来“读”数据库,赋值给keyColumn用来写数据库

· selectKey的两大作用:1、生成主键;2、获取刚刚插入数据的主键。

· 使用selectKey,并且使用MySQLlast_insert_id()函数时,before必为false,也就是说必须先插入然后执行last_insert_id()才能获得刚刚插入数据的ID

 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 共享打印机无法打印怎么办 网络权限被禁止怎么办 硬盘显示不出来怎么办 硬盘插上不显示怎么办 mac不能读取移动硬盘怎么办 mac系统坏了怎么办 ip地址网站打不开怎么办? 电脑页面偏了怎么办 wifi被禁止联网怎么办 oppo浏览器屏蔽网站怎么办 被网站禁言怎么办 网站被模仿了怎么办 公积金不允许提取还房贷怎么办 电脑超出频率限制怎么办 海带宝转运丢失怎么办 xp电脑证书过期怎么办 电脑qq重复登录怎么办 海带宝少东西怎么办 苹果手机照片打不开怎么办 旧电脑没有密码了怎么办 快手忘记登录账号怎么办 b站永久封禁怎么办 微博自动关注怎么办 微博会自动点赞怎么办 游戏名字被占用怎么办 闲鱼头像违规怎么办 请求状态码错误怎么办 微博错误20521怎么办 忘记申请的邮箱怎么办 填写简历忘记邮箱怎么办 雅虎邮箱忘记用户名怎么办 oppo手机忘记密码怎么办 设备昵称忘了怎么办 快手昵称被注册怎么办 app占用越来越大怎么办 淘宝昵称被占用怎么办 电脑开机时间不准怎么办 电脑的时间不对怎么办 做完运动饿了怎么办 qq被冻结七天怎么办 12306电话号码忘了怎么办