小黑子—MyBatis:第三章

news2024/11/14 4:12:22

MyBatis入门3.0

  • 七 小黑子使用javassist生成类
    • 7.1 Javassist的使用
    • 7.2 javassist生成动态类并实现接口
    • 7.3 工具类GenerateDaoProxy的编写
      • 7.3.1 每一个方法体的动态拼接
      • 7.3.2 MyBatis的getMapper方法
  • 八 MyBatis中接口代理机制及使用
    • 8.1 面向接口的方式进行CRUD
      • 8.1.1 步骤1
      • 8.1.2 步骤2
  • 九 小黑子的MyBatis小技巧
    • 9.1 #{} 和 $()
    • 9.2 拼接表名
    • 9.3 批量删除
    • 9.4 模糊查询
    • 9.5 别名标签 typeAliases
    • 9.6 mapper的配置
    • 9.7 IDEA配置模板文件
    • 9.8 插入数据时获取自动生成的主键

七 小黑子使用javassist生成类

javassist是一个开源的分析、编辑和创建java字节码类库。是由东京工业大学的数学和计算机科学系的Shigeru Chiba(千叶滋)所创建的。它已加入了开发源代码JBoss应用服务器项目,通过使用Javassist对字节码操作为JBoss实现动态"AOP"框架

7.1 Javassist的使用

  • 我们要使用javassist,首先要引入它的依赖
<dependency>
  <groupId>org.javassist</groupId>
  <artifactId>javassist</artifactId>
  <version>3.29.1-GA</version>
</dependency>
  • 样例代码:
package com.powernode.javassist;

import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import org.junit.Test;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class JavassistTest {
    @Test
    public void testGenerateFirstClass() throws CannotCompileException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        //获取类池,这个类池就是用来给我生成class的
        ClassPool pool = ClassPool.getDefault();
        //创造类(需要告诉javassist,类名是啥)
        CtClass ctClass = pool.makeClass("com.powernode.bank.dao.impl.AccountDapImpl");
        // 创造方法
        String methodCode = "public void insert(){System.out.println(123);}";
        CtMethod ctMethod = CtMethod.make(methodCode, ctClass);
        //将方法添加到类中
        ctClass.addMethod(ctMethod);
        //在内存中生成class
        ctClass.toClass();



        //类加载到JVM当中,返回AccountDaoImpl
        Class<?> clazz = Class.forName("com.powernode.bank.dao.impl.AccountDapImpl");

        //创建对象
        Object obj = clazz.newInstance();
        //获取AccountDaoImpl中的insert方法
        Method insertMethod = clazz.getDeclaredMethod("insert");
        //调用方法insert
        insertMethod.invoke(obj);
    }
}

在这里插入图片描述

运行要注意:在配置中加两个参数,要不然会有异常。

  • –add-opens java.base/java.lang=ALL-UNNAMED
  • –add-opens java.base/sun.net.util=ALL-UNNAMED
    在这里插入图片描述
    在这里插入图片描述

7.2 javassist生成动态类并实现接口

在这里插入图片描述

package com.powernode.javassist;

import com.powernode.bank.dao.AccountDao;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import org.junit.Test;

public class JavassistTest {


    @Test
    public void testGenerateImpl() throws Exception {
        //获取类池
        ClassPool pool = ClassPool.getDefault();
        //制作类
        CtClass ctClass = pool.makeClass("com.powernode.bank.dao.impl.AccountDapImpl");
        //制造接口
        CtClass ctInterface = pool.makeInterface("com.powernode.bank.dao.AccountDao");
        //添加接口到类中
        ctClass.addInterface(ctInterface);
        // 实现接口中的方法
        //制造方法
        CtMethod ctMethod = CtMethod.make("public void delete(){System.out.println(\"hello delete\");}", ctClass);

        //将方法添加到类中
        ctClass.addMethod(ctMethod);
        //在内存中生成类,同时将生成的类加载到JVM当中
        Class<?> clazz = ctClass.toClass();
        AccountDao accountDao = (AccountDao) clazz.newInstance();
        accountDao.delete();
    }
}

