当前位置: 首页 > news >正文

mybatisStudy

1.mybatis入门

1.环境配置:

​ 要使用 MyBatis, 只需将 mybatis-x.x.x.jar 文件置于类路径(classpath)中即可。

​ 如果使用 Maven 来构建项目,则需将下面的依赖代码置于 pom.xml 文件中:

<dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>x.x.x</version>
</dependency>

2.mybatis核心配置文件:

<!--常命名为mybatis-config.xml--><?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//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="${driver}"/><property name="url" value="${url}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment></environments><!--映射到 Mapper.xml--><mappers><mapper resource="org/mybatis/example/BlogMapper.xml"/></mappers>
</configuration>

注意 XML 头部的声明,它用来验证 XML 文档的正确性。environment 元素体中包含了事务管理和连接池的配置。mappers 元素则包含了一组映射器(mapper),这些映射器的 XML 映射文件包含了 SQL 代码和映射定义信息。

从 XML 中构建 SqlSessionFactory:

​ 每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例。

3.编写mapper.xml文件:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.mybatis.example.BlogMapper"><select id="selectBlog" resultType="Blog">select * from Blog where id = #{id}</select>
</mapper>

4.常见异常:

很有可能是maven的问题 由于maven的约定大于配置,我们可能遇到所写的配置文件无法导出或生效

  • java.lang.ExceptionInInitializerError 初始化异常

    资源过滤问题:没有加载到target资源目录中

    解决方法:

    在build中配置resources,来防止我们资源导出失败的问题
    <!--    在build中配置resources , 来防止我们资源导出失败的问题--><build><resources><resource><directory>src/main/resources</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes></resource><resource><directory>src/main/java</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes></resource></resources></build>
    
  • org.apache.ibatis.binding.BindingException: Type interface com.song.dao.UserDao is not known to the MapperRegistry. mapper 没有注册

    每一个mapper.xml都需要在mybatis核心配置文件中注册

    解决方法:

    ​ 在mybatis核心配置文件中注册 Eg:

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

2.CRUD(练手)

Mapper.xml中 :

**namespeace : dao层接口名 标签中 id : 接口中的方法名 **

parameterType : 参数类型 resultType :结果返回值类型

每个sqlSession 对象用完后都应关闭,建议写在finally中

1. 需要提交事务

1.insert

  1. 编写接口中的方法
public interface UserMapper { //添加用户int addUser(User user);
}
  1. 编写Mapper.xml文件
