service层的作业+mybatis中的重要组件

一.JavaWeb中service层的作用

MVC = Jsp + Servlet + JavaBean
其中jsp View,servlet Controller,javaBean 是一个可复用的java对象。

BS项目
客户端发送请求 controller service dao
如果是CS项目
客户有一个界面【操作】 service dao
以上分析,BS 与 CS 的 service和dao都是一样的,这样分层,代码复用,而且容易多人协作开发。

DAO:最听话的,让你**增删改**你就增删改。没有情感,没有思想。
Controller:控制层,接收客户端请求的,客户端只能请求到servlet,不能请求到service,dao,其他
的java类。Controller的作用就是**接收客户端请求,调用其他java类**。

如果要删除一个账号,谁去组织代码的逻辑呢?
这一层就是业务逻辑层,简称Service 层。
举例理解Service层
ATM机器上,你插入银行卡要给 小红 转账,1 元
【界面】
	转账
		进入转账界面
			输入对方的卡号
			输入转账金额
		确认按钮
【controller】可以一键生成的
	获取对方卡号,获取转账金额
	获取当前登录用户(session会话跟踪)
【service】需要程序员根据业务需求自行编写,设计规则
	//jdbc事务
	public void transfer(String fromNo,String toNo,int money){
        //判断
        对方卡号存不存在
        对方卡的状态对不对
        你的余额够不够
        updateMoney(toNo,1);
        //停电了....
        updateMoney(fromNo,-1);
        给你发短信
        给对方发短信
        给你的微信公众号发消息
        添加转账记录.....
    }
【dao】可以一键生成的
	public void updateMoney(String cardNo,int money);

举例2

注册账号:
【界面】
	填写你的账号
	输入两次密码
	手机验证码可选的(越来越多,短信不能随便发了)
【controller】 servlet(springMVC)
    try{
        接收数据 String
        数据封装,数据类型转换,封装为实体对象
        调用--》service
        显示结果-->请求转发/重定向到页面 或者 输出的是json
    }catch(Exception e){
        //对异常进行显示即可
        String msg = e.getMessage();
        request.setAttribute("msg",msg);
        //请求转发到注册jsp,jsp ${msg}
        //如果前端是ajax
        //response.getWrite().print("{result:false,msg:“+msg+”}");
    }
【service】业务逻辑
public void register(Account account){
    //判断,非空判断,长度判断,密码安全性判断【前端不是有js判断,前端判断对程序员无效】
    throw new RuntimeException("密码长度不足6位");
    //两次密码一致性判断
    throw new RuntimeException("两次密码不一致");
    //用户名or手机号是否被注册判断....
    //密码进行加密储存--> MD5【前端传输数据的时候就已经进行MD5的加密了】
    //调用dao保存数据
    //日志,xxx 什么 时间 xxx 注册了,什么 ip
    //发送短信
}
【dao】
    public Account queryByName(String name){}
    public void save(Account account){}

二.MyBatis重要组件

小结mybatis开发步骤:

增加mybatis的依赖,mysql jar 的依赖

编写mybatis-config.xml 核心配置文件【是mybatis运行的基础,mybatis所有的组件都是基于配置文
件运行的】

编写model,实体类,编写mapper.xml映射文件【就是编写sql代码,达到sql和java代码分离以便于容
易的维护sql。以及提高sql的复用】

使用mybatis提供的API,对数据库进行操作【接口,类很多】

1.Resources类

将文件读取为文件输入流。

注意事项:

// "mybatis-config.xml" 从当前类所在的包查找文件
// "/mybatis-config.xml" 从classes根目录下寻找

Resources类
将文件读取为 文件输入流
// "mybatis-config.xml" 从当前类所在的包查找文件
// "/mybatis-config.xml" 从classes根目录下寻找
InputStream resourceAsStream1 =
AccountMapperTest.class.getClass().getResourceAsStream("mybatis-config.xml");
System.out.println(resourceAsStream1);
//从classes根目录查找文件
//建议使用
InputStream resourceAsStream2 =
AccountMapperTest.class.getClassLoader().getResourceAsStream("mybatisconfig.xml");
System.out.println(resourceAsStream2);
//读取核心配置文件
InputStream resourceAsStream = Resources.getResourceAsStream("mybatisconfig.xml");

反射方式读取文件

(1)、AppClass.class.getClassLoader().getResourceAsStream("file")