在这里插入图片描述

  • 实现接口中的所有方法
 @Test
    public void testGenerateAccountDaoImpl() throws Exception{
        // 获取类池
        ClassPool pool = ClassPool.getDefault();
        //制造类
        CtClass ctClass = pool.makeInterface("com.powernode.bank.dao.impl.AccountDapImpl");
        //制造接口
        CtClass ctInterface = pool.makeInterface("com.powernode.bank.dao.AccountDao");

        //实现接口
        ctClass.addInterface(ctInterface);
        //实现接口中所有的方法
        //获取接口中所有的方法
        Method[] methods  = AccountDao.class.getDeclaredMethods();
        Arrays.stream(methods).forEach(method -> {
            //method 是接口中的抽象方法
            try {
                // public void delete(){System.out.println(111);}
                StringBuilder methodCode = new StringBuilder();
                methodCode.append("public ");//追加修饰符列表
                methodCode.append(method.getReturnType().getName());//追加返回值类型
                methodCode.append(" ");
                methodCode.append(method.getName());
                methodCode.append("(");
                //添加参数
                Class<?>[] parameterTypes = method.getParameterTypes();
                for (int i = 0; i < parameterTypes.length; i++) {
                    Class<?> parameter =  parameterTypes[i];
                    methodCode.append(parameter.getName());
                    methodCode.append(" ");
                    methodCode.append("arg"+i);
                    if (i != parameterTypes.length-1){
                        methodCode.append(",");
                    }
                }
                methodCode.append("){System.out.println(11111);");
                //添加返回值
                String returnName = method.getReturnType().getSimpleName();//获取返回值类名的简类名
                if ("int".equals(returnName)){
                    methodCode.append("return 1;");
                } else if ("String".equals(returnName)) {
                    methodCode.append("return \"hello\";");
                }
                methodCode.append("}");
                CtMethod ctMethod = CtMethod.make(methodCode.toString(), ctClass);
                //将方法都加到类中
                ctClass.addMethod(ctMethod);
            } catch (CannotCompileException e) {
                e.printStackTrace();
            }
        });
        //在内存中生成类,同时生成的类加载到JVM当中
        Class<?> aClass = ctClass.toClass();
        AccountDao accountDao = (AccountDao)aClass.newInstance();
        //执行里面的方法
        accountDao.insert("aaaaa");
        accountDao.delete();
        accountDao.update("aaaa",1000.00);
        accountDao.selectByActno("aaaa");
}

7.3 工具类GenerateDaoProxy的编写

工具类GenerateDaoProxy能够动态地提供接口实现类

mybatis自己内置有javassist,mybatis号称轻量级的,只需要一个jar包就行

package com.powernode.bank.utils;

import org.apache.ibatis.javassist.ClassPool;
import org.apache.ibatis.javassist.CtClass;
import org.apache.ibatis.javassist.CtMethod;

import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * 工具类:可以动态地生成DAO的实现类(或者说可以动态生成DAO的代理类)
 * @author 小黑子
 * @version 1.0
*/
public class GenerateDaoProxy {
    /**
     * 生成dao接口实现类,并且将实现类的对象创建出来并返回
     * @param daoInterface dao接口
     * @version 1.0
    */
    public static Object generate(Class daoInterface){
        //类池
        ClassPool pool = ClassPool.getDefault();
        //制造类(com.powernode.bank.dao.AccountDao->com.powernode.bank.dao.impl.AccountDapImpl)
        final CtClass ctClass = pool.makeClass(daoInterface.getName()+"Proxy");
        //制造接口
        CtClass ctInterface = pool.makeInterface(daoInterface.getName());
        //实现接口中的所有方法
        Method[] methods = daoInterface.getDeclaredMethods();
        Arrays.stream(methods).forEach(method->{

            //method是抽象方法
            //将method这个抽象方法进行实现
            try {
                //public Account selectByActno(String arg0,int arg1,int arg2){代码;}
                StringBuilder methodCode = new StringBuilder();
                methodCode.append("public ");
                methodCode.append(method.getReturnType().getName());
                methodCode.append(" ");
                methodCode.append(method.getName());
                methodCode.append("(");
                //需要方法的形式参数列表
                Class<?>[] parameterTypes = method.getParameterTypes();
                for (int i = 0; i < parameterTypes.length; i++) {
                    Class<?> parameterType = parameterTypes[i];
                    methodCode.append(parameterType.getName());
                    methodCode.append(" ");
                    methodCode.append("arg"+i);
                    if(i!=parameterTypes.length-1){
                        methodCode.append(",");
                    }
                }
                methodCode.append(")");
                methodCode.append("{");
               
                //需要方法体的代码
                methodCode.append("}");
                CtMethod ctMethod = CtMethod.make(methodCode.toString(), ctClass);
                ctClass.addMethod(ctMethod);

            } catch (Exception e) {
                e.printStackTrace();
            }

        });


        //创建对象
        Object obj = null;
        try {
            Class<?> clazz = ctClass.toClass();
            obj = clazz.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }


        return null;
    }
}

7.3.1 每一个方法体的动态拼接

AccountDaoImpl的mybatis规范

package com.powernode.bank.dao.impl;

import com.powernode.bank.dao.AccountDao;
import com.powernode.bank.pojo.Account;
import com.powernode.bank.utils.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;

public class AccountDaoImpl implements AccountDao {
    @Override
    public Account selectByActno(String arg0) {
        SqlSession sqlSession = SqlSessionUtil.openSession();
//        Account account = (Account) sqlSession.selectOne("account.selectByActno",actno);
//        return account;
        return (Account) sqlSession.selectOne("account.selectByActno",arg0);
    }