<!--    插入用户--><insert id="addUser" parameterType="com.song.pojo.User" >insert into mybatis.user(id,name, pwd) VALUES (#{id},#{name},#{pwd})</insert>
  1. 测试
@Testpublic void insertUser(){//获取SqlSessionSqlSession sqlSession = mybatisUtil.getSqlSession();//获取接口映射对象 Mapper对象UserMapper mapper = sqlSession.getMapper(UserMapper.class);//执行接口中的方法int i = mapper.addUser(new User(8,"sjf","123"));if (i>0){System.out.println("插入成功");sqlSession.commit();}else {System.out.println("插入失败");sqlSession.rollback();}sqlSession.close();}

2.delete

  1. 编写接口中的删除用户方法
public interface UserMapper { //删除用户int deleteUser(int id);
}
  1. 编写Mapper.xml文件
<!--    删除用户--><delete id="deleteUser" parameterType="int" >delete from mybatis.user where id=#{id}</delete>
  1. 测试
@Testpublic void insertUser(){//获取SqlSessionSqlSession sqlSession = mybatisUtil.getSqlSession();//获取接口映射对象 Mapper对象UserMapper mapper = sqlSession.getMapper(UserMapper.class);//执行接口中的方法int i = mapper.deleteUser(8);if (i>0){System.out.println("删除成功");sqlSession.commit();}else {System.out.println("删除失败");sqlSession.rollback();}sqlSession.close();}

3.update

public interface UserMapper { //修改用户int modifyUser(User user);
}
<!--    修改用户--><update id="modifyUser" parameterType="com.song.pojo.User">update mybatis.userset name =#{name} ,pwd=#{pwd}where id=#{id};</update>>
 @Testpublic void modifyUser(){SqlSession sqlSession = mybatisUtil.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);int i = mapper.modifyUser(new User(8, "hhh", "123"));if (i>0){System.out.println("修改成功");sqlSession.commit();}else {System.out.println("修改失败");sqlSession.rollback();}sqlSession.close();}

2.不需提交事务

4.select

  1. 编写接口中查询方法
  //获取用户列表List<User> getUserList();//通过id获取用户User getUserById(int id);
  1. 配置Mapper.xml文件
<!--    查询用户--><select id="getUserList" resultType="com.song.pojo.User">select * from mybatis.user</select>
<!--    通过ID 查询用户--><select id="getUserById"  parameterType="int" resultType="com.song.pojo.User">select * from mybatis.user where `id`=#{id}</select>
  1. 测试
 @Testpublic void getUser(){SqlSession sqlSession=null;try {//获取SqlSession对象sqlSession = mybatisUtil.getSqlSession();//获取接口映射对象UserMapper mapper = sqlSession.getMapper(UserMapper.class);//通过接口映射对象,执行接口中的方法// 执行方法 1List<User> userList = mapper.getUserList();// 执行方法 2
//            List<User> userList = sqlSession.selectList("com.song.dao.UserMapper.getUserList");for (User user : userList) {System.out.println(user);}}finally {//关闭sqlSession资源sqlSession.close();}}
//通过id获取用户@Testpublic void getUserById(){User user=new User(1,"aaa","sdww");SqlSession sqlSession = mybatisUtil.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);User userById = mapper.getUserById(2);System.out.println(userById);sqlSession.close();}

3.小结

易错点:

  • 标签匹配错误:

    org.apache.ibatis.binding.BindingException: Mapper method 'com.song.dao.UserMapper.addUser attempted to return null from a method with a primitive return type (int).

    eg:

    
    <!--    插入用户   正确--><insert id="addUser" parameterType="com.song.pojo.User" >insert into mybatis.user(id,name, pwd) VALUES (#{id},#{name},#{pwd})</insert><!--    插入用户  错误--><select id="addUser" parameterType="com.song.pojo.User" >insert into mybatis.user(id,name, pwd) VALUES (#{id},#{name},#{pwd})</select>
    
  • resource绑定Mapper.xml 需要用"/"

    eg:

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

3. mybatis配置解析

configuration(配置)

  • properties(属性)
  • settings(设置)
  • typeAliases(类型别名)
  • typeHandlers(类型处理器)
  • objectFactory(对象工厂)
  • plugins(插件)
  • environments(环境配置)
    • environment(环境变量)
      • transactionManager(事务管理器)
      • dataSource(数据源)
  • databaseIdProvider(数据库厂商标识)
  • mappers(映射器)

1. 核心配置文件

  • mybatis-config.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configurationPUBLIC "-//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="${driver}"/><property name="url" value="${url}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment></environments><mappers><mapper resource="org/mybatis/example/BlogMapper.xml"/></mappers>
    </configuration>
    

MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息

properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)

1. environments(环境配置)

environments 元素定义了如何配置环境。

MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中, 现实情况下有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置;或者想在具有相同 Schema 的多个生产数据库中使用相同的 SQL 映射

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

  • 注意一些关键点:

    • 默认使用的环境 ID(比如:default=“development”)。

    • 每个 environment 元素定义的环境 ID(比如:id=“development”)。

    • 事务管理器的配置

      在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]"):

      默认是JDBC

      • JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。
      • MANAGED – 这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接。然而一些容器并不希望连接被关闭,因此需要将 closeConnection 属性设置为 false 来阻止默认的关闭行为。

      提示 如果你正在使用 Spring + MyBatis,则没有必要配置事务管理器,因为 Spring 模块会使用自带的管理器来覆盖前面的配置。

      这两种事务管理器类型都不需要设置任何属性。它们其实是类型别名,换句话说,你可以用 TransactionFactory 接口实现类的全限定名或类型别名代替它们

    • 数据源的配置(比如:type=“POOLED”)。

      有三种内建的数据源类型(也就是 type="[UNPOOLED|POOLED|JNDI]"):

      默认是POOLED

2.mappers (映射器)

注册绑定 dao层 mapper.xml

既然 MyBatis 的行为已经由上述元素配置完了,我们现在就要来定义 SQL 映射语句了。 但首先,我们需要告诉 MyBatis 到哪里去找到这些语句。 在自动查找资源方面,Java 并没有提供一个很好的解决方案,所以最好的办法是直接告诉 MyBatis 到哪里去找映射文件。 你可以使用相对于类路径的资源引用,或完全限定资源定位符(包括 file:/// 形式的 URL),或类名和包名等。例如:

<!-- 使用相对于类路径的资源引用 -->
<mappers><mapper resource="org/mybatis/builder/AuthorMapper.xml"/><mapper resource="org/mybatis/builder/BlogMapper.xml"/><mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- 使用完全限定资源定位符(URL) -->
<mappers><mapper url="file:///var/mappers/AuthorMapper.xml"/><mapper url="file:///var/mappers/BlogMapper.xml"/><mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>

已过时

<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers><mapper class="org.mybatis.builder.AuthorMapper"/><mapper class="org.mybatis.builder.BlogMapper"/><mapper class="org.mybatis.builder.PostMapper"/>
</mappers>

接口名必须和Mapper.xml文件同名

接口名必须和Mapper.xml在同一个包中

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

接口名必须和Mapper.xml文件同名

这些配置会告诉 MyBatis 去哪里找映射文件,剩下的细节就应该是每个 SQL 映射文件了

3.properties(属性)

这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置

eg:

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306?useUnicode=true&characterEncoding=utf-8&useSSL=true
username=root
password=123456

在xml核心配置文件中引入propert文件

<!--    引入外部配置文件--><properties resource="mybatis.properties"/>

注意 xml标签中元素是有顺序的:The content of element type “configuration” must match “(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?)”.

也可以在 properties 元素的子元素中设置。例如:

 <properties resource="mybatis.properties"><property name="password" value="123456"/></properties>

两者优先级: properties文件 > property标签

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><!--配置-->
<configuration><!--    引入外部配置文件--><properties resource="mybatis.properties"/><!--环境s--><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><!--没有的话会出现绑定注册异常org.apache.ibatis.binding.BindingException: Type interfacecom.song.dao.UserDao is not known to the MapperRegistry.mapper--><mappers><package name="com.song.dao"/></mappers></configuration>

4.typeAliases(类型别名)

意在降低冗余的全限定类名书写

1.类型别名可为 Java 类型设置一个缩写名字

eg: 把 com.song.pojo.User 缩写为 User

<typeAliases><typeAlias type="com.song.pojo.User" alias="User"></typeAlias>
</typeAliases>

2.指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean

eg:

<typeAliases>
<!--    <typeAlias type="com.song.pojo.User" alias="User"></typeAlias>-->
<package name="com.song.pojo"/>
</typeAliases>

小结: 第一种适合实体类比较少的时候,第二种则反之

​ 第一种可以自定义别名,

​ 第二种自定义别名则需要在实体类加@alias注解

5.其他配置

settings(设置)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)

dataSource(数据源)
databaseIdProvider(数据库厂商标识)

4.结果映射

引入:当数据库中字段名和实体类中属性名不一致时

数据库字段:

在这里插入图片描述

实体类属性:
在这里插入图片描述

查询后密码为空

在这里插入图片描述

这时就需要就需要一种映射关系将数据库字段和实体类属性映射关联

  //       id:结果映射标识  type:结果类型
<resultMap id="UserMap" type="User"// 不一致的内容   property:实体类属性   column:数据库字段<result property="password" column="pwd"/></resultMap>
//												resultMap:引入结果映射<select id="getUserById" parameterType="int" resultMap="UserMap">select *from mybatis.userwhere id = #{id}</select>

映射之后查询:

在这里插入图片描述

5.日志

1.日志工厂

在核心配置文件的settings中设置

logImpl指定 MyBatis 所用日志的具体实现,未指定时将自动查找。SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING未设置
设置名描述有效值默认值
  1. STDOUT_LOGGING日志工厂

    在核心配置文件中设置(注意xml文件中标签元素的位置)

    <settings><setting name="logImpl" value="STDOUT_LOGGING"/></settings>
    

    打印出的日志

在这里插入图片描述

  1. LOG4J日志工厂

    1. 在pom文件中导入log4j依赖

              <dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency>
      
    2. 在mybatis-config.xml核心配置文件中setting中设置

        <settings><setting name="logImpl" value="LOG4J"/></settings>
      

      打印出的日志

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xojW1N1D-1622602332291)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20210524183554031.png)]

6.分页

1. 通过sql

  1. 编写接口

2.通过RowBounds

3.通过第三方插件

7.使用注解开发

  1. 在mybatis-config.xml核心配置文件中配置映射

    可使用类绑定和包扫描

    <mappers>
<!--        <mapper class="com.song.dao.UserMapper"/>--><package name="com.song.dao"/>
<!-- 注解不能使用   <mapper resource="com/song/dao/UserMapper"/>-->
<!-- 注解不能使用   <mapper url="com.song.dao.UserMapper"/>--></mappers>
  1. 编写接口

    public interface UserMapper {//查询用户@Select("select * from user")List<User> getUserList();//通过id查询用户@Select("select * from user where id =#{id}")User getUser(int id);//增加用户@Insert("insert into user(name, pwd) VALUES (#{name},#{pwd})")int addUser(User user);//删除用户//当有多个基本数据类型应使用@Param注解 取值与注解相对应@Delete("delete from user where id=#{id1}")int deleteUser(@Param("id1") int id);//修改用户@Update("update user set name=#{name} , pwd=#{pwd}")int modifyUser(User user);
    }
    

    当有多个基本数据类型应使用@Param注解取值与注解相对应

  2. 编写测试类

    public class UserMapperTest {//获取用户列表@Testpublic void getUserList() {SqlSession sqlSession = MybatisUtil.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);List<User> userList = mapper.getUserList();for (User user : userList) {System.out.println(user);}sqlSession.close();}//通过Id查询用户@Testpublic void getUser() {SqlSession sqlSession = MybatisUtil.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);User user = mapper.getUser(1);System.out.println(user);sqlSession.close();}//添加用户@Testpublic void addUser() {SqlSession sqlSession = MybatisUtil.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);int i = mapper.addUser(new User(3, "宋俊芳", "123"));if (i > 0) {System.out.println("添加成功!!");sqlSession.commit();} else {System.out.println("添加失败!!");}sqlSession.close();}//删除用户@Testpublic void deleteUser() {SqlSession sqlSession = MybatisUtil.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);int i = mapper.deleteUser(11);if (i > 0) {System.out.println("删除成功!!");sqlSession.commit();} else {System.out.println("删除失败!!");}sqlSession.close();}//修改用户信息@Testpublic void modifyUser() {SqlSession sqlSession = MybatisUtil.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);int i = mapper.modifyUser(new User(0, "小明明", "234"));if (i > 0) {System.out.println("修改成功!!!");sqlSession.commit();} else {System.out.println("修改失败!!!");}sqlSession.close();}
    }

