Mybatis 入门合集

Mybatis

1、简介

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

赠送官网链接:https://mybatis.org/mybatis-3/zh/index.html

2、第一个Mybatis 程序

2.1、环境搭建

数据库

CREATE DATABASE `mybatis`
use `mybatis`

CREATE TABLE `user`(
 `id` int NOT NULL PRIMARY KEY ,
 `name` VARCHAR(30) NOT NULL,
 `pwd` VARCHAR(50) NOT NULL
)ENGINE=INNODB DEFAULT CHARSET=utf8;

insert into `user` values
(1,'张三','1233456'),
(2,'李四','1233456'),
(3,'王五','1233456')

新建项目

新建一个普通的maven项目

删除src目录 (目的作为父工程)

导入依赖

   <!--导入依赖-->
    <dependencies>
<!--        mysql 驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.11</version>
        </dependency>
<!--        mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
<!--        junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
2.2、创建一个模块
  • 编写Mybatis 的配置文件

    在resources 下新建 Mybatis配置文件:mybatis-config.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>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/><!--驱动-->
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&amp;userUnicode=true&amp;charterEncoding=utf8&amp;serverTimezone=UTC"/><!--url-->
                <property name="username" value="TR"/><!--连接数据库的用户名-->
                <property name="password" value="adminxhb"/><!--密码-->
            </dataSource>
        </environment>
    </environments>
  
  <!--上面几乎不用改了,这里注意每次有mapper  都需要在这里注册-->
  <mappers>
        <mapper resource="com/xhb/dao/UserMapper.xml"></mapper><!--mapper映射-->
    </mappers>
</configuration>

可能会出现资源加载不进去的问题:因为约定大约配置(java文件不能放配置文件的)

所以如果要打破这个约定,就需要在pom.xml 中添加如下代码

<resources>
         <resource>
             <directory>src/main/java</directory>
             <includes>
                 <include>**/*.properties</include>
                 <include>**/*.xml</include>
             </includes>
             <filtering>false</filtering>
         </resource>
         <resource>
             <directory>src/main/resources</directory>
             <includes>
                 <include>**/*.properties</include>
                 <include>**/*.xml</include>
             </includes>
             <filtering>false</filtering>
         </resource>
     </resources>
  • 编写Mybatis 工具类
/**
 *  Mybatis 工具类
 */