    @Override
    public int updateByActno(Account arg0) {
        SqlSession sqlSession = SqlSessionUtil.openSession();
//        int count = sqlSession.update("account.updateActno", act);
//        return count;
        return sqlSession.update("account.updateActno", arg0);
    }

  • 动态拼接
package com.powernode.bank.utils;

import org.apache.ibatis.javassist.ClassPool;
import org.apache.ibatis.javassist.CtClass;
import org.apache.ibatis.javassist.CtMethod;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.session.SqlSession;

import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * 工具类:可以动态地生成DAO的实现类(或者说可以动态生成DAO的代理类)
 * @author 小黑子
 * @version 1.0
*/
public class GenerateDaoProxy {
    /**
     * 生成dao接口实现类,并且将实现类的对象创建出来并返回
     * @param daoInterface dao接口
     * @version 1.0
    */
    public static Object generate(SqlSession sqlSession, Class daoInterface){
        //类池
        ClassPool pool = ClassPool.getDefault();
        //制造类(com.powernode.bank.dao.AccountDao->com.powernode.bank.dao.impl.AccountDapImpl)
        final CtClass ctClass = pool.makeClass(daoInterface.getName()+"Proxy");
        //制造接口
        CtClass ctInterface = pool.makeInterface(daoInterface.getName());

        // 实现接口
        ctClass.addInterface(ctInterface);

        //实现接口中的所有方法
        Method[] methods = daoInterface.getDeclaredMethods();
        Arrays.stream(methods).forEach(method->{

            //method是抽象方法
            //将method这个抽象方法进行实现
            try {
                //public Account selectByActno(String arg0,int arg1,int arg2){代码;}
                StringBuilder methodCode = new StringBuilder();
                methodCode.append("public ");
                methodCode.append(method.getReturnType().getName());
                methodCode.append(" ");
                methodCode.append(method.getName());
                methodCode.append("(");
                //需要方法的形式参数列表
                Class<?>[] parameterTypes = method.getParameterTypes();
                for (int i = 0; i < parameterTypes.length; i++) {
                    Class<?> parameterType = parameterTypes[i];
                    methodCode.append(parameterType.getName());
                    methodCode.append(" ");
                    methodCode.append("arg"+i);
                    if(i!=parameterTypes.length-1){
                        methodCode.append(",");
                    }
                }
                methodCode.append(")");
                methodCode.append("{");
                //需要方法体的代码
                methodCode.append("org.apache.ibatis.session.SqlSession  sqlSession = com.powernode.bank.utils.SqlSessionUtil.openSession();");
                methodCode.append("sqlSession");
                //需要知道是什么类型的sql语句
                // sql语句的id是框架使用者提供的,具有多边性。对于我框架的开发人员来说。我不知道
                //既然我框架开发者不知道sqlId。怎么办?mybatsi框架的开发者于是就出台了一个规定:凡是使用GenerateDaoProxy机制的
                //sqlId都不能随便写。namespace必须是dao接口的全限定名称,id必须是dao接口中的方法名
                String sqlId = daoInterface.getName() + "," + method.getName();
                SqlCommandType sqlCommandType = sqlSession.getConfiguration().getMappedStatement(sqlId).getSqlCommandType();
                if(sqlCommandType == sqlCommandType.INSERT){

                }
                if(sqlCommandType == sqlCommandType.DELETE){

                }

                if(sqlCommandType == sqlCommandType.UPDATE){
                    methodCode.append(" return sqlSession.update(\""+sqlId+"\", arg0)");
                }

                if(sqlCommandType == sqlCommandType.SELECT){
                    String returnType = method.getReturnType().getName();
                    methodCode.append(" return (" +returnType+") sqlSession.selectOne(\""+sqlId+"\", arg0)");
                }


                methodCode.append("}");
                CtMethod ctMethod = CtMethod.make(methodCode.toString(), ctClass);
                ctClass.addMethod(ctMethod);

            } catch (Exception e) {
                e.printStackTrace();
            }

        });


        //创建对象
        Object obj = null;
        try {
            Class<?> clazz = ctClass.toClass();
            obj = clazz.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }


        return obj;
    }
}

7.3.2 MyBatis的getMapper方法

<?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">
<!--sqlMapper.xml文件的编写者,提供者是谁?使用你mybatis框架的java程序员负责提供的-->
<!--要想使用这种机制:namespace必须是dao接口的全限定名-->
<mapper namespace="account">
<!--    要使用这种机制,id必须是dao接口的方法名-->
    <select id="selectByActno" resultType="com.powernode.bank.pojo.Account">
        select * from t_act where actno = #{actno}
    </select>