8. #{} 与 ${}

  1. #{}是预编译处理,$ {}是字符串替换。

  2. 在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;mybatis在处理 $ { } 时,就是把 ${ } 替换成变量的值。

  3. 使用 #{} 可以有效的防止SQL注入,提高系统安全性。

${param}传递的参数会被当成sql语句中的一部分,比如传递表名,字段名例子:(传入值为id)order by ${param} 则解析成的sql为:order by id#{parm}传入的数据都当成一个字符串,会对自动传入的数据加一个双引号例子:(传入值为id)select * from table where name = #{param}则解析成的sql为:select * from table where name = "id"为了安全,能用#的地方就用#方式传参,这样可以有效的防止sql注入攻击sql注入简介
直接上了百度的例子,感觉一看就清晰明了某个网站的登录验证的SQL查询代码为:strSQL = "SELECT * FROM users WHERE (name = '" + userName + "') and (pw = '"+ passWord +"');"恶意填入userName = "1' OR '1'='1";与passWord = "1' OR '1'='1";时,将导致原本的SQL字符串被填为strSQL = "SELECT * FROM users WHERE (name = '1' OR '1'='1') and (pw = '1' OR '1'='1');"也就是实际上运行的SQL命令会变成下面这样的strSQL = "SELECT * FROM users;"这样在后台帐号验证的时候巧妙地绕过了检验,达到无账号密码,亦可登录网站。所以SQL注入攻击被俗称为黑客的填空游戏

9.lombok

  1. 安装lombok插件

在这里插入图片描述

  1. 在大项目中导入lombok依赖
 <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.20</version></dependency>
  1. 注解

    写在类上

    1. @Data

在这里插入图片描述

  1. @AllArgsConstructor有参构造
    
  2. @NoArgsConstructor 无参构造
    

10.进阶

1.多对一嵌套查询

如: 多个学生对应一个老师
在这里插入图片描述

应用 resultMap 结果映射 association 关联

//Student类
public class Student {private int id;private String name;//外键//学生关联老师private Teacher teacher;
}//Teacher类
public class Teacher {private int id;private String name;}

eg:查询学生信息 id、 name 及教师姓名

1. 按照结果嵌套映射处理

  1. 编写dao层 Mapper接口

    public interface StudentMapper {//获取学生列表List<Student> getStudentList();
    }
    
  2. 编写Mapper.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--写到接口名-->
    <mapper namespace="com.song.dao.StudentMapper"><!--          方法名                  结果映射标识名                  --><select id="getStudentList" resultMap="Student-Teacher">select s.id sid, s.name sname, t.name tnamefrom student as s,teacher as twhere s.tid = t.id</select><!--按照结果嵌套映射处理 多对一 关键字 association 关联--><!-- 结果映射--><!--                     结果映射标识名       结果返回值类型--><resultMap id="Student-Teacher" type="Student"><result property="id" column="sid"/><result property="name" column="sname"/><association property="teacher" javaType="Teacher"><result property="name" column="tname"/></association></resultMap>
    </mapper>
    
  3. 测试

    public class StudentMapperTest {@Test//获取学生列表public void getStudentList(){SqlSession sqlSession = MybatisUtil.getSqlSession();StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);List<Student> students = mapper.getStudentList();for (Student student : students) {System.out.println(student);}sqlSession.close();}
    }
    

2.按照查询嵌套映射处理

  1. 编写dao层 Mapper接口

    public interface StudentMapper {//获取学生列表List<Student> getStudentList();//获取学生列表2List<Student> getStudentList2();
    }
  2. 编写Mapper.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--写到接口名-->
    <mapper namespace="com.song.dao.StudentMapper"><select id="getStudentList2" resultMap="Student-Teacher2">select *from mybatis.student</select><!--结果映射--><!--           结果映射标识名           结果返回值类型              --><resultMap id="Student-Teacher2" type="Student"><!--      实体属性名     数据库字段名     --><result property="id" column="id"/><result property="name" column="name"/><!--                                         实体类型        --><association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/><!--嵌套查询--></resultMap><!--嵌套查询表示名             返回值类型        --><select id="getTeacher" resultType="Teacher">select *from mybatis.teacher where id=#{tid}</select>
    </mapper>
    
  3. 测试

     @Test//获取学生列表2public void getStudentList2(){SqlSession sqlSession = MybatisUtil.getSqlSession();StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);List<Student> studentList2 = mapper.getStudentList2();for (Student student : studentList2) {System.out.println(student);}}
    

2.一对多嵌套查询

在这里插入图片描述

pojo:

//Student类
public class Student {private int id;private String name;//所属的教师private Teacher teacher;
}//Teacher类
public class Teacher {private int id;private String name;//老师包含的学生private List<Student> students;
}

查询Teacher 所管理的学生

复杂的属性 应用 resultMap 结果映射 collection 关联

javaType: 指定属性的类型

ofType: 集合中泛型的类型


1. 按照结果嵌套映射处理

  1. 编写dao层Mapper接口

    public interface TeacherMapper {//获取老师包含的信息List<Teacher> getTeacherList(@Param("tid") int id);
    }
  2. 编写mapper.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.song.dao.TeacherMapper"><!--结果映射 标识名 对应id--><select id="getTeacherList" resultMap="Teacher-Student">select s.id sid, s.name sname, t.name tnamefrom teacher t,student swhere s.tid = t.idand t.id = #{tid}</select><!--结果映射--><!--           结果映射标识名           结果返回值类型              --><resultMap id="Teacher-Student" type="Teacher"><result property="name" column="name"/><!--        实体类属性名         ofType集合泛型中类型        --><collection property="students" ofType="Student"><!--实体类属性名        sql中所查询的字段        --><result property="id" column="sid"/><result property="name" column="sname"/></collection></resultMap>
    </mapper>
    
  3. 测试

       @Testpublic void getTeacherList(){SqlSession sqlsession = MybatisUtil.getSqlsession();TeacherMapper mapper = sqlsession.getMapper(TeacherMapper.class);List<Teacher> teacherList = mapper.getTeacherList(2);for (Teacher teacher : teacherList) {System.out.println(teacher);}}
    