public class MybatisUtils {
    private static SqlSessionFactory sqlSessionFactory ;
    static {
        //使用Mybatis的第一步      获取 SqlSessionFactory 对象
        InputStream inputStream = null;
        try {
            String resource = "mybatis-config.xml";
            inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    //既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。
    // SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}
2.3、编写代码
  • 实体类

        private int id;
        private String name;
        private String pwd;
    
    // 构造
    //get/set 方法
    // tostring 方法
    
  • DAO接口

    public interface UserDao {
        List<User> getUserList();
    }
    
  • 接口实现类

    由原来的UserDaoImp 转换为 mapper配置文件(UserMapper.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.xhb.dao.UserDao">
      <!-- 上面的namespace 对应你的Dao接口,
    		 		id:接口的方法
    				resultType:返回的类型(接口中定义的泛型):注意是全路径,必须全路径
    				然后就是SQL语句
    -->
        <select id="getUserList" resultType="com.xhb.pojo.User">
            select * from Blog where id = 1
        </select>
    </mapper>
    
2.4、测试
public class UserDaoTest {
   @Test
   public void test(){
       // 第一步:获得sqlSession 对象    从工具类中获取
       SqlSession sqlSession = MybatisUtils.getSqlSession();
     
       // 执行SQL  方式一:getMapper() :推荐使用,方式二不说了。
       UserDao mapper = sqlSession.getMapper(UserDao.class);
       List<User> userList = mapper.getUserList();
       for (User user : userList) {
           System.out.println(user);
       }
       sqlSession.close();
   }
}

3、CRUD

编写接口(UserMapper)

public interface UserMapper {
   
    List<User> getUserList(); // 查询所有用户
  
    User getUserById(int id);  // 根据id查询用户
   
    int addUser(User user); // 添加用户
   
    int updateUser(User user); // 修改用户
  
    int delUser(int id);  // 删除用户
}
select(查询)

UserMapper.xml

	<!-- 查全部-->
	<select id="getUserList" resultType="com.xhb.pojo.User">
        select * from mybatis.user
    </select>
	<!-- 根据id查-->
    <select id="getUserById" resultType="com.xhb.pojo.User" parameterType="int">
        select * from mybatis.user where id = #{id}
    </select>

#{id}是返回类型的 属性名。

测试

   // 第一步:获得sqlSession 对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        // 执行SQL  方式一:getMapper()
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = mapper.getUserList();
        for (User user : userList) {
            System.out.println(user);
        }
        // 关闭资源
        sqlSession.close();
insert (增)
 		<insert id="addUser"  parameterType="com.xhb.pojo.User">
        insert into mybatis.user values(default ,#{name},#{pwd})
    </insert>

//测试

  
			User user = new User( "xixi", "123456");
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int rows = mapper.addUser(user);
        if(rows>0){
            System.out.println("插入成功");
        }else{
            System.out.println("插入失败");
        }

        //增删改  需要提交事务
        sqlSession.commit();
        sqlSession.close();  // 关闭资源
delete(删)
 		<delete id="delUser" parameterType="int">
        delete from mybatis.user where id=#{id}
    </delete>
update(改)
   <update id="updateUser" parameterType="com.xhb.pojo.User" >
        update mybatis.user
        set name = #{name},pwd=#{pwd}
        where id = #{id};
    </update>

注意增删改需要提交事务,查不需要。

万能Map
 	 	<update id="updateUser2" parameterType="map" >
        update mybatis.user set name=#{userName},pwd=#{password} where id =#{userId}
    </update>

userNamepassworduserId是 map 集合的key

    @Test
    public void testUpdateUser2(){
       // User user = new User(2, "qq", "12456");//
        HashMap<String, Object> map = new HashMap<>();
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        map.put("userName","迪迦");
        map.put("userId",1);
        map.put("password","123456");
        mapper.updateUser2(map);

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

用Map的好处

当一个对象的字段很多,但是SQL语句中只用到了些许字段,

那么new一个对象会麻烦 (假设有参构造:User user = new User(字段1,字段2,... 字段10))是不是会很烦,(难道会为了某一个用途,再增加一个特有构造方法吗? 那显然不太符合编码规范(或者增加阅读疑问)吧。

OK,既然不new 有参构造,那我new 无参构造,然后set属性:object.setXXX(Object o)那这样总没问题吧。

好吧,问题又来了,假设有一个实体类,只能是有参构造,没有无参构造呢。假设实体类字段过多,new 的对象占用资源就大,是不是也不太合理。

那么这时候就用Map 就比较合适了(上面一大段废话,无非就是强行解释map 的好处,可以忽略…)权当只为增加一个新知识吧。

4、配置解析

https://mybatis.org/mybatis-3/zh/configuration.html:Mybatis 官方网址,可对着操作

image-20210812162533924

1、核心配置文件

  • Mybatis-config.xml
属性(properties)

在resources文件夹中 创建 db.properties文件

image-20210812170937129

db.properties

driver = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://localhost:3306/mybatis?useSSL=false&userUnicode=true&charterEncoding=utf8&serverTimezone=UTC
username = TR
password = adminxhb

注意: 之前在 environment 中使用的url 是&amp; 转义& , 记得改回来,小细节

mybatis-config.xml

<!--    映入外部资源 -->
    <properties resource="db.properties">
  			<property name="password" value="123456"/> <!--可以自己增加一些属性配置,-->
    </properties>

      <environment id="development"> <!-- 在环境中使用引入的外部资源的属性-->
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>

如果引用外部资源的字段名和内部的重名了,则 外部同名属性 覆盖 内部同名属性 ,像这里的密码123456就不会生效

设置(settings)
  • cacheEnabled 缓存
  • lazyLoadingEnabled 懒加载
  • logImpl 日志

settings 可以设置的太多了,具体可以看文档:https://mybatis.org/mybatis-3/zh/configuration.html#settings

类型别名(typeAliases)

typeAlias

    <typeAliases>
        <!-- 给com。xhb.pojo.User 起别名-->
        <typeAlias type="com.xhb.pojo.User" alias="User"/>
    </typeAliases>
image-20210812173539376

package

	 <typeAliases>
        <!-- 给com。xhb.pojo下所有实体类起别名 默认别名是 类名(首字母小写—) 不可以修改,除非用注解-->
        <package name="com.xhb.pojo"/>
    </typeAliases>

如果类不多的话,可以用第一种,反之则第二种

注解

会使前两种方式失效

@Alias("hello")
public class User {

当然还有自带的一些别名,去官网看。https://mybatis.org/mybatis-3/zh/configuration.html#typeAliases

环境配置 (environments)

不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-es51Hvhl-1629206460872)(D:\install\typora\images\image-20210812164140188.png)]

了解:

  • transactionManage 在 MyBatis 中有两种类型的事务管理器(也就是 type="[ JDBC| MANAGED ]"):
  • dataSource :有三种内建的数据源类型(也就是 type="[UNPOOLED|POOLED|JNDI]"):对应无连接池,连接池,普通

当然这些可能在实际开发中并不怎么用到,但是当做了解一下了, 或许在选择题,判断题,啥的问到

映射器(mappers)

使用相对于类路径的资源引用 (推荐使用

<!-- 使用相对于类路径的资源引用 -->
<mappers>
  <mapper resource="com/xhb/dao/UserMapper.xml"/>
</mappers>

使用映射器接口实现类的完全限定类名

<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
  <mapper class="com.xhb.dao.UserMapper"/>
</mappers>

使用此方式的注意点:

  • 接口必须和Mapper配置文件 同名
  • 必须在同一个目录(包)下

将包内的映射器接口实现全部注册为映射器

<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
  <package name="om.xhb.dao"/>
</mappers>

使用此方式的注意点(同上):

  • 接口必须和Mapper配置文件 同名
  • 必须在同一个目录(包)下
其他:

貌似对于初学者没啥用的 ,想看自己看,链接已经附上

5、作用域和生命周期

作用域和生命周期类别是至关重要的,因为错误的使用会导致非常严重的并发问题。

image-20210812211222634 image-20210812212429739
SqlSessionFactoryBuilder

这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。(老工具人了)

SqlSessionFactory
  • 可以理解为线程池,只要程序还存活, 就一直存在,等待连接对象

  • 没有任何理由丢弃它或重新创建另一个实例

  • SqlSessionFactory 的最佳作用域是应用作用域

  • 为了确保只有这一个实例,最简单的就是使用单例模式或者静态单例模式

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

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

  • 每次创建后都需要关闭(一定

  • 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中

6、解决数据库字段名和实体类属性名不一致问题

是否常听大佬 或者 老师 们说 数据库字段名 最好和 实体类属性名 要一致。

当然还有很多地方也需要按照规矩 去写代码或者建工程之类的。

比如:常见的jdk环境,是不是都让配置环境变量的时候写一个JAVA_HOME保存路径,然后path里引入。如果这时候你没按要求,你写成小写或者其他名字的时候,发现也都可以运行,以为老师骗你的,结果你学到了Tomcat 时候,发现你的Tomcat 闪退,其原因就是开启Tomcat的startUp.bat文件中引用的java jdk 的路径用的是JAVA_HOME而你用的是小写,所以 找不到,所以才闪退。

所以为什么一定一定 按照规范来写代码或者建工程呢。这是有道理的。

OK ,言归正传,那要是真出现这种问题怎么办呢。应该会有小聪明会来问,那我改成一致的不就行了,,,确实,可以。不过万一公司给你的是一个老项目,写的不规范,字段不一致,那你去改表,还是改实体类呢。显然这两种方法都不可取,因为你不知道这里面牵扯了多少的代码,这只会让你的项目bug 上 再加bug。

所以我们要学习resultMap看过来,看过来,肯定有小伙伴不想看一大段废话又不那么废话的废话,下面正片开始

还原现场

数据库与实体类中的字段不一致 (密码 不一致)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-29L8sXpd-1629206460876)(D:\install\typora\images\字段.png)]

结果 (密码这一栏为空)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4vwqS7cO-1629206460878)(D:\install\typora\images\image-20210813150931278.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-68JgFANU-1629206460881)(D:\install\typora\images\image-20210813151700940.png)]

解决方式一:

给数据库返回的字段取别名。

		 <select id="getUserById" resultType="user" parameterType="int">
        select  id, name, pwd as password from mybatis.user where id = #{id}
    </select>

emmm… 狂神说这是小屁孩才玩的方法(自我感觉很好用(手动狗头))。

所以我们介绍解决方式二

解决方式二 :

ResultMap( 结果集映射)

<!--    结果集映射-->
    <resultMap id="userMap" type="user">   <!-- 此处的id的值和下面 resultMap是对应的 type:返回的类型-->
        <result column="id" property="id"/> <!-- 字段映射 column :数据库字段   propertry:实体类属性-->
        <result column="name" property="name"/>
        <result column="pwd" property="password"/>
    </resultMap>

    <select id="getUserById" resultMap="userMap" parameterType="int">
        select  id, name, pwd  from mybatis.user where id = #{id}
    </select>

是不是发现,emmm ,还是上面那种简单,这种方式也挺简单。

如果这个世界总是这么简单就好了。

下面,看个有操作的,前方高能!!请打起精神

resultMap

ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。

7、日志

Mybatis 通过使用内置的日志工厂提供日志功能。内置日志工厂将会把日志工作委托给下面的实现之一:

  • ​ SLF4J
  • ​ Apache Commons Logging
  • ​ Log4j 2
  • ​ Log4j (掌握)
  • ​ JDK logging

log4j使用

导包

<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

log4j.properties

#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file

#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n

#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/kuang.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n

#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

核心配置文件中

    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>
    static Logger logger = Logger.getLogger(TestDao.class); //阿帕奇下的包 别导错了
		
		@Test
    public void testLog4j(){
        logger.info("进来了info:haha"); // 用于提示信息
        logger.debug("debug:haha"); // 调试信息
        logger.error("err:haha"); // 错误信息   给你分好了等级
    }

8、分页

limit分页

1、编写接口 (UserMapper)

    //分页查询
    List<User> getUserListByLimit(Map<String,Integer> map);

2、mapper 映射

 <!--    结果集映射-->
    <resultMap id="userMap" type="com.xhb.pojo.User">
        <result column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="pwd" property="password"/>
    </resultMap>

<!-- 因为上次改了实体的属性,所以这用一下结果集映射-->
		<select id="getUserListByLimit" resultMap="userMap" >
        select * from mybatis.user limit #{startIndex},#{offset}
    </select>

3、测试

    @Test
    public void testLimit(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        Map<String,Integer> map = new HashMap<String,Integer>();
        map.put("startIndex",1);
        map.put("offset",3);

        List<User> list = mapper.getUserListByLimit(map);
        for (User user : list) {
            System.out.println(user);
        }
        sqlSession.close();
    }
RowBounds 分页

1、编写接口

   // RowBounds 分页查询
    List<User> getUserListByRowBounds();

2、Mapper映射

  	 <select id="getUserListByRowBounds" resultMap="userMap">
        select * from mybatis.user
    </select>

3、测试

  @Test
    public void testRowBounds(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        RowBounds rowBounds = new RowBounds(2, 2);
        List<User> userList = sqlSession.selectList("com.xhb.dao.UserMapper.getUserListByRowBounds",null,rowBounds);

        for (User user : userList) {
            System.out.println(user);
        }
        sqlSession.close();
    }
PageHelp 分页插件

官方参考文档:https://pagehelper.github.io/docs/

9、使用注解开发

使用注解只适用于简单的sql语句。如果复杂还是推荐使用``xxxMapper.xml `配置文件

当然Mybatis 一般不适用注解。。。

1、编写接口

public interface UserMapper {
    @Select("select * from user")
    List<User> getUsers();
}

2、mybatis-config.xml 配置mapper(没有xml配置了,用的类映射)

 <mappers>
      <mapper class="com.xhb.dao.UserMapper"/>
 </mappers>

3、测试

    @Test
    public void testzj(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = mapper.getUsers();
        for (User user : users) {
            System.out.println(user);
        }
        sqlSession.close();
    }
注解增删改查

前提:在mybatis-config.xml 中配置了Mapper

    // 多个基本类型的参数要使用param  注解
    @Insert("insert into user(id,name,pwd) values(#{id},#{name},#{password})")
    int addUser(User user);

		// 一个参数 可以不用@param 注解  
		@Delete("delete from user where id=#{id}")
    int deleteUserById(int id);

    // 对象的话就不用 声明@Param 注解了
    @Update("Update user set name=#{name},pwd =#{password} where id = #{id}")
    int updateUserById(User user);

   // 多个基本类型的参数要使用 @Param 注解 
    @Select("select * from user where id =#{uid} and name=#{uname}")
    User getUserByIdAndName(@Param("uid") int id ,@Param("uname") String name);

测试

insert(增)

  @Test
  public void testAddUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.addUser(new User(22,"tt","123456"));
        sqlSession.commit();
        sqlSession.close();
    }

delete(删)

   @Test
    public void testDeleteUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.deleteUserById(1231);
        sqlSession.commit();
        sqlSession.close();
    }

update(改)

   @Test
    public void testupdateUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int rows = mapper.updateUserById(new User(2,"qqwwqq","123456"));
        System.out.println(rows);
        sqlSession.commit();
        sqlSession.close();
    }

select(查)

   @Test
    public void testGetUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.getUserByIdAndName(2, "qq");
        System.out.println(user);
        sqlSession.close();
    }

关于@ param () 注解

  • 基本类型的参数或者String类型,需要加上
  • 引用类型不需要加
  • 如果只有一个基本类型的话,可以忽略。为了养成习惯,也可以加上
  • 在sql语句中引用的就是注解里的属性#{注解的属性名}

#{},${} 区别

  • #{} 预编译的
  • ${} 不是预编译的

10、Lombok

使用

1.安装Lombok插件

File–> Settings —> Plugins

image-20210815212751935

2.导入依赖

<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.20</version>
    <scope>provided</scope>
</dependency>

@Data: 无参构造,get,set,tostring ,hashCode ,equals

@AllArgsConstructor:有参构造

@NoArgsConstructor:无参构造

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
  	 @Getter
    private Integer id; // 只是这个字段有get方法,前期去掉上面的@Data
    private String name;
    private String password;
}

放在类上是所有字段;放在属性上,是单一字段

11、多对一

关联:多个学生关联了一个老师

集合:一个老师 集合了一群学生

1、环境搭建
image-20210815231317756

sql 建表 填充数据

CREATE TABLE `teacher` (
  `id` INT(10) NOT NULL,
  `name` VARCHAR(30) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8

INSERT INTO teacher(`id`, `name`) VALUES (1, '秦老师'); 


CREATE TABLE `student` (
  `id` INT(10) NOT NULL,
  `name` VARCHAR(30) DEFAULT NULL,
  `tid` INT(10) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `fktid` (`tid`),
  CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8

INSERT INTO `student` (`id`, `name`, `tid`) VALUES (1, '小明', 1); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (2, '小红', 1); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (3, '小张', 1); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (4, '小李', 1); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES (5, '小王', 1);

resources 下新建Mybatis核心配置文件,数据库连接属性

mybatis-config.xmldb.properties

db.properties

driver = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://localhost:3306/mybatis?useSSL=false&userUnicode=true&charterEncoding=utf8&serverTimezone=UTC
username = TR
password = adminxhb

mybatis-config.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>
<!--    映入外部资源-->
    <properties resource="db.properties"/>

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

    </environments>

    <mappers>
      <mapper class="com.xhb.dao.StudentMapper"/>
    </mappers>
</configuration>

提取公用工具类MybatisUtils

package com.xhb.utils;

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;

/**
 *  Mybatis 工具类
 */
public class MybatisUtils {
    private static SqlSessionFactory sqlSessionFactory ;
    static {
        //使用Mybatis的第一步      获取 SqlSessionFactory 对象
        InputStream inputStream = null;
        try {
            String resource = "mybatis-config.xml";
            inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    //既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。
    // SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句
    // openSession(true) 开启事务自动提交
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}

pojo

@Data
public class Student { // 学生类
    private int id;
    private String name;

    // 学生需要关联一个老师
    private Teacher teacher;
}

public class Teacher { // 老师类
    private int id;
    private String name;
}

测试

   @Test
    public void testStudent(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        List<Student> studentList = mapper.getStudentList();
        for (Student student : studentList) {
            System.out.println(student);
        }
        sqlSession.close();
    }
2、子查询

select s.id,s.name,t.name from student as s ,teacher as t where s.tid = t.id

    <!-- 连表查询 学生 和 老师-->
    <select id="getStudents" resultMap="studentTeacher">
        select * from student
    </select>

    <resultMap id="studentTeacher" type="student">
        <association property="teacher" column="tid" select="getTeachers"/>
    </resultMap>
    
    <select id="getTeachers" resultType="teacher">
        select * from teacher where id =#{id}
    </select>

测试

    @Test
    public void testStudent(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        List<Student> studentList = mapper.getStudents();
        for (Student student : studentList) {
            System.out.println(student);
        }
        sqlSession.close();
    }
3、连表查询
<!--    连表查询方式二-->
    <select id="getStudents2" resultMap="st">
        select s.id as sid ,s.name as sname,t.name as tname from student as s , teacher as t where s.tid = t.id
    </select>
    <resultMap id="st" type="student">
        <result property="id" column="sid"/>
        <result property="name" column="sname"/>
        <association property="teacher" javaType="teacher">
            <result property="name" column="tname"/>
        </association>
    </resultMap>

测试结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jqH1zfPu-1629206460890)(D:\install\typora\images\image-20210816111133742.png)]

因为上面我们只查了老师的名字,所以id 并没有(那是int类型的默认值)

12、一对多

一个老师有多个学生,对于老师而言,就是一对多

环境搭建

和刚才一样

需要改的是实体类

实体类

@Data
public class Teacher {
    private int id;
    private String name;
    // 一个老师拥有多个学生
    private List<Student> students;
}
@Data
public class Student {
    private int id;
    private String name;
    private int tid;
}
联表查询
<!--    根据id 查询老师-->
    <select id="getTeacherById" resultMap="teacherStu">
        select t.id as tid,t.name as tname,s.name as sname
        from teacher as t ,student as s
        where t.id = s.tid and t.id = #{tid}
    </select>
    <resultMap id="teacherStu" type="teacher">
        <result property="id" column="tid"/>
        <result property="name" column="tname"/>
        <collection property="students" ofType="student">
            <result property="name" column="sname"/>
        </collection>
    </resultMap>

测试

  @Test
    public void testGetTeacher(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
        Teacher teacher = mapper.getTeacherById(1);

            System.out.println(teacher);

        sqlSession.close();
    }

13、动态SQL

还记得被SQL 语句拼接的痛苦吗,现在动态SQL 来了,mama 再也不用担心我被SQL语句拼接所支配了

环境搭建
  1. 导入依赖(Lombokmysql-connector-java , mybatis , junit) 数据库驱动,Mybatis 的库必须导,其他选择性导入
  2. Mybatis 配置文件(mybatis-config.xmldb.properties)
  3. 提取工具类(mybatisUtils)
  4. 编写实体类(Blog
  5. 编写接口(BlogMapper)
  6. 编写接口对应的Mapper(BlogMapper.xml) 放在resourcesmapper(新建) 文件夹下
image-20210816210320442
IF

实现的功能

如果map中没参数则查询所有博客,如果传入title 参数,则SQL语句增加and title = #{title} 根据标题查博客…

<!--    动态sql if 查询博客-->
    <select id="getBlogListByIf" parameterType="map" resultType="blog">
        select * from blog where 1=1
        <if test="title!=null">
            and title = #{title}
        </if>
        <if test="author!=null">
            and author = #{author}
        </if>
    </select>
    @Test
    public void testIf(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();
//        map.put("author","哈哈");
//        map.put("title","mybatis");
        List<Blog> list = mapper.getBlogListByIf(map);
        for (Blog blog : list) {
            System.out.println(blog);
        }

结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iENM3USK-1629206460892)(D:\install\typora\images\动态sql.png)]

choose (when otherwise)

相当于就是java的switch

switch(xxx){  //choose   就相当于switch 这个框
  case 0:xxxx;break;//when  就相当于每一个case
  case 1:xxx;break;
  default:xxx;break;//otherwise 相当于default 
}
 <!--    动态sql where choose when otherwise 查询博客-->
    <select id="getBlogListByChoose" parameterType="map" resultType="blog">
        select * from blog
        <where>
            <!-- 分支结构 和java的switch一样的,只能选择其一 ,emmm 不存在java的switch穿透-->
            <choose>
                <when test="title!=null">
                    title = #{title}
                </when>
                <when test="author!=null">
                    author = #{author}
                </when>
                <otherwise >
                    views >= 10
                </otherwise>
            </choose>
        </where>
    </select>

应该是没有java中switch的穿透概念的。

set
  <!--    动态sql set 查询博客-->
    <update id="updateBlogBySet" parameterType="map">
        update blog
        <set>
            <if test="title!=null">
                title = #{title},
            </if>
            <if test="author!=null">
                author = #{author},
            </if>
        </set>
        where id = #{id}
    </update>
  @Test
    public void testSet(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();
        map.put("author","嘻嘻");
        map.put("id","11e81df322be44b8bd0a6aecf6417ba3");
        mapper.updateBlogBySet(map);
        sqlSession.commit();
        sqlSession.close();
    }

多了他可以帮你省,少了就报错

SQL片段

重复性比较高的语句提取出来,封装,就形成SQL片段,提高复用

    <sql id="if_title_author">
        <if test="title!=null">
            and title = #{title}
        </if>
        <if test="author!=null">
            and author = #{author}
        </if>
    </sql>
<!--    动态sql if 查询博客-->
    <select id="getBlogListByIf" parameterType="map" resultType="blog">
        select * from blog
        <where>
            <include refid="if_title_author"></include> <!-- include 标签引用上面sql片段 -->
        </where>
    </select>

注意:最好基于单表定义sql片段,对于复杂的SQL 采用sql拼接可能对前后有冲突之类的,并不能提高复用,所以单表好。

foreach
<!--    查询id 为 1,3的博客-->
    <select id="getBlogByIn" parameterType="list" resultType="blog">
        select * from blog where id in 
        <foreach collection="list" item="id" open="(" separator="," close=")">
             #{id}
          <!-- 这里取的id就是item 的id   -->
        </foreach>
    </select>

 @Test
    public void testForeach(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        ArrayList arrayList = new ArrayList();
        arrayList.add(1);
        arrayList.add(3);
        List<Blog> blogByIn = mapper.getBlogByIn(arrayList);
        for (Blog blog : blogByIn) {
            System.out.println(blog);
        }
        sqlSession.close();
    }

14、Mybatis缓存

Mybatis包含一个非常强大的查询缓存特性,他可以非常方便地定制和配置缓存。缓存可以极大的提升查询效率。

  • Mybatis 系统中默认定义了两种缓存:一级缓存二级缓存
  • 默认情况下,只有一级缓存开启。(SQLSession级别的缓存,也称为本地缓存)
  • 二级缓存需要手动开启和配置,他是基于namespace 级别的缓存。
  • 为提高扩展性,Mybatis定义了缓存接口Cache。 实现Cache接口自定义二级缓存
一级缓存

测试前的准备工作,开启日志

mybatis-congif.xml

<!--    设置日志-->
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

测试结果

注意对比两张图的日志输出

image-20210817160819714 缓存png

第二张图 明显是查了两遍,而第一张图只查了一遍

缓存失效情况:

  • 映射语句文件中的所有 select 语句的结果将会被缓存。
  • 映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存
  • 缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。
  • 缓存不定时进行刷新(也就是说,没有刷新间隔)。
  • 手动清除缓存 sqlSession.clearCache();
二级缓存
  • 二级缓存也叫全局缓存,一级缓存的作用域太低了,所以诞生了二级缓存。

  • 二级缓存基于namespace 级别的缓存

工作机制

一个会话查询一条数据,放在一级缓存中,当会话关闭了,对应的一级缓存也没了,数据被保存到了二级缓存中,新的会话查询时,就可以从二级缓存中获取

使用:

1、开启缓存

虽然默认值是true,可以不用写,为了增加阅读性还是可以写的

  <!--        开启缓存-->
  <setting name="cacheEnabled" value="true"/>

2、在要使用的mapper.xml 中开启(这样就可以用了)

  <cache/>

也可以配置一些参数

<cache
  eviction="FIFO" <!--清除策略 FIFO:先进先出-->
  flushInterval="60000" <!-- ,每隔 60 秒刷新-->
  size="512" <!-- 最多可以存储结果对象或列表的 512 个引用-->
  readOnly="true"/> <!-- 返回的对象被认为是只读的-->

​ 可用的清除策略有:

  • LRU – 最近最少使用:移除最长时间不被使用的对象。
  • FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
  • SOFT – 软引用:基于垃圾回收器状态和软引用规则移除对象。
  • WEAK – 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。

3、测试

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JpM3DevQ-1629206460893)(D:\install\typora\images\image-20210817171356002.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Sc0rRX2R-1629206460894)(D:\install\typora\images\缓存2-1629192410201.png)]

扩展

在sql 标签中能定义时候使用,刷新缓存

image-20210817174122707

遇到了问题:

开启二级缓存后报错 实体类没有序列化?

那么在 实体类中实现序列化接口 或者 <cache readOnly="true"/>

小结一下:

  • 一级缓存的作用域在sqlSession中

  • 二级缓存的作用域在Mapper.xml 的namespace 中

  • 二级缓存的数据一定是一级缓存关闭前存进去的(也就是先有一级缓存才有二级缓存)

回顾Mybatis 的一生//todo

很多年后,你想起了陪你一起走过风风雨雨的Mybatis。你陷入了回忆…

你想起你的第一节课,什么是Mybatis

老师说:Mybatis 是一个可以自定义SQL,存储过程和高级映射的持久层框架?并且能摒除大部分的JDBC代码、手工设置参数和结果集映射。

你留下了疑问?能摒除大部分JDBC代码?

于是老师带着你来探寻其中的真理了…

老师让你配置好你的环境,有什么呢?

  • 数据库(表)是不能少的

  • 新建普通maven项目,删除src目录(作为父工程),新建module(子工程)

  • 导入依赖(mysql-connector-javamybatislombokjunit) 前两个必须导入

       <dependencies>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId><!--mysql 驱动-->
                <version>8.0.11</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId><!-- mybatis-->
                <version>3.5.2</version>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId><!--junit-->
                <version>4.12</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId><!--lombok-->
                <version>1.18.20</version>
            </dependency>
        </dependencies>
    
  • 编写mybatis核心配置文件mybatis-config.xml db.properties

    <?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>
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.cj.jdbc.Driver"/><!--驱动-->
                    <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&amp;userUnicode=true&amp;charterEncoding=utf8&amp;serverTimezone=UTC"/><!--url-->
                    <property name="username" value="TR"/><!--连接数据库的用户名-->
                    <property name="password" value="adminxhb"/><!--密码-->
                </dataSource>
            </environment>
        </environments>
      
      <!--上面几乎不用改了,这里注意每次有mapper  都需要在这里注册-->
      <mappers>
            <mapper resource="com/xhb/dao/UserMapper.xml"></mapper><!--mapper映射-->
        </mappers>
    </configuration>
    
    driver = com.mysql.cj.jdbc.Driver
    url = jdbc:mysql://localhost:3306/mybatis?useSSL=false&userUnicode=true&charterEncoding=utf8&serverTimezone=Asia/Shanghai
    username = TR
    password = adminxhb
    

准备工作终于做好了,老师开始教你封装JDBC 代码了,提取工具类(MybatisUtils

老师告诉你,首先将你的配置文件 转换成流

InputStream inputStream = null; 
String resource = "mybatis-config.xml";
inputStream = Resources.getResourceAsStream(resource); //将配置文件 转换成流   

然后将 资源流 通过sqlSession 工厂建造者,给你建一个sqlsession工厂

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

然后你有了sqlsession的工厂,你就可以肆意妄为的造sqlsession了

从 SqlSessionFactory 中获取 SqlSession

SqlSession session = sqlSessionFactory.openSession()

而后得到了完整的工具类

public class MybatisUtils {
    private static SqlSessionFactory sqlSessionFactory ;
    static {
        //使用Mybatis的第一步      获取 SqlSessionFactory 对象
        InputStream inputStream = null;
        try {
            String resource = "mybatis-config.xml";
            inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();   // openSession(true) 开启事务自动提交
    }
}

工具类也好了,去测试吧!

测试前提工作:编写实体类,接口,接口映射Mapper.xml

  • 编写实体类

    老师说:偷懒的孩子可以用 Lombok 的注解 @Data@AllArgsConstructor@NoArgsConstructor ,分别可以生成

    get/set ,equals,tostring ,hashCode 和 全参构造 和 无参构造 的实体类。

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User {
        private Integer id;
        private String name;
        private String pwd;
    }
    
  • 接口

    public interface UserMapper {
        // 查询所有用户
        List<User> getUserList();
    }
    
  • Mapper.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.UserMapper">
        <!--插入-->
        <select id="getUserList" resultType="com.User">
            select * from mybatis.user
        </select>
    </mapper>
    

在核心配置文件中注册mapper

		<mappers>
        <mapper resource="com/xhb/dao/UserMapper.xml"></mapper>
    </mappers>

这次真的都准备好了

    @Test
    public void test(){
        // 第一步:获得sqlSession 对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        // 执行SQL  方式一:getMapper()
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = mapper.getUserList();
        for (User user : userList) {
            System.out.println(user);
        }
        // 关闭资源
        sqlSession.close();
    }

老师说 第一个Mybatis的程序就写完了,

至于代码有些是不需要改的

比如:工具类,就可以不用动他了。核心配置文件,也几乎不需要大修改了,只是有用到某些东西的时候,往里面加几句代码就可以了,实体类这不需要动了,除非再增加其他实体类

那么要修改的就只有,接口,mapper.xml 了

接口很简单,只需要往里面添加需要的方法。

重点就是mapper.xml 了, 所有的sql语句都写在这里。

第一节课下课了,,,,

第二节课上课了,,,,

老师让你们开始练习写写CRUD

你开心的写着

第一步写接口

写接口还是比较轻松的,只需要想清楚要传递的参数,返回值类型

public interface UserMapper {
    
    List<User> getUserList();// 查询所有用户
    
    User getUserById(int id);// 根据id查询用户
   
    int addUser(User user); // 添加用户
   
    int updateUser(User user); // 修改用户
    
    int updateUser2(Map<String,Object> map2);// 修改用户
   
    int delUser(int id); // 删除用户
}

第二步写mapper.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.xhb.dao.UserMapper">
  
    <select id="getUserList" resultType="com.xhb.pojo.User">
        select * from mybatis.user
    </select>
  
    <select id="getUserById" resultType="com.xhb.dao.pojo" parameterType="int">
        select * from mybatis.user where id = #{id}
    </select>
  
    <insert id="addUser"  parameterType="com.xhb.dao.pojo">
        insert into mybatis.user values(default ,#{name},#{pwd})
    </insert>
  
    <update id="updateUser" parameterType="com.xhb.dao.pojo" >
        update mybatis.user
        set name = #{name},pwd=#{pwd}
        where id = #{id};
    </update>
  
    <delete id="delUser" parameterType="int">
        delete from mybatis.user where id=#{id}
    </delete>

    <update id="updateUser2" parameterType="map" >
        update mybatis.user set name=#{userName},pwd=#{password} where id =#{userId}
    </update>
</mapper>

老师教你:namespace 就是绑定你的接口

然后有很多标签 常用 insert ,delete , update ,select 对应的就是增删改查

其中id 代表的是你接口中的方法,,,

有时候会传递参数,那么parameterType 就代表你传递参数的类型

其中属性resultType 代表是返回值类型,必须要全限定名

你觉得有些麻烦,于是老师又教了你一招

在核心配置文件中取别名(两种方式)

    <typeAliases>
        <!-- 给com。xhb.pojo.User 起别名-->
        <typeAlias type="com.xhb.pojo.User" alias="User"/>
    </typeAliases>
	 <typeAliases>
        <!-- 给com。xhb.pojo下所有实体类起别名 默认别名是 类名(首字母小写—) 不可以修改,除非用注解-->
        <package name="com.xhb.pojo"/>
    </typeAliases>
@Alias("haha")
public class User {} // 注解方式取别名  

然后开始写sql语句了,你不明白那个#{id} 是啥意思,就是接口传递过来变量(对象的属性)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值