从类路径classpath,也就是classes根目录下读取文件。[推荐]

//1、读取核心配置文件
//InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
InputStream in = AccountMapperTest.class.getClassLoader().getResourceAsStream("mybatis-config.xml");
//2、创建SqlSessionFactory
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);

(2)、AppClass.class.getResourceAsStream(file)

// "mybatis-config.xml" 从当前类所在的包查找文件
// "/mybatis-config.xml" 从classes根目录下寻找

//1、读取核心配置文件
//InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
//InputStream in = AccountMapperTest.class.getClassLoader().getResourceAsStream("mybatis-config.xml");
InputStream in = AccountMapperTest.class.getResourceAsStream("/mybatis-config.xml");
//2、创建SqlSessionFactory
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);

上述三种方式都可,在MyBatis中推荐使用Resources类。

2.api的生命周期

注意api的生命周期

(1) SqlSessionFactoryBuilder

SqlSessionFactoryBuilder
构建sqlsessionfactory
一旦构建了sqlsessionfactory builder的作用就达到了,
builder生命周期 就是方法范围

(2) SqlSessionFactory

SqlSessionFactory
接口
这是一个重量级的对象,他的作用是获取sqlsession,是一本工厂设计模式,应该被设计为系统唯一。
如何去实现呢?
单例模式
静态块初始化【简单】
public interface SqlSessionFactory {
	SqlSession openSession();//使用最多的
	SqlSession openSession(boolean autoCommit);
	SqlSession openSession(Connection connection);
	SqlSession openSession(TransactionIsolationLevel level);
	SqlSession openSession(ExecutorType execType);
	SqlSession openSession(ExecutorType execType, boolean autoCommit);
	SqlSession openSession(ExecutorType execType, TransactionIsolationLevel
		level);
	SqlSession openSession(ExecutorType execType, Connection connection);
	Configuration getConfiguration();
}

(3) SqlSession

SqlSession
sql session
和数据库的一次会话,本质 connection+statement 。。PS
生命周期应该是方法内的,不能放在全局,类的属性都不行,而且特别还要注意用完即关闭,必须要关
闭,否则连接资源耗尽


每个线程都应该有它自己的 SqlSession 实例。

SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。

绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。 也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中,比如 Servlet 框架中的 HttpSession。

如果你现在正在使用一种 Web 框架,考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中。 换句话说,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它。 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。 下面的示例就是一个确保 SqlSession 关闭的标准模式:
try (SqlSession session = sqlSessionFactory.openSession()) {
  // 你的应用逻辑代码
}

在所有代码中都遵循这种使用模式,可以保证所有数据库资源都能被正确地关闭。

3.代码的改进

针对上面的点,对上次的代码进行改进

通过对mybaits提供的编程接口声明周期的理解,可以更好的组织程序代码。

package com.oracle.util;


import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;


/**
 * 编写mybatis的工具类,工具类最核心的就是为程序中各个mapper
 * 提供 sqlsession ,因为mapper要和 xml 打交道,打交道进行crud操作
 * 都是使用的sqlsession 提供的方法
 * <p>
 * 如何保证sqlsessionfactory是系统唯一呢?
 * 所谓单例 整个应用中,仅有一个类的实例存在
 */
public class MybatisUtil {
    //私有化构造
    private MybatisUtil() {
    }

    //避免线程的不可见行
    private volatile static SqlSessionFactory sqlSessionFactory;

    public static SqlSessionFactory getSqlSessionFactory() {
        //双重锁
        if (sqlSessionFactory == null) {

            synchronized (MybatisUtil.class) {
                if (sqlSessionFactory == null) {
                    try {
                        //在这里初始化即可
                        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
                        sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);

                    } catch (Exception e) {
                        System.err.println("初始化sqlsessionfactory异常:" + e.getMessage());
                        System.exit(0);
                    }
                }
            }
        }
        return sqlSessionFactory;

    }
}

现阶段mapper【以前的dao】代码编写

package com.oracle.mapper;

import com.oracle.model.Account;
import com.oracle.util.MybatisUtil;
import org.apache.ibatis.session.SqlSession;


import java.util.List;

public class AccountMapper {
    public List<Account> selectAll(){
        SqlSession sqlSession = MybatisUtil.getSqlSessionFactory().openSession();
        try {
            //查询多个用selectList,查询一个用selectOne
            return sqlSession.selectList("com.oracle.mapper.AccountMapper.selectAll");
        }finally {
            sqlSession.close();
        }
    }