2. 按照查询嵌套映射处理

  1. 编写dao层Mapper接口

    public interface TeacherMapper {//获取老师包含的信息方法一List<Teacher> getTeacherList(@Param("tid") int id);//获取老师包含的信息方法二List<Teacher> getTeacherList2(@Param("tid") int id);
    }
    
  2. 编写mapper.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.song.dao.TeacherMapper"><select id="getTeacherList" resultMap="Teacher-Student">select s.id sid, s.name sname, t.name tnamefrom teacher t,student swhere s.tid = t.idand t.id = #{tid}</select><resultMap id="Teacher-Student" type="Teacher"><result property="name" column="name"/><collection property="students" ofType="Student"><result property="id" column="sid"/><result property="name" column="sname"/></collection></resultMap><select id="getTeacherList2" resultMap="Teacher-Student2">select *from mybatis.teacher where id=#{tid}</select><resultMap id="Teacher-Student2" type="Teacher"><collection property="students" javaType="ArrayList" ofType="Student" select="getStudent" column="id"/></resultMap><select id="getStudent" resultType="Student">select * from mybatis.student where tid=#{tid}</select></mapper>
    
  3. 测试

    public class TeacherMapperTest {@Testpublic void getTeacherList() {SqlSession sqlsession = MybatisUtil.getSqlsession();TeacherMapper mapper = sqlsession.getMapper(TeacherMapper.class);List<Teacher> teacherList = mapper.getTeacherList(2);for (Teacher teacher : teacherList) {System.out.println(teacher);}sqlsession.close();}@Testpublic void getTeacherList2() {SqlSession sqlsession = MybatisUtil.getSqlsession();TeacherMapper mapper = sqlsession.getMapper(TeacherMapper.class);List<Teacher> teacherList2 = mapper.getTeacherList2(1);for (Teacher teacher : teacherList2) {System.out.println(teacher);}sqlsession.close();}
    }
    

小结:

  • 多对一 : association(关联)

  • 一对多 : collection(集合)

  • javaType & ofType

    1. javaType :指定Java实体类属性的类型
    2. ofType : 指定集合中泛型的类型

11.动态SQL

  • 什么时动态SQL:

    根据不同场景选用不同的SQL语句

如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach
mapUnderscoreToCamelCase是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。true | falseFalse
默认值

在mybatis-config.xml核心配置文件中设置

  <!--        是否开启驼峰命名自动映射--><setting name="mapUnderscoreToCamelCase" value="true"/></settings><typeAliases><typeAlias type="com.song.pojo.Blog" alias="Blog"/>

0.if标签

  1. 编写dao层mapper接口

    public interface BLogMapper {//添加Blogint addBlog(Blog blog);//动态查询Blog IfList<Blog> queryBlogIf(Map map);
    }
    
  2. 编写mapper.xml配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.song.dao.BLogMapper"><insert id="addBlog" parameterType="Blog">insert into mybatis.blog(id, title, author, create_time, views)values (#{id}, #{title}, #{ author}, #{createTime}, #{views});</insert><select id="queryBlogIf" parameterType="map" resultType="Blog"><!--   where 1=1 不规范      -->select * from mybatis.blog where 1=1<if test="title!=null">and title=#{title}</if><if test="author!=null">and author=#{author}</if></select>
    </mapper>
    
  3. 测试

        public void queryBlogIf(){SqlSession sqlsession = MybatisUtil.getSqlsession();BLogMapper mapper = sqlsession.getMapper(BLogMapper.class);Map map = new HashMap();
    //        map.put("title","Mybatis如此简单");map.put("author","sjf");List<Blog> blogs = mapper.queryBlogIf(map);for (Blog blog : blogs) {System.out.println(blog);}sqlsession.close();}
    

1.where标签

where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。

eg:

改造 0. if 标签

<select id="queryBlogIf" parameterType="map" resultType="Blog">select * from mybatis.blog<where><if test="title!=null">and title=#{title}</if><if test="author!=null">and author=#{author}</if></where>
</select>

2.常用标签

1.choose

choose、when、otherwise

otherwise: 仅当 when中不成立时才会选择

when : 当满足以一个when时则不会再次选择其余的when 只会选择一个执行

  1. 编写dao层mapper接口

      //动态查询Blog chooseList<Blog> queryBlogChoose(Map map);
    
  2. 编写mapper.xml配置文件

    <select id="queryBlogChoose" resultType="Blog" parameterType="map">select * from mybatis.blog<where><choose><when test="title!=null">and title=#{title}</when><when test="author!=null">and author=#{author}</when><otherwise>and views=#{views}</otherwise></choose></where>
    </select>
    
  3. 测试

     //动态查询Blog choose@Testpublic void queryBlogChoose() {SqlSession sqlsession = MybatisUtil.getSqlsession();BLogMapper mapper = sqlsession.getMapper(BLogMapper.class);Map map = new HashMap();map.put("views",10000);map.put("title", "Spring如此简单");
    //        map.put("author", "狂神说");List<Blog> blogs = mapper.queryBlogChoose(map);for (Blog blog : blogs) {System.out.println(blog);}sqlsession.close();}
    

    2.set

    1. 用于动态更新语句的类似解决方案叫做 setset 元素可以用于动态包含需要更新的列,忽略其它不更新的列。

    2. set 元素会动态地在行首插入 SET 关键字 ,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的) 故set元素中必须有正确的sql语句。

      eg:更新Blog

      1. 编写dao层mapper接口

        //动态更新Blog set
        int updateBlogSet(Map map);
        
      2. 编写mapper.xml配置文件

        <update id="updateBlogSet" parameterType="map">update mybatis.blog<set><if test="title!=null">title=#{title},</if><if test="author!=null">author=#{author},</if></set><where>id=#{id}</where>
        </update>
        
      3. 测试

        //动态更新Blog choose
        @Test
        public void queryBlogSet() {SqlSession sqlsession = MybatisUtil.getSqlsession();BLogMapper mapper = sqlsession.getMapper(BLogMapper.class);Map map = new HashMap();map.put("title", "Spring如此简单1");map.put("author", "sjf");map.put("id","d1d1f1dd5b1a4661baccba8e88c8d3ec");mapper.updateBlogSet(map);sqlsession.commit();sqlsession.close();
        }
        

3.foreach标签

格式:

<select id="getBlogListForEach" parameterType="map" resultType="Blog">select * from mybatis.blog# 注释 select * from blog where( id=1 or id=2 or id=3 or id=4)<where><!--               collection从哪里(集合)遍历item被遍历集合中的元素open以```开始close 以```结束separator 通过什么来分割 --><foreach collection="ids" item="id" open="(" close=")" separator="or">id=#{id}</foreach></where></select>