    <update id="updateByActno">
        update t_act set balance = #{balance} where actno = #{actno}
    </update>
</mapper>

在mybatis当中。mybatis提供了相关的机制,也可以为动态为我们生成接口的实现类。(代理类:接口的代理)

mybatis当中实际上采用了代理模式,在内存中生成dao接口的代理类,然后创建代理类的实例

使用mybatis的这种代理机制的前提:

  • SqlMapper.xml文件中namespace必须是dao接口的全限定名称,id必须是dao接口中的方法名

怎么写?
AccountDao accountDao = SqlSessionUtil.openSession().getMapper(AccountDao.class);

八 MyBatis中接口代理机制及使用

其实以上所讲内容mybatis内部已经实现了。直接调用以下代码即可获取dao接口的代理类:

AccountDao accountDao = (AccountDao)sqlSession.getMapper(AccountDao.class);

使用以上代码的前提是:AccountMapper.xml文件中的namespace必须和dao接口的全限定名称一致,id必须和dao接口中方法名一致

8.1 面向接口的方式进行CRUD

8.1.1 步骤1

在这里插入图片描述
CarMapper接口:

package com.powernode.mybatis.mapper;

import com.powernode.mybatis.pojo.Car;

import java.util.List;

public interface CarMapper {
    /**
     * @description: 新增car
     * @return
    */
    int insert(Car car);

    /**
     * @description: 根据id删除car
     * @return
     */
    int deleteById(Long id);

    /**
     * @description: 根据id修改汽车信息
     * @return
     */
    int update(Car car);

    /**
     * @description: 获取单个的汽车信息
     * @return
     */
    Car selectById(Long id);