    public Account selectById(Integer aid){
        SqlSession sqlSession = MybatisUtil.getSqlSessionFactory().openSession();
        try {
            return sqlSession.selectOne("com.oracle.mapper.AccountMapper.selectById",aid);
        }finally {
            sqlSession.close();
        }
    }

    public void insert(Account account){
        SqlSession sqlSession = MybatisUtil.getSqlSessionFactory().openSession();
        try {
            sqlSession.insert("com.oracle.mapper.AccountMapper.insert",account);
        }finally {
            sqlSession.close();
            sqlSession.commit();
        }
    }

    public void update(Account account) {
        SqlSession sqlSession = MybatisUtil.getSqlSessionFactory().openSession();
        try {
            sqlSession.update("com.oracle.mapper.AccountMapper.update",account);
            sqlSession.commit();
        }finally {
            sqlSession.close();
        }
    }

    public void delete(Integer aid) {
        SqlSession sqlSession = MybatisUtil.getSqlSessionFactory().openSession();
        try {
            sqlSession.update("com.oracle.mapper.AccountMapper.delete",aid);
            sqlSession.commit();
        }finally {
            sqlSession.close();
        }

    }

}

AccountMapper.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 命名空间,程序中通过 sql映射的唯一标识获取 sql,比如当前文件有一个 insert sql标识,但是
其他文件中也有一个insert sql标识,就无法区分了,所以不同的sql功能,操作,使用namespce进行区分-->
<!--建议namaspce的值 为 包名.文件名-->
<mapper namespace="com.oracle.mapper.AccountMapper">
    <!--查询  -->
    <!--sql代码-->
    <!--mybatis中提供了四个最基础的sql标签,增删改查-->
    <!--id是程序中获取sql的标识,完整的标识是 namespace.sqlID-->
    <!--resultType 结果返回类型-->
    <select id="selectAll" resultType="com.oracle.model.Account">

        select aid,aname,apassword,a_nickname as anikename from account
    </select>

    <!--通过id查询,#{} 占位符,程序会自动根据参数的类型,选择是否增加 '' -->
    <select id="selectById" resultType="com.oracle.model.Account">
        select aid,aname,apassword,a_nickname as anikename from account where aid=#{aid}
    </select>

    <!--下面的insert语句中 #{} 中写的是对象的属性-->
    <!--下面的insert语句中 #{} 中写的是对象的属性-->
   <insert id="insert">
       insert
       into
       account(aname,apassword,a_nickname)
       values(#{aname},#{apassword},#{anikename})
   </insert>

    <update id="update">
        update account
        set aname = #{aname}, apassword = #{apassword}, a_nickname = #{anickname}
        where aid = #{aid}
    </update>

    <delete id="delete">
        delete from account
        where aid = #{aid}
    </delete>


</mapper>

AccountMapperTest.java

package com.oracle.mapper;

import com.oracle.model.Account;
import org.junit.Before;
import org.junit.Test;

import java.util.List;

public class AccountMapperTest4 {

    private AccountMapper accountMapper;

    @Before
    public void before() {
        accountMapper = new AccountMapper();
    }

    @Test
    public void selectAll(){
        List<Account> list = accountMapper.selectAll();
        System.out.println(list);
        /*
        *
        * [Account{aid=1, aname='zhangsan', apassword='123456', anikename='张三'}, Account{aid=2, aname='lisi', apassword='123456', anikename='李四'},
        * Account{aid=4, aname='wangwu', apassword='123456', anikename='王五'}]
        * */
    }

    @Test
    public void selectById(){
        Account account = accountMapper.selectById(1);
        System.out.println(account);
        //Account{aid=1, aname='zhangsan', apassword='123456', anikename='张三'}
    }

    @Test
    public void update(){
        Account account = new Account();
        account.setAid(5);
        account.setAname("wuhu");
        account.setApassword("123456");
        account.setAnickname("wuhuwuhu");
        accountMapper.update(account);
    }
    @Test
    public void insert(){
        Account account = new Account();
        account.setAname("aaa");
        account.setApassword("aaa");
        account.setAnickname("aaa");
        accountMapper.insert(account);
    }
    @Test
    public void delete(){

        accountMapper.delete(4);
    }
}

三.优化开发(日志别名配置文件)

mybatis-config.xml

1.配置properties

将数据库访问参数放在resources资源目录下的db.properties文件。

# 配置文件的key前面最好加上文件名
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql:///mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8
db.username=root
db.password=123456

在MyBatis核心配置文件中通过properties标签引入。mybatis-config.xml

<!--加载并读取配置文件-->
<!--resource 从classes目录下寻找配置文件-->
<!--属性文件中的值 使用 ${key}-->
<properties resource="db.properties"> </properties>

获取

<!--环境-->
<environments default="development">
    <environment id="development">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="${db.driver}"/>
            <property name="url" value="${db.url}"/>
            <property name="username" value="${db.username}"/>
            <property name="password" value="${db.password}"/>
        </dataSource>
    </environment>
</environments>

核心配置文件:

<?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 配置-->
<configuration>

    <!--加载并读取配置文件-->
    <!--resource 从classes目录下寻找配置文件-->
    <!--属性文件中的值 使用 ${key}-->
    <properties resource="db.properties"> </properties>

    <!--环境,很多环境,一个程序可能操作多个数据源(数据库),而且我们开发环境和本地测试环境也不一样-->
    <!--对于不同数据库的操作我们理解为环境-->
    <!--default就是程序默认使用的数据源-->
    <!--环境-->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${db.driver}"/>
                <property name="url" value="${db.url}"/>
                <property name="username" value="${db.username}"/>
                <property name="password" value="${db.password}"/>
            </dataSource>
        </environment>
    </environments>


    <!--加密mapper的映射文件-->
    <mappers>
        <!--mapper文件的全路径,注意使用/分隔-->
        <mapper resource="com/oracle/mapper/AccountMapper.xml"></mapper>
    </mappers>
    

</configuration>

2.别名

别名,在mapper.xml文件中,有一个xml的属性 resultType,它表示select标签执行后的java数据类
型。

<select id="selectAll" resultType="com.oracle.model.Account">
select
aid,aname,apass,a_nikename as anikename
from
account
</select>

所谓别名映射,就是指 com.oracle.model.Account 类的全称可以简写

<!--model别名设置-->
<typeAliases>
<!--type是类型 alias是别名-->
<!--在mapper.xml中 <select id="selectAll" resultType="account"> -->
<!--typeAlias不足是需要一一配置-->
<!--<typeAlias type="com.oracle.model.Account" alias="account"/>-->
<!--能不能对整个model包进行别名设置-->
<!--包下所有的类的别名都是类的名字,且不区分大小写-->
<package name="com.oracle.model"/>
</typeAliases>
<!--别名-->
<typeAliases>
    <!--单独一个类的别名映射-->
    <!--<typeAlias type="org.westos.model.Account" alias="account"/>-->
    <!--type是类型,alias是别名-->
    <!--不足之处在于需要逐一配置-->

    
    <!--对一个包下的所有类进行别名映射,别名都是类的名字,且不区分大小写-->
    <package name="com.oracle.model"/>
    
</typeAliases>

3.映射文件mapper

在mybatis-config.xml中加载了mapper.xml。

如果mapper.xml很多,引入不方便,后期会采用Mapper代理。

 <!--加载mapper映射文件-->
    <mappers>
        <!--mapper文件的全路径,注意使用/分割-->
        <mapper resource="com/oracle/mapper/AccountMapper.xml"/>
        <!--package包扫描,加载的是接口 (mapper代理开发模式)-->
        <!--<package name="com.oracle.model"/>-->
    </mappers>

4. #{}和${}区分

#{}和${}都表示参数的替换,不同之处在于:

#{},占位符,会根据参数的类型,自动选择是否增加单引号,本质就是利用了PreparedStatement;

${}只是替换,也就是说,你传递String字符串,也是直接替换,不会为你自动增加单引号;

${ }只是替换,也就是说,你传递 String类型,也直接替换
#{ }使用的多 ; ${}模糊查询,最大的缺点sql注入【 ' or 1=1 -- 】

a. #{ }

#{ }使用的是OGNL 表达式获取对象中的数据

<insert id="insert" >
    insert
    into
    account(aname,apassword,a_nikename)
    values
    (#{aname},#{apassword},#{anikename})
</insert>

public void insert(Account account) {
    try (SqlSession sqlSession = SqlSessionFactoryUtil.getSqlSessionFactory().openSession()) {
        sqlSession.insert("com.oracle.mapper.AccountMapper.insert", account);
        sqlSession.commit();
    }
}

以上两个代码结合,就是传递了Account对象,但是在sql运行的时候,获取到了对象的属性值,这种从
对象中获取属性值的方式,是通过OGNL对象图表达式语言完成的。

总结:#{}如果参数是非自定义对象,值可以随意填写;如果参数是自定义对象,那么值必须为属性。

#{}可以根据数据类型自动选择是否增加单引号。

5.${}

(1)

当参数是Integer时,#{aid}我们发现是能够获取值的

<select id="selectById" resultType="account">
    select aid, aname, apassword, a_nickname as anickname
    from account
    where aid = #{aid}
</select>

但是,${aid}会报错,

<select id="selectById" resultType="account">
    select aid, aname, apassword, a_nickname as anickname
    from account
    where aid = #{aid}
</select>
@Test
    public void selectById(){
        Account account = accountMapper.selectById(1);
        System.out.println(account);
        //Account{aid=1, aname='zhangsan', apassword='123456', anikename='张三'}
    }

错误:

### Error querying database.  Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'aid' in 'class java.lang.Integer'
### Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'aid' in 'class java.lang.Integer'

${ }对于int,Integer 数值类型,要求必须传递 v a l u e , 一 旦 识 别 {value} ,一旦识别 value,{value}就直接替换,不使用OGNL

如果参数是对象类型,${ 对象的属性 },还是通过OGNL运算给数值

这里是把Integer当做了自定义对象,寻找属性aid了,然后就会报找不到错误。

a i d 改 为 {aid}改为 aid{value}。

 <select id="selectById" resultType="account">
        select aid, aname, apassword, a_nickname as anickname
        from account
        where aid = ${value}
    </select>

与之类似的还有String类型参数。

如果参数是String类型,${aname}的情况下,把String当做了自定义对象,寻找aname属性;

org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'aname' in 'class java.lang.String'
### Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'aname' in 'class java.lang.String'

${ }只是替换

org.apache.ibatis.exceptions.PersistenceException:
### Error updating database. Cause: java.sql.SQLSyntaxErrorException: Unknown
column '李四' in 'field list'
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: insert into account(aname,apass,a_nikename)
values (李四,33,张三)
### Cause: java.sql.SQLSyntaxErrorException: Unknown column '李四' in 'field
list'

6.#{}

模糊查找使用#{}

如果参数是对象类型,${对象的属性},还是通过OGNL运算给数值。

但是,${对象的属性}只是替换,不会因为你是字符串就自动给你加上单引号。

ps:所以在传递对象作为参数时,选用#{}是最好的选择。

AccountMapper.xml

 <select id="selectByName" resultType="account">
        select aid, aname, apassword, a_nickname as anickname
        from account
        where aname like #{aname}
    </select>

AccountMapper.java

public List<Account> selectByName(String aname){
        SqlSession sqlSession = MybatisUtil.getSqlSessionFactory().openSession();
        try {
            return sqlSession.selectList("com.oracle.mapper.AccountMapper.selectByName",aname);

        }finally {
            sqlSession.commit();
            sqlSession.close();
        }
    }

测试方法

  @Test
    public void selectByName(){
        List<Account> list = accountMapper.selectByName("%zhang%");
        System.out.println(list);
    }

如果使用#{},那么在参数中必须把%设置好了。

[Account{aid=1, aname='zhangsan', apassword='123456', anickname='张三'}]

使用${}带来的问题

<select id="selectByName2" resultType="account">
    select aid, aname, apassword, a_nickname  as  anickname
    from account
    where aname like '%${value}%'
</select>

AccountMapper.java

//模糊查询
public List<Account> selectByName(String name) {
    try (SqlSession sqlSession = SqlSessionFactoryUtil.getSqlSessionFactory().openSession()) {
        return sqlSession.selectList("com.oracle.mapper.AccountMapper.selectByName2", name);
    }
}

测试:

@Test
public void selectByName() {
    List<Account> list = accountMapper.selectByName("zhang");
    System.out.println(list);
}

结果:

[Account(aid=1, aname=zhangsan, apassword=nasgnahz, anickname=张三)]

但是,${}存在SQL注入的风险,慎用。

@Test
public void selectByName() {
    List<Account> list = accountMapper.selectByName("a' or 1 = 1 -- ");
    System.out.println(list);
}

最终的SQL为:

SELECT * FROM account WHERE aname LIKE '%a' OR 1 = 1 -- %';

1后面的--为SQL语言的注释。

查询结果为数据库中的所有数据:

[Account(aid=1, aname=zhangsan, apassword=nasgnahz, anickname=张三), Account(aid=2, aname=lisi, apassword=isil, anickname=李四)]

总结:${}如果参数是非自定义对象,那么值只能为value;如果参数是自定义对象,那么值必须为属性;

${}存在Sql注入的风险;

${}不会根据数据类型自动增加单引号。

7.得到插入数据的主键值

得到插入数据的主键值
比如说qq号,注册qq号,可能qq号是数据库的主键值。
在比如插入类别和商品,注意一次性插入,插入类别后返回主键值

<!--下面的insert语句中 #{} 中写的是对象的属性-->
<!--useGeneratedKeys 使用插入后的主键值-->
<!--keyProperty将主键值映射到哪一属性上-->

    <!--主键自动获取前提是 数据库的主键生成方式 为 自动增长 mysql,sqlserver。oracle不是
    的-->
    <!--oracle怎么办? oracle主键生成策略? sequence 序列-->
    <!--mysql如何查询插入值得id,sql-->
    <insert id="insert" useGeneratedKeys="true" keyProperty="aid" >
    insert
    into
    account(aname,apass,a_nikename)
    values
    (#{aname},#{apass},#{anikename})
    </insert>

MyBatis支持插入数据并返回数据库中的主键值。

数据库的id值存在两种情况:

  • 数据库自动维护id的值

    • sqlserver
    • mysql
  • 另一种是序列sequence

    • oracle

      <!--像mysql、sqlserver,支持主键自动增长的数据库-->
      <!--useGeneratedKeys:使用插入后的主键值-->
      <!--keyProperty:将主键值映射到哪一属性上-->
      <insert id="insert" useGeneratedKeys="true" keyProperty="aid">
          insert into account(aname, apassword, a_nickname)
          values
          (#{aname}, #{apassword}, #{anickname})
      </insert>
      
      
@Test
public void insert() {
    Account account = new Account();
    account.setAname("wangwu");
    account.setApassword("uwgnaw");
    account.setAnickname("王五");
    accountMapper.insert(account);
    System.out.println(account.getAid());
    //3
}

last_insert_id()函数

<!--mysql还提供了一个函数last_insert_id(), 它必须紧跟插入语句,而且是插入语句先执行-->
<!--通过函数查询主键值,然后设置到属性中-->
<!--keyProperty:Java属性,order是指执行顺序在insert之前还是之后-->
<insert id="insert1">
    <selectKey keyProperty="aid" resultType="int" order="AFTER">
        select last_insert_id()
    </selectKey>
    insert into account(aname, apassword, a_nickname)
    values
    (#{aname}, #{apassword}, #{anickname})
</insert>

@Test
public void insert() {
    //2、插入一条记录
    Account account = new Account();
    account.setAname("john");
    account.setApassword("123456");
    account.setAnickname("jj");
    accountMapper.insert(account);
    System.out.println(account.getAid());
    //4
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot是一个用于构建独立的、基于生产的Spring应用程序的框架。它使开发人员能够更快速地构建和部署应用程序,通过提供诸如自动配置、嵌入式服务器和无需任何XML配置文件等特性来降低开发的复杂性。 MyBatis是一个持久层的框架,它可以与Spring Boot集成来提供数据库访问的功能。它通过将SQL语句从Java代码分离出来,从而实现了数据访问层的解耦,使开发人员可以更方便地进行数据库操作。 在Spring Boot使用MyBatis,可以通过在项目的pom.xml文件添加相应的依赖项来使用MyBatis,并在application.properties或application.yml文件配置数据库连接信息和MyBatis相关的配置。 在MyBatis的使用,可以通过编写Mapper接口和对应的Mapper XML文件来定义数据库操作的方法。MyBatis根据Mapper接口的方法名和Mapper XML文件的SQL语句进行映射,从而实现数据库操作的执行。 在Spring Boot,可以使用@Mapper注解将Mapper接口标识为MyBatis的Mapper组件,并通过@MapperScan注解扫描Mapper接口所在的包。这样就可以在Spring Boot的业务逻辑层使用注入Mapper接口的方式来进行数据库操作。 总结起来,Spring Boot和MyBatis可以很好地配合使用,通过Spring Boot的自动配置和简化的开发方式,以及MyBatis的灵活性和强大的数据库访问能力,可以更快速地开发出高效可靠的应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值