eg:查询Blog id为1,2,3,4的blog

  1. 编写dao层mapper接口

    //动态查询遍历Blog forEach
    List<Blog> getBlogListForEach(Map map);
    
  2. 编写mapper.xml配置文件

    <select id="getBlogListForEach" parameterType="map" resultType="Blog">select * from mybatis.blog# 注释 select * from blog where( id=1 or id=2 or id=3 or id=4)<where><!--               collection从哪里(集合)遍历item被遍历集合中的元素open以```开始close 以```结束separator 通过什么来分割 --><foreach collection="ids" item="id" open="(" close=")" separator="or">id=#{id}</foreach></where></select>
    
  3. 测试

    @Test
    public void getBlogForEach(){SqlSession sqlsession = MybatisUtil.getSqlsession();BLogMapper mapper = sqlsession.getMapper(BLogMapper.class);HashMap map = new HashMap();ArrayList ids = new ArrayList();ids.add("1");ids.add("2");ids.add(3);ids.add(4);map.put("ids",ids);for (Object id : ids) {System.out.println(id.getClass());}List<Blog> blogs = mapper.getBlogListForEach(map);for (Blog blog : blogs) {System.out.println(blog);}sqlsession.close();
    }
    

4.小结

  • 动态SQL:不同情况下可以执行不同的SQL语句
  • 本质上是SQL语句逻辑的拼接
  • 使用时:
    1. 先写出应要执行的SQL语句(确保无误)
    2. 在mapper.xml中根据逻辑进行组装所需要的SQL语句

12.缓存

1.一级缓存

默认开启

基于SqlSession级别

查询相同数据

只执行一条SQL

Opening JDBC Connection
Created connection 2101636817.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7d446ed1]
==>  Preparing: select * from mybatis.user where id=?
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 张三, 234
<==      Total: 1
User(id=1, name=张三, pwd=234)
=================
User(id=1, name=张三, pwd=234)
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7d446ed1]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7d446ed1]
Returned connection 2101636817 to pool.

刷新缓存

  1. 两条相同查询语句间插入删除,更新,插入语句会导致缓存刷新
  2. 手动清理缓存(缓存失效)

eg:

Opening JDBC Connection
Created connection 315805187.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@12d2ce03]
==>  Preparing: select * from mybatis.user where id = ?
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 张三, 234
<==      Total: 1
User(id=1, name=张三, pwd=234)
==>  Preparing: update mybatis.user set name=? where id=?
==> Parameters: 宋俊芳(String), 1(Integer)
<==    Updates: 1
=================
==>  Preparing: select * from mybatis.user where id = ?
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 宋俊芳, 234
<==      Total: 1
User(id=1, name=宋俊芳, pwd=234)
Rolling back JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@12d2ce03]
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@12d2ce03]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@12d2ce03]
Returned connection 315805187 to pool.

查询两条不同数据

执行两条SQL(查询多条不同数据执行多条SQL)

Opening JDBC Connection
Created connection 1186339926.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@46b61c56]
==>  Preparing: select * from mybatis.user where id=?
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 张三, 234
<==      Total: 1
User(id=1, name=张三, pwd=234)
=================
==>  Preparing: select * from mybatis.user where id=?
==> Parameters: 2(Integer)
<==    Columns: id, name, pwd
<==        Row: 2, 李四, 234
<==      Total: 1
User(id=2, name=李四, pwd=234)
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@46b61c56]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@46b61c56]
Returned connection 1186339926 to pool.

若关闭使用二级缓存

Opening JDBC Connection
Created connection 1902430796.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7164ca4c]
==>  Preparing: select * from mybatis.user where id = ?
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 张三, 234
<==      Total: 1
User(id=1, name=张三, pwd=234)
=================
==>  Preparing: select * from mybatis.user where id = ?
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 张三, 234
<==      Total: 1
User(id=1, name=张三, pwd=234)
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7164ca4c]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7164ca4c]
Returned connection 1902430796 to pool.

2.二级缓存

基于nameSpeace级别

  1. 在mybatis-config.xml中设置

    <!--    显示开启缓存  二级\全局-->
    <settings><setting name="cacheEnabled" value="true"/>
    </settings>
    
  2. 开启缓存 在Mapper.xml中

<cache/>

遇到问题

org.apache.ibatis.cache.CacheException: Error serializing object.  Cause: java.io.NotSerializableException: com.song.pojo.User

解决方案: 序列化实体类 实现Serializable接口

测试:

实体类

//实现Serializable接口序列化
public class User implements Serializable {private int id;private String name;private String pwd;
}

测试

    //通过id获取用户@Testpublic void getUserById() {SqlSession sqlsession = MybatisUtil.getSqlsession();UserMapper mapper = sqlsession.getMapper(UserMapper.class);User u1 = mapper.getUserById(1);System.out.println(u1);sqlsession.close();//sqlsession关闭sqlsession.clearCache();//清除一级缓存System.out.println("=================");SqlSession sqlsession2 = MybatisUtil.getSqlsession();UserMapper mapper2 = sqlsession2.getMapper(UserMapper.class);User u2 = mapper2.getUserById(1);System.out.println(u2);sqlsession2.close();//sqlsession2关闭}

输出的日志:

同一个Mapper中的不同sqlSession也可共用二级缓存

Opening JDBC Connection
Created connection 2049051802.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7a220c9a]
==>  Preparing: select * from mybatis.user where id = ?
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 张三, 234
<==      Total: 1
User(id=1, name=张三, pwd=234)
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7a220c9a]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7a220c9a]
Returned connection 2049051802 to pool.
=================
As you are using functionality that deserializes object streams, it is recommended to define the JEP-290 serial filter. Please refer to https://docs.oracle.com/pls/topic/lookup?ctx=javase15&id=GUID-8296D8E8-2B93-4B9A-856E-0A65AF9B8C66
Cache Hit Ratio [com.song.dao.UserMapper]: 0.5
User(id=1, name=张三, pwd=234)

如关闭使用缓存

    <!--    通过id获取用户                                             关闭使用缓存    --><select id="getUserById" parameterType="_int" resultType="User" useCache="false">select *from mybatis.userwhere id = #{id}</select>

共查询两次:

Opening JDBC Connection
Created connection 1902430796.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7164ca4c]
==>  Preparing: select * from mybatis.user where id = ?
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 张三, 234
<==      Total: 1
User(id=1, name=张三, pwd=234)
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7164ca4c]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7164ca4c]
Returned connection 1902430796 to pool.
=================
Opening JDBC Connection
Checked out connection 1902430796 from pool.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7164ca4c]
==>  Preparing: select * from mybatis.user where id = ?
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 张三, 234
<==      Total: 1
User(id=1, name=张三, pwd=234)
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7164ca4c]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7164ca4c]
Returned connection 1902430796 to pool.

3.缓存原理

ectionImpl@7a220c9a]
Returned connection 2049051802 to pool.

As you are using functionality that deserializes object streams, it is recommended to define the JEP-290 serial filter. Please refer to https://docs.oracle.com/pls/topic/lookup?ctx=javase15&id=GUID-8296D8E8-2B93-4B9A-856E-0A65AF9B8C66
Cache Hit Ratio [com.song.dao.UserMapper]: 0.5
User(id=1, name=张三, pwd=234)