    /**
     * @description: 获取所有的汽车信息
     * @return
     */
    List<Car> selectAll();
}

资源下的CarMapper.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">
<!--namespace先随意写一个-->
<mapper namespace="com.powernode.mybatis.mapper.CarMapper">
    <insert id="insert">
        insert into t_car values(null,#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})
    </insert>

    <delete id="deleteById">
        delete from t_car where id =#{id}
    </delete>

    <update id="update">
        update t_car set
                    car_num = #{carNum},brand = #{brand}, guide_price = #{guidePrice},produce_time = #{produceTime},car_type = #{carType}
        where id = #{id}
    </update>

    <select id="selectById" resultType="com.powernode.mybatis.pojo.Car">
        select
               id,
               car_num as carNum,
               brand,
               guide_price as guidePrice,
               produce_time as produceTime,
               car_type as carType
        from t_car where id = #{id}
    </select>

    <select id="selectAll" resultType="com.powernode.mybatis.pojo.Car">
        select
            id,
            car_num as carNum,
            brand,
            guide_price as guidePrice,
            produce_time as produceTime,
            car_type as carType
        from t_car
    </select>

</mapper>

8.1.2 步骤2

测试代码:

package com.powernode.mybatis;

import com.powernode.mybatis.mapper.CarMapper;
import com.powernode.mybatis.pojo.Car;
import com.powernode.mybatis.utils.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

public class CarMapperTest {
    @Test
    public void testInsert(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        //面向接口获取接口的代理对象
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Car car = new Car(null, "8654", "麻瓜", 3.0, "2022-1-20", "新能源");
        int insert = mapper.insert(car);
        System.out.println(insert);
        sqlSession.commit();
        sqlSession.close();
    }

    @Test
    public void testDeleteById(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        int insert = mapper.deleteById(16L);
        System.out.println(insert);
        sqlSession.commit();
        sqlSession.close();
    }

    @Test
    public void testUpdateById(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Car car = new Car(15L, "22222", "小老板", 3.0, "2022-10-1", "新能源");
        mapper.update(car);
        System.out.println(car);

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


    @Test
    public void testSelectById(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Car car = mapper.selectById(33L);
        System.out.println(car);
    }

    @Test
    public void testSelectAll(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        List<Car> cars = mapper.selectAll();
        cars.forEach(car -> System.out.println(car));
    }
}

九 小黑子的MyBatis小技巧

9.1 #{} 和 $()

#{}:底层是PreparedStatement实现,特点:先编译sql语句,再给占位符传值。可以防止sql注入,比较常用。

  • 使用该方法会自动给传入的值添加''

${}:底层是Statement实现,特点:先进行sql语句拼接,然后再编译sql语句。不会给值添加'',所以存在sql注入现象。只有在需要进行sql语句关键字拼接的情况下才会用到。

  • 比如在书写升降序查询功能的SQL时,就需要使用${}来时asc或desc不带''形式拼接到SQL语句中
select id,car_num as carNum,brand,guide_price as guidePrice,produce_time as produceTime,car_type as carType from t_car order by carNum 'asc'

asc是一个升序关键字,不能带单引号的,所以在进行sql语句关键字拼接的时候,必须使用${}

案例:

  • CarMapper接口
package com.powernode.mybatis.mapper;

import com.powernode.mybatis.pojo.Car;

import java.util.List;

public interface CarMapper {
    /**
     * @description: 根据汽车类获取汽车信息并且根据desc降序、asc升序
     * @param asc
     * @version 1.0
     */
    List<Car> selectAllAscOrDesc(String asc);

    /**
     * @description: 根据汽车类获取汽车信息
     * @param carType
     * @version 1.0
    */
    List<Car> selectBycarType(String carType);
}

  • CarMapper.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.powernode.mybatis.mapper.CarMapper">
    <select id="selectAllAscOrDesc" resultType="com.powernode.mybatis.pojo.Car">
        select id,
               car_num as carNum,
               brand,
               guide_price as guidePrice,
               produce_time as produceTime,
               car_type as carType
        from
             t_car
        order by
            produce_time ${ascOrDesc}
    </select>

    <select id="selectBycarType" resultType="com.powernode.mybatis.pojo.Car">
        select id,
               car_num as carNum,
               brand,
               guide_price as guidePrice,
               produce_time as produceTime,
               car_type as carType
        from t_car
        where
            car_type = #{carType}
    </select>



</mapper>
  • 测试包:
    @Test
    public void testSelectAllAscOrDesc(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        List<Car> cars = mapper.selectAllAscOrDesc("asc");
        cars.forEach(car-> System.out.println(car));
        sqlSession.commit();
        sqlSession.close();
    }

使用#{}来进行升降序查询:
在这里插入图片描述
使用${}来进行升降序查询:
在这里插入图片描述

  • 所以如果是SQL语句的关键字放到SQL语句中,只能使用${},因为#{}是以值的形式放到SQL语句当中的

9.2 拼接表名

向SQL语句当中拼接表名,就需要使用${}

  • 现实业务当中,可能会存在分表存储数据的情况。因为一张表的花,数据量太大,查询效率比较低
  • 可以将这些数据有规律的分表存储,这样在查询的时候效率就比较高。因为扫描的数据量变少了。
  • 日志表:专门储存日志信息的。如果t_log只有一张表 ,这张表中每一天都会产生很多log,慢慢的,这个表中数据会很多

怎么解决问题?

  • 可以每天生成一个新表,每张以当天日期作为名称,例如:

    • t_log_20220901
    • t_log_20220902…
  • 如果想知道某一天的日志信息怎么办?

    • 假设 今天是20220901,那么直接查:t_log_2022901的表即可。

例子:

  • LogMapper.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">
<!--namespace先随意写一个-->
<mapper namespace="com.powernode.mybatis.mapper.LogMapper">
    <select id="selectAllByTable" resultType="com.powernode.mybatis.pojo.Log">
        select * from t_log_${date}
    </select>
</mapper>
  • LogMapper
package com.powernode.mybatis.mapper;

import com.powernode.mybatis.pojo.Log;

import java.util.List;

public interface LogMapper {
    /*
     * @description: 根据日期查询获取表中不同的日志
     * @version 1.0
    */

    List<Log> selectAllByTable(String date);
}

  • LogMapperTest
package com.powernod.mybatis.test;

import com.powernode.mybatis.mapper.LogMapper;
import com.powernode.mybatis.pojo.Log;
import com.powernode.mybatis.utils.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

public class LogMapperTest {

    @Test
    public void testSelectAllByTable(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        LogMapper mapper = sqlSession.getMapper(LogMapper.class);
        List<Log> logs = mapper.selectAllByTable("20220901");
        logs.forEach(log -> System.out.println(log));

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

在这里插入图片描述

在这里插入图片描述

9.3 批量删除

批量删除:一次删除多条记录

  • 批量删除的SQL语句有两种写法:
    • 第一种or:delete from t_car where id=1 or id=2 or id=3;
    • 第二种int:delete from t_car where id in(1,2,3);

案例:

  • CarMapper接口
package com.powernode.mybatis.mapper;

import com.powernode.mybatis.pojo.Car;

import java.util.List;

public interface CarMapper {

    /*
     * @description: 批量删除
     * @param ids
     * @version 1.0
    */
    int deleteBatch(String ids);

    /**
     * @description: 根据汽车类获取汽车信息并且根据desc降序、asc升序
     * @param asc
     * @version 1.0
     */
    List<Car> selectAllAscOrDesc(String asc);

    /**
     * @description: 根据汽车类获取汽车信息
     * @param carType
     * @version 1.0
    */
    List<Car> selectBycarType(String carType);
}

  • CarMapper.xml
    <delete id="deleteBatch">
        delete from t_car where id in (${ids})
    </delete>
  • 测试
  @Test
    public void testDeleteBatch(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        int count = mapper.deleteBatch("33");
        System.out.println(count);

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

在这里插入图片描述

9.4 模糊查询

需求: 根据汽车品牌进行模糊查询

  • CarMapper接口:
public interface CarMapper {
    /*
     * @description: 根据汽车品牌进行模糊查询
     * @param brand
     * @version 1.0
    */
    List<Car> selectByBrandLike(String brand);


    /*
     * @description: 批量删除
     * @param ids
     * @version 1.0
    */
    int deleteBatch(String ids);

    /**
     * @description: 根据汽车类获取汽车信息并且根据desc降序、asc升序
     * @param asc
     * @version 1.0
     */
    List<Car> selectAllAscOrDesc(String asc);

    /**
     * @description: 根据汽车类获取汽车信息
     * @param carType
     * @version 1.0
    */
    List<Car> selectBycarType(String carType);
}

  • 测试包
  @Test
    public void testSelectByBrandLike(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        List<Car> cars = mapper.selectByBrandLike("宝马");
        cars.forEach(car-> System.out.println(car));

        sqlSession.commit();
        sqlSession.close();
    }
  • CarMapper.xml
    • 第一种方案:'%{brand}%'
    • 第二种方案:concat函数,这个是mysql数据库当中的一个函数,专门进行字符串拼接
      concat('%',#{brand},'%')
    • 第三种方案: concat('%',${brand},'%') 比较鸡肋,可以不用
    • 第四种方案:"%"#{brand}"%"
  <select id="selectByBrandLike" resultType="com.powernode.mybatis.pojo.Car">
        select id,
               car_num as carNum,
               brand,
               guide_price as guidePrice,
               produce_time as produceTime,
               car_type as carType
        from
            t_car
        where
            brand like '%${brand}%'
    </select>

在这里插入图片描述
在这里插入图片描述

9.5 别名标签 typeAliases

第一种方式:typeAlias(可自定义,也可采用默认别名)
在mybatis.xml核心配置文件下写:

    <typeAliases>
        <typeAlias type="com.powernode.mybatis.pojo.Car" alias="aaa"></typeAlias>
    </typeAliases>

首先要注意typeAliases标签的放置位置,如果不清楚的话,可以看看错误提示信息。

typeAliases标签中的typeAlias可以写多个。

  • typeAlias:
    • type属性:指定给哪个类起别名
    • alias属性:别名。
  • alias属性不是必须的,如果缺省的话,type属性指定的类型名的简类名作为别名。比如:com.powernode.mybatis.pojo.Car,简化成:car
  • alias是大小写不敏感的。也就是说假设alias=“aaa”,再用的时候,可以aaa,也可以Aaa,也可以AAa,都行。但是就是不能写漏,或者写多

注意:namespace不能使用别名机制,必须写全限定接口名称、带有包名的
在这里插入图片描述

第二种方式:package(包下所有的类自动起别名,使用简名作为别名)

如果一个包下的类太多,每个类都要起别名,会导致typeAlias标签配置较多,所以mybatis用提供package的配置方式,只需要指定包名,该包下的所有类都自动起别名,别名就是简类名。并且别名不区分大小写。

    <typeAliases>
        <package name="com.powernode.mybatis.pojo"/>
    </typeAliases>

9.6 mapper的配置

SQL映射文件的配置方式包括四种:

  • resource:从类路径中加载
  • url:从指定的全限定资源路径中加载
  • class:使用映射器接口实现类的完全限定类名
  • package:将包内的映射器接口实现全部注册为映射器

resource

这种方式是从类路径中加载配置文件,所以这种方式要求SQL映射文件必须放在resources目录下或其子目录下。

<mappers>
  <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
  <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
  <mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>

url
这种方式显然使用了绝对路径的方式,这种配置对SQL映射文件存放的位置没有要求,随意。这种方式使用极少,因为移植性太差。

<mappers>
  <mapper url="file:///var/mappers/AuthorMapper.xml"/>
  <mapper url="file:///var/mappers/BlogMapper.xml"/>
  <mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>

class
这个位置提供的是mapper接口的全限定接口名,必须带有包名的。

思考:mapper标签的作用是指定SqlMapper.xml文件的路径,指定接口名有什么作用呢?

  • <mapper class="com.powernode.mybatis.mappper.CarMapper"/>
  • 如果你class指定是:com.powernode.mybatis.mappper.CarMapper
  • 那么mybatis框架会自动去com/powernode/mybatis/mapper目录下查找CarMapper.xml文件

注意:也就是说,如果采用这种方式,那么就必须保证CarMapper.xml文件和CarMapper接口必须在同一个目录下

如果使用这种方式必须满足以下条件:

  • SQL映射文件和mapper接口放在同一个目录下。
  • SQL映射文件的名字也必须和mapper接口名一致。
<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
  <mapper class="org.mybatis.builder.AuthorMapper"/>
  <mapper class="org.mybatis.builder.BlogMapper"/>
  <mapper class="org.mybatis.builder.PostMapper"/>
</mappers>

将CarMapper.xml文件移动到和mapper接口同一个目录下:

  • 在resources目录下新建:com/powernode/mybatis/mapper【这里千万要注意:不能这样新建 com.powernode.mybatis.dao
  • 将CarMapper.xml文件移动到mapper目录下
  • 修改mybatis-config.xml文件
<mappers>
  <mapper class="com.powernode.mybatis.mapper.CarMapper"/>
</mappers>

package

如果class较多,可以使用这种package的方式,但前提条件和上一种方式一样。

这种包的方式在实际开发中是经常使用的,前提是:xml文件必须和接口放在一起,并且名字一致

<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
  <package name="com.powernode.mybatis.mapper"/>
</mappers>

9.7 IDEA配置模板文件

在这里插入图片描述

9.8 插入数据时获取自动生成的主键

前提是:主键是自动生成的。
业务背景:一个用户有多个角色。

在这里插入图片描述

插入一条新的记录之后,自动生成了主键,而这个主键需要在其他表中使用时。
插入一个用户数据的同时需要给该用户分配角色:需要将生成的用户的id插入到角色表的user_id字段上。

第一种方式:可以先插入用户数据,再写一条查询语句获取id,然后再插入user_id字段。【比较麻烦】
第二种方式:mybatis提供了一种方式更加便捷。

  • CarMapper接口
/*
     * @description: 插入Car信息,并且使用生成的主键值
     * @param car
     * @version 1.0
    */
    int insertCarUseGeneratedKeys(Car car);
  • CarMapper.xml
<!--
      useGeneratedKeys="true" 使用自动生成的主键值
      keyProperty="id" 指定主键值赋值给对象的哪个数学。这个就表示将主键值赋值给Car对象的id属性
-->
    <insert id="insertCarUseGeneratedKeys" useGeneratedKeys="true" keyProperty="id">
        insert into t_car values(null,#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})
    </insert>
  • 测试
 @Test
    public void testInsertCarUseGenerateKeys(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);

        Car car = new Car(null,"9991","凯迪",40.0,"2022-11-11","能源车");

        mapper.insertCarUseGeneratedKeys(car);

        System.out.println(car);
        sqlSession.commit();
        sqlSession.close();
    }

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1075140.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

idea将jar包deploy到本地仓库

1、pom.xml文件引入配置&#xff0c;如下参考&#xff1a; <distributionManagement><snapshotRepository><id>maven-snapshots</id><url>http://nexus1.coralglobal.cn/repository/maven-snapshots/</url></snapshotRepository><…

2023全网最火的接口自动化框架对比 (建议收藏)

一、前言 自动化测试是把将手工驱动的测试行为转化为机器自动执行&#xff0c;通常操作是在某一框架下进行代码编写&#xff0c;实现用例自动发现与执行&#xff0c;托管在 CI/CD 平台上&#xff0c;通过条件触发或手工触发&#xff0c;进行回归测试&线上监控&#xff0c;…

四川竹哲电子商务有限公司抖音培训的靠谱选择

在今天的数字时代&#xff0c;抖音已经成为企业和个人必备的营销工具。然而&#xff0c;如何充分利用抖音的潜力&#xff0c;实现最大的营销效果&#xff0c;却让许多人感到困惑。四川竹哲电子商务有限公司正是为了解决这一问题而存在的。作为一家专业的抖音培训公司&#xff0…

Windows 7或10 - 删除进程方法,解决端口占用问题 - taskkill 命令删除进程

目录 一、正常删除进程Windows 命令 —— netstat&#xff1a; 二、taskkill 命令删除进程参考链接 一、正常删除进程 Windows 命令 —— netstat&#xff1a; 查看 8080 端口占用的进程 PID 号 netstat -ano|findstr "8080"类似如下&#xff1a;&#xff08;笔者…

溯源图构建工具SPADE的使用历程

溯源图构建工具SPADE的使用历程 一、我的环境二、SPADE下载安装过程1.下载SPADE2.编译SPADE3.安装SPADE4.启动SPADE 三、遇到的问题 一、我的环境 虚拟机&#xff1a;Virtual Box 6.1 OS&#xff1a;Kali 二、SPADE下载安装过程 SPADE网址&#xff1a;https://github.com/as…

MyBatisPlus属性自动填充和乐观锁插件+查询删除操作

属性字段自动填充 一、实体类和数据表添加两个字段&#xff08;属性&#xff09; 表&#xff1a;create_tiem/update_time 实体类&#xff1a;createTime/updateTime 二、实体类中属性进行注解添加 TableField(fillFieldFill.INSERT) private Date createTime;TableField(f…

复旦大学EMBA王世峰:坚持科技创造与品质,铸就“中国智造”梦!

当前&#xff0c;新能源产业呈现持续爆发式增长趋势&#xff0c;2023年《政府工作报告》对汽车行业提出“扩大消费绿色发展”的指导方向。动力电池是新能源汽车核心概念&#xff0c;对新能源汽车的性能和品质起着决定性作用。锂离子电池在电动汽车、电动飞行器、储能等领域的应…

Centos安装Jenkins官方方式安装教程

通过Jenkins官网方式安装&#xff0c;官网地址&#xff1a;Jenkins # 执行命令 sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo # 执行 sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key # yum方…

设计模式 - 行为型模式:模板方法模式(概念 | 案例实现 | 优缺点 | 使用场景)

目录 一、行为型模式 1.1、模板方法模式 1.1.1、概念 1.1.2、案例实现 1.1.3、优缺点 1.1.4、使用场景 一、行为型模式 一句话概括行为型模式 行为型模式&#xff1a;类或对象间如何交互、如何划分职责&#xff0c;从而更好的完成任务. 1.1、模板方法模式 1.1.1、概念 …

Go 语言中的反射

今天主要来聊聊 Go 语言中反射&#xff0c;希望对你有新的认知 虽然很多人使用 Go 语言有一定时间了&#xff0c;甚至有的使用了 1 年 2 年&#xff0c;然后对于 Go 语言中的反射还是模棱两可&#xff0c;使用起来的时候&#xff0c;心里也不是非常有底气 更有甚者&#xff0…

星际争霸之小霸王之小蜜蜂(十七)--究极体

系列文章目录 星际争霸之小霸王之小蜜蜂&#xff08;十六&#xff09;--狂奔的花猫 星际争霸之小霸王之小蜜蜂&#xff08;十五&#xff09;--剧将终场 星际争霸之小霸王之小蜜蜂&#xff08;十四&#xff09;--资本家的眼泪 星际争霸之小霸王之小蜜蜂&#xff08;十三&…

硬件测试(一):温循

一、定义&#xff1a; 温度循环试验&#xff0c;也称为热循环试验或高低温循环试验&#xff0c;是将试验样品暴露于预设的高低温交替的试验环境中所进行的可靠性试验。 温循作为自然环境的模拟&#xff0c;可以考核产品在不同环境条件下的适应能力&#xff0c;常用于产…

Cocos Creator3.8 项目实战(八)2D UI DrawCall优化详解(上)

游戏开发的朋友都知道&#xff0c;在游戏开发过程中&#xff0c;DrawCall 是我们优化性能的一个非常重要的指标&#xff0c;直接影响游戏的整体性能表现&#xff0c;DrawCall数量越多&#xff0c;帧率会降低&#xff0c;能明显感觉到卡顿。 那今天我们就来聊一聊&#xff0c;2D…

3D 生成重建005-NeRF席卷3D的表达形式

3D生成重建005-NeRF席卷3D的表达形式 文章目录 0 论文工作1 论文方法1.1 体渲染1.2 离散积分1.3位置编码1.4分层采样1.5 影响 2 效果 0 论文工作 NeRF(神经辐射场技术)最早2020年提出用于新视图合成任务&#xff0c;并在这个领域取得了优秀的效果。如下图所示&#xff0c;受到…

JAVA 自定义注解,实现数据脱敏处理

1&#xff1a;自定义注解 /*** 脱敏注解**/ Retention(RetentionPolicy.RUNTIME) Target(ElementType.FIELD) JacksonAnnotationsInside JsonSerialize(using SensitiveSerialize.class) public interface Sensitive {/*** 脱敏数据类型*/SensitiveTypeEnum type();}2&#x…

怎么在图片上加logo?

怎么在图片上加logo&#xff1f;在工作中我们经常需要给图片添加logo&#xff0c;例如公司的产品图片在对外发布时需要添加公司的logo&#xff0c;这样的做的目的主要有以下目的&#xff1a; ① 品牌推广&#xff1a;将品牌的logo添加到图片中可以增加品牌曝光度&#xff0c;并…

【Rust】Rust环境配置与语法基础

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍Rust环境配置与语法基础。 学其所用&#xff0c;用其所学。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c;下次更新不迷…

使用python连接Linux服务器发送指定命令

1.安装paramiko库 pip install paramiko2.使用paramiko库连接linux #导入库 import paramiko#创建一个sshclient对象 ssh paramiko.SSHClient()#允许连接不在know_host中的主机 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())#连接主机 ssh.connect(hostname&q…

nginx运行vue项目的dist文件

目录 1、安装nginx1.1、nginx常用命令1.2、将nginx注册为Windows系统服务 2、拷贝文件3、修改配置文件4、访问 1、安装nginx 官网下载&#xff1a;http://nginx.org/en/download.html 下载完之后直接解压即可 注&#xff1a;存放路径最好不要有中文、空格 1.1、nginx常用命令…