如关闭使用缓存```xml<!--    通过id获取用户                                             关闭使用缓存    --><select id="getUserById" parameterType="_int" resultType="User" useCache="false">select *from mybatis.userwhere id = #{id}</select>

共查询两次:

Opening JDBC Connection
Created connection 1902430796.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7164ca4c]
==>  Preparing: select * from mybatis.user where id = ?
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 张三, 234
<==      Total: 1
User(id=1, name=张三, pwd=234)
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7164ca4c]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7164ca4c]
Returned connection 1902430796 to pool.
=================
Opening JDBC Connection
Checked out connection 1902430796 from pool.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7164ca4c]
==>  Preparing: select * from mybatis.user where id = ?
==> Parameters: 1(Integer)
<==    Columns: id, name, pwd
<==        Row: 1, 张三, 234
<==      Total: 1
User(id=1, name=张三, pwd=234)
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7164ca4c]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7164ca4c]
Returned connection 1902430796 to pool.

3.缓存原理

在这里插入图片描述

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

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

设计模式导读助记

各个设计模式的详细介绍都已经完成&#xff0c;但是不经常用总会忘&#xff0c;所以我想用 一句话 总结设计模式&#xff0c;思考模式的真正意图&#xff0c;再用 一点提示 来思考代码如何实现 写在前面 我整理的设计模式这一个系列&#xff0c;主要是结合了以下几本书 : 《设…...

RT-Thrad|STM32F103+ESP8266 S01+RT-Thread联网之环境搭建(1/3)

文章目录前言硬件准备百问网STM32F103ESP8266 01SESP8266 介绍ESP8266 01S技术规格参数软件准备下载安装 Keil μVision5Pack Installer安装 ST-Link 驱动获取RT-Thread源码下载安装 RT-Thread env 工具文章列表 RT-Thrad|STM32F103ESP8266 S01RT-Thread联网之环境搭建(1/3)RT…...

Flask初体验

Flask初体验 flask框架是一个微型框架&#xff0c;但是微型框架不代表功能比其他框架少&#xff0c;并且flask的约束也比较少&#xff0c;使用更加方便。Flask安装 pip install flask 废话不多说直接上代码 from flask import Flaskapp Flask(__name__)app.route("/&qu…...

天眼查怎么删除信息_天眼查删除信息的方法介绍

天眼查信息怎么删除 天眼查风险信息怎么清除 天眼查问答信息怎么删除 天眼查法律诉讼信息可以删吗 天涯查上的信息删除怎么操作&#xff0c;天眼查成立于2014年&#xff0c;至今发展迅速&#xff0c;已经帮助了无数的企业和消费者&#xff0c;那么很多企业的天眼查信息有时候需…...

5.Random

用于生产一个随机数 步骤&#xff1a; 1.导包 import java.util.Random; 2.创建对象 Random random new Random();3.获取随机数 int number random.nextInt(10); //随机数的取值范围是[0,10),即大于等于&#xff0c;小于10 上面不能获取到10&#xff0c;若要获取到10&…...

Xxl-Job调度器原理解析

项目解析源码地址&#xff1a;https://gitee.com/lidishan/xxl-job-code-analysisxxl-job版本&#xff1a;2.3.0Xxl-Job分为执行器、调度器。而我们平时的客户端就属于一个执行器&#xff0c;执行器启动的时候会自动注册到调度器上&#xff0c;然后调度器进行远程调度。调度器初…...

51单片机利用锁存器控制数码管显示年月日时分秒

数码管模块中的两片74hc573&#xff0c;一片锁存段码&#xff0c;一片锁存位码&#xff0c;这样才能驱动8位数码管。74hc573是锁存器&#xff0c;用于数码管显示时通常是采用段选、片选共用同一组并口的驱动方式。 驱动数码管需要两个信号&#xff0c;一个是段选信号&#xff…...

webrtc之SVC实现(十)

一、概念 SVC&#xff08;可适性视频编码或可分级视频编码&#xff09;是传统H.264/MPEG-4 AVC编码的延伸&#xff0c;可提升更大的编码弹性&#xff0c;并具有时间可适性&#xff08;Temporal Scalability&#xff09;、空间可适性&#xff08;Spatial Scalability&#xff09…...

LeetCode 数值的整数次方

实现 pow(x, n) &#xff0c;即计算 x 的 n 次幂函数&#xff08;即&#xff0c;xn&#xff09;。不得使用库函数&#xff0c;同时不需要考虑大数问题。 示例 1&#xff1a; 输入&#xff1a;x 2.00000, n 10 输出&#xff1a;1024.00000 示例 2&#xff1a; 输入&#xf…...

python 继承和多态

在已有类的基础上创建新类&#xff0c;这其中的一种做法就是让一个类从另一个类那里将属性和方法直接继承下来&#xff0c;从而减少重复代码的编写。提供继承信息的我们称之为父类&#xff0c;也叫超类或基类&#xff1b;得到继承信息的我们称之为子类&#xff0c;也叫派生类或…...

JAVA 基础学习之 继承与方法覆写

1 继承引入​​​​​​​ 三个类都有重复的代码&#xff0c;可以把这共同的代码抽出去&#xff0c;抽出去放到另外一个类里面&#xff1b;下面的3个类和上面的类需要发生一点关系&#xff08;继承&#xff09;&#xff0c;上面的类叫做 父类&#xff08;超类&#xff0c;基类&…...

个性化个人主页html5模板

介绍&#xff1a; 个性化个人主页html5模板 网盘下载地址&#xff1a; http://kekewl.net/tARDuX5n02U0 图片&#xff1a;...

java IO教程《三》

缓冲区流讲解(Buffered) 什么是缓冲区&#xff1f; 缓冲流&#xff0c;也叫高效流&#xff0c;是对4个基本的File流的增强&#xff0c;所以也是4个流&#xff0c;按照数据类型分类&#xff1a; 字节缓冲流&#xff1a;BufferedInputStream&#xff0c;BufferedOutputStream字…...

elementUI-Tree 树形控件的使用

elementUI-Tree 树形控件的使用 实现效果&#xff1a; 控件的官方使用说明 控件要求返回的数据结构 {"success": true,"code": 20000,"message": "成功","data": {"items": [{"id": "1394579386…...

实训第一天以及第二天所学记录

实训第一天以及第二天所学记录 浏览器内核 IE&#xff1a;Trident Firefox&#xff1a;Gecko Chrome&#xff1a;Webkit / Blink Safari&#xff1a;Webkit Opera&#xff1a;Presto / Blink 在VScode中使用注释的快捷键 按住键盘的Ctrl/ 元素 &#xff08;标签 标记&…...

跨域请求

/* * Description: 配置文件 */ module.exports { publicPath: "./", devServer: { open: true, proxy: "http://106.15.179.105/api" //跨域路径 }, }; // proxy是代理的意思 // 代理跨域就是在欺骗浏览器 让浏览器认为你访问的还是 同…...

Mac os下通过Anaconda在远程服务器配置python虚拟环境

一、SSH管理软件 这里推荐一款本人正在使用的软件&#xff0c;Termius。Termius是一款非常好用而且漂亮的SSH客户端&#xff0c;能快速远程控制服务器&#xff0c;可以定制自己喜欢的主题.Termius不仅涵盖了Windows、Linux、OSX&#xff0c;还变态得支持Android和iOS&#xff…...

Labview需求(部分)

本人从事工控行业多年,有一些资源,目前labview的单子干不过来了,想找几个靠谱的labview工程师跟我合作,想做兼职,接单的labview工程师可以私聊我,另外我有一些项目还需要跟单片机工程师,plc工程师,fpga工程师合作,欢迎大家找我合作!以下是手里比较着急的项目,需要外包 需求1&am…...

2021java1年经验公司面试真题

1面我就省略了&#xff0c;主要就是看你的以前工作情况&#xff0c;以前工作内容能不能清晰表达&#xff0c;还有一些简单的java基础问题&#xff0c;大概20多分钟。二面就是40分钟基础&#xff0c;20分钟业务&#xff0c;10分钟个人情况。下面是二面问题 1.自我介绍 做一下自…...

Unity基础之C#核心篇笔记4:多态

Unity基础之C#核心篇笔记4&#xff1a;多态多态1.多态的概念2.解决的问题3.多态的实现4.总结抽象类和抽象方法1.抽象类2.抽象函数3.总结4.练习题接口1.接口的概念2. 接口的申明3.接口的使用4.接口可以继承接口5.显示实现接口6.总结7.练习题密封方法1.密封方法基本概念2.实例3.总…...

vue实现点击复制功能

废话不多说&#xff0c;直接上代码 html部分 <template><dvi><div click"">今天星期三<div></div> </template>js部分 <script> export default {data() {return {url:"http://www.4399.com/"};},methods: {c…...

[Jetson][转载]jetson上安装pytorch+torchvision教程

1. Jetpack默认已安装opencv、cuda、cudnn&#xff0c;故只需再安装pytorch即可&#xff0c;留意jetson是arm架构&#xff0c;需要下载对应的安装文件加以安装  2. pytorch的安装   查询Jetpack的版本 sudo -H pip3 install jetson-stats jetson_release   pytorch的whl文…...

配置odoo服务为80端口

配置odoo服务为80端口一. 下载nginx二. 配置nginx一. 下载nginx 下载nginx sudo apt install nginx检查nginx是否安装成功 nginx -v检查nginx配置文件是否有错 nginx -t 二. 配置nginx worker_processes 1; events {worker_connections 1024; } http {include mime.…...

清华大学迎来中国首个原创虚拟学生华智冰:智商、情商双高,颜值出众

2021 年 6 月 1 日&#xff0c;清华大学计算机系知识工程实验室迎来了中国首个原创虚拟学生 — 华智冰&#xff0c;清华大学为她办理了学生证和邮箱。 报道称&#xff0c;华智冰智商和情商双高&#xff0c;可以作诗、作画、创作剧本杀&#xff0c;还具有一定的推理和情感交互的…...

松松团队参加2021阿里云开发者大会

最近松松团队受阿里云开官方团队邀请&#xff0c;在上个周5.29号参加了阿里云在北京会议中心举办的2021年度开发者大会&#xff0c;收获满满! 本来松松团队作为阿里云多年的合作伙伴和官方代理商受邀参会应该是有松松团队创始人卢松松带队的&#xff0c;但是凑巧的是&#xff0…...

快捷实现转换农历

首先给大家看下效果图 第一步:新建一个js文件夹,把下列代码cv到文件夹中去. /*** 1900-2100区间内的公历、农历互转* charset UTF-8* Author jiangjiazhi* 公历转农历&#xff1a;calendar.solar2lunar(1987,11,01); //[you can ignore params of prefix 0]* 农历转公历&…...

git操作和笔记

使用本地的 git 工具操作 github 1. 网上创建好了有内容的仓库&#xff0c;本地去更新 将远端的仓库克隆到本地使用 git clone 地址 命令 远端地址分为两种 1. http 地址 2. ssh 地址 在克隆好的项目中更新一个 index.html将做好的更新提交到远端 在对应仓库打开 npm执行 git…...

移动互联网时代,短视频app开发有哪些参考?

微博发布“爱动短视频”&#xff0c;一下科技发布“波波视频”&#xff0c;陌陌直播发布“谁说”和“超有梗”…新短视频APP如雨后春笋不断涌现&#xff0c;并且大多数来头不小。 据相关统计分析&#xff0c;现阶段的短视频APP有101个&#xff0c;称得上“百团大战”。现在让我…...

2021年P气瓶充装考试APP及P气瓶充装免费试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 P气瓶充装考试APP是安全生产模拟考试一点通总题库中随机出的一套P气瓶充装免费试题&#xff0c;在公众号安全生产模拟考试一点通上点击P气瓶充装作业手机同步练习。2021年P气瓶充装考试APP及P气瓶充装免费试题 1、【…...

Python基础——文件操作

编程过程中总免不了需要对各种文件进行读与写&#xff0c;这篇文章主要总结对文件的常用操作&#xff0c;以备以后不时之需。 1、读文件 1.1、读文本文件 # 1.打开文件 file_object open(info.txt, modert, encodingutf-8)# 2.读取文件内容&#xff0c;并赋值给data data …...

为什么边缘概率密度是联合概率密度的积分_解读奥运积分排名:石宇奇为何第13 林丹谌龙未入前16...

亲关注天羽部落公众号在对话框输入&#xff1a;直播 即可收看 谢谢&#xff01;2019新加坡公开赛男单决赛 桃田贤斗vs金廷 2019新加坡公开赛男双决赛 嘉村健士/园田启悟vs阿山/ 阿山/亨德拉 2019新加坡公开赛混双视频 哈菲兹/维德佳佳VS陈炳顺/吴柳莹 2019新加坡公开赛男单四…...

vs为什么打了断点不断_2019年亚洲羽毛球锦标赛半决赛焦点对阵:陈雨菲vs山口茜 德查波/莎西丽vs王懿律/黄东萍 周天成vs石宇奇...

2019新加坡公开赛男单决赛 桃田贤斗vs金廷 2019新加坡公开赛男双决赛 嘉村健士/园田启悟vs阿山/ 阿山/亨德拉 2019新加坡公开赛混双视频 哈菲兹/维德佳佳VS陈炳顺/吴柳莹 2019新加坡公开赛男单四分之一视频 谌龙vs金廷 2018年BWF年终总决赛视频 男双A组 李俊慧/刘雨辰VS吉迪…...

vs为什么打了断点不断_2019世界羽毛球锦标赛决赛焦点对阵:郑思维/黄雅琼VS德差波/沙西丽...

亲关注天羽部落公众号在对话框输入&#xff1a;直播 即可收看 谢谢&#xff01;2019新加坡公开赛男单决赛 桃田贤斗vs金廷 2019新加坡公开赛男双决赛 嘉村健士/园田启悟vs阿山/ 阿山/亨德拉 2019新加坡公开赛混双视频 哈菲兹/维德佳佳VS陈炳顺/吴柳莹 2019新加坡公开赛男单四…...

Windows访问centOS的Tomcat

首先&#xff0c;先准备好jdk1.8和Tomcat的文件 点击此处获取jdk1.8和Tomcat的文件&#xff08;提取码&#xff1a;xxrc&#xff09; 配置IP地址 打开终端输入ifconfig&#xff0c;检查centOS的ip地址 根据要求&#xff0c;是要把ip地址最后一位改为自己的学号&#xff08;前…...

vs为什么打了断点不断_2019年亚洲羽毛球锦标赛决赛焦点对阵:桃田贤斗VS石宇奇 松本麻佑/永原和可那VS陈清晨/贾一凡 山口茜VS何冰娇...

2019新加坡公开赛男单决赛 桃田贤斗vs金廷 2019新加坡公开赛男双决赛 嘉村健士/园田启悟vs阿山/ 阿山/亨德拉 2019新加坡公开赛混双视频 哈菲兹/维德佳佳VS陈炳顺/吴柳莹 2019新加坡公开赛男单四分之一视频 谌龙vs金廷 2018年BWF年终总决赛视频 男双A组 李俊慧/刘雨辰VS吉迪…...

【转】Python三十年技术演变史

作者 | 宋天龙&#xff0c;TrueMetrics 合伙人&#xff0c;大数据技术专家&#xff0c;触脉咨询合伙人兼副总裁。擅长数据挖掘、建模、分析与运营&#xff0c;精通 端到端数据价值场景设计、业务需求转换、数据结构梳理、数据建模与学习以及数据工程交互。 出品 | AI科技大本…...

Python 传奇:30 年崛起之路 。

来源&#xff1a;AI科技大本营 作者 | 宋天龙&#xff0c;大数据技术专家&#xff0c;触脉咨询合伙人兼副总裁&#xff0c;前 Webtrekk 中国区技术和咨询负责人&#xff08;Webtrekk&#xff0c;德国的在线数据分析服务提供商&#xff09;。擅长数据挖掘、建模、分析与运营&am…...

Python传奇:30年崛起之路

作者 | 宋天龙&#xff0c;大数据技术专家&#xff0c;触脉咨询合伙人兼副总裁&#xff0c;前Webtrekk中国区技术和咨询负责人&#xff08;Webtrekk&#xff0c;德国的在线数据分析服务提供商&#xff09;。擅长数据挖掘、建模、分析与运营&#xff0c;精通端到端数据价值场景设…...

44岁的微软如何刷新未来?

整理 | 伍杏玲出品 | AI科技大本营&#xff08;ID&#xff1a;rgznai100&#xff09;在当今的“云”时代&#xff0c;很多企业在多个云计算平台部署应用&#xff0c;且需要统一管理和保护应用。在微软Ignite 2019 大会上&#xff0c;为了让企业轻松地在任何类型的基础设施平台上…...

细数Python三十年技术演变史——萌发于小众,崛起于AI

作者 | 宋天龙 来源 | AI科技大本营 导语&#xff1a;一切都始于1989年的那个圣诞节&#xff0c;Python的诞生并不算恰逢其时&#xff0c;它崛起充满了机遇巧合&#xff0c;也有其必然性。三十年间&#xff0c;Python技术不断更迭&#xff0c;生态逐渐完善&#xff0c;加上互联…...

4分钟看尽Top编程语言15年沉浮:C#默Java泪,Python终上位!

大数据文摘出品作者&#xff1a;宁静哪种编程语言最火爆&#xff1f;在不同的时代&#xff0c;这个问题也有着不同的答案&#xff0c;而一部编程语言的使用人数变迁史&#xff0c;实际上也是一部计算机世界的成长编年史。一位名叫PYPL的油管up主很尽心地统计了从2004年到2019年…...

【机器学习百科全书目录】PRML ESL MLAPP 西瓜书 花书 RLAI 统计学习方法 蒲公英书

文章目录机器学习百科全书目录Pattern Recognition and Machine LearningThe Elements of Statistical Learning (Second edition)Machine Learning A Probabilistic Perspective西瓜书花书Reinforcement Learning:An Introduction (Second edition)统计学习方法&#xff08;第…...

2017高考计算机试卷,2017年高考模拟试卷 信息技术卷.doc

2017年高考模拟试卷信息技术卷要点2017年高考模拟试卷卷信息及信息的获取信息技术的发展和应用a选择题(1)2第二单元信息的加工字处理批注和修订c选择题(4)2表处理表格数据的基本操作c填空题(13)1表格数据的排序筛选和图表制作c1数据分析及综合应用c11算法的常用表示方法顺序、选…...

经验分享(三)一个程序员的体会

昨天&#xff0c;叔叔给我介绍了一份工作&#xff0c;搞推销&#xff0c;完成任务给1000 元&#xff0c;完不成任务给500 元。我又一次拒绝了&#xff0c;爸爸问我为什么不干&#xff0c;我说不想从事这个行业。这次爸爸终于发怒了&#xff0c;真说我“不要脸”&#xff0c;还说…...

手把手教你做智能合约开源|多文件合约开源|引用文件开源

本文手把手教你使用 区块链浏览器 验证智能合约的三种方式。 验证单一 Solidity 文件 在开始验证之前&#xff0c;我们需要首先部署智能合约。进入 Remix IDE&#xff0c;创建一个合约新文件。复制粘贴下面的代码&#xff1a; // SPDX-License-Identifier: MITpragma solidit…...

一个程序员的体会

昨天&#xff0c;叔叔给我介绍了一份工作&#xff0c;搞推销&#xff0c;完成任务给1000元&#xff0c;完不成任务给500元。我又一次拒绝了&#xff0c;爸爸问我为什么不干&#xff0c;我说不想从事这个行业。这次爸爸终于发怒了&#xff0c;真说我“不要脸”&#xff0c;还说了…...

LENZE E84AVSCE1534VX0/E94ASHEO174A33ENPM/E94ASHEO134A33NNPM/E84AVSCE2234VX0/E84AVSCE1534VX0

W;1 8 03 0 1 7 77 5 9 LENZE E84AVSCE1534VX0/E94ASHEO174A33ENPM/E94ASHEO134A33NNPM/E84AVSCE2234VX0/E84AVSCE1534VX0LENZE E84AVSCE1534VX0/E94ASHEO174A33ENPM/E94ASHEO134A33NNPM/E84AVSCE2234VX0/E84AVSCE1534VX0LENZE E84AVSCE1534VX0/E94ASHEO174A33ENPM/E94ASHE...

^_^ 给力,找了好久,终让我找到了,好多VB源码免费下载,路过的朋友快看看吧

找了好多源码,不知道在那里和朋友们分享啊,,,,,,,,,,,,,,,,,,,,, www.2e3.org/upload/文件属性修改器&#xff08;比较完善&#xff09;.rar http://www.2e3.org/upload/结束这在运行的文件&#xff08;非常好用&#xff09;.rarhttp://www.2e3.org/upload/支持多种格式的VB网络…...

论《计算机网络技术》与素质教育

论文摘要&#xff1a;计算机网络技术的迅猛发展&#xff0c;使社会发生了巨大的变革&#xff0c;也必然促使课堂教学过程产生深刻的变革&#xff0c;这种深刻变革将会改变教学模式、内容、方法&#xff0c;并最终导致整个教育思想的根本变革。本文旨在为计算机网络技术的教学在…...

各种css新闻页样例

下面这些模板可以随意添加在你的ruby on rails项目中的 views里面实现前台的新闻列表 1&#xff1a;有序新闻列表<style type"text/css">body{margin:0 auto; padding:0;}#pagelist{ font-size:12px; margin:20px; border:4px #ccc solid; padding:10px; list-…...