JavaSSM框架从入门到精通!第三天(MyBatis(二))!

四、Mapper 的动态代理


1. 引入
在上面的 CURD 例子中,我们发现:Dao 层的实现类的每一个方法仅仅是通过 SqlSession 对象的相关 API 定位到映射文件 mapper 中的 SQL 语句,真正对数据库操作的工作实际上是有 Mybatis 框架通过 mapper 中的 SQL 语句完成的,所以 Dao 层的实现类并没有做什么实质性的工作,所以,Mybatis 就可以抛开 Dao 层实现类,直接定位到 mapper 中的 SQL 语句来操作数据库,这种 Dao 层实现类的实现方式称为 Mapper 动态代理,即使用动态代理对象替换掉原来的 Dao 层实现类。
2. Mapper 动态代理特点 
Mapper 动态代理方式不需要程序员去实现 Dao 层接口,接口的实现由 Mybatis 结合映射文件自动生成动态代理对象来实现的。
3. 要实现 mapper 的动态代理,需要满足如下条件:
(1) 映射文件 mapper 需要和 Dao 层接口在同一个包下面:

(2) 映射文件的名称需要和 Dao 层接口的名称相同

(3) 映射文件 mapper 中的 namespace 的名称必须是 Dao 层接口的全类名

(4) 映射文件 mapper 中的 SQL 语句的 id 名称需要和 Dao 层接口的方法名相同:

(5) 删除 Dao 层的实现类

(6) 删除 Dao 层接口的 selectStudentMap() 方法以及映射文件配置,因为 Mapper 动态代理不支持 map 查询

(7) 修改主配置文件 mybatis.xml 中引入 mapper 映射文件的方式: 

(8) 将 Student 的 tscore 属性改过来,mapper 也要改
Student.java:

package com.edu.beans;

public class Student {
private long id;
private String name;
private int age;
private double score;

    public Student() {
}

    public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}

    public Student(long id, String name, int age, double score) {
this.id = id;
this.name = name;
this.age = age;
this.score = score;
}

    public long getId() {
return id;
}

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

    public String getName() {
return name;
}

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

    public int getAge() {
return age;
}

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

    public double getScore() {
return score;
}

    public void setScore(double score) {
this.score = score;
}

    @Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
}

IStudentDao.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">
<!--
mybatis-3-mapper.dtd:是 mybatis 映射文件的约束文件,约束文件的位置在 mybatis 的核心jar包(mybatis-3.3.0.jar)
的这里:org.apache.ibatis.builder.xml.mybatis-3-mapper.dtd
-->
<mapper namespace="com.edu.dao.IStudentDao">
<!--
定义了一个插入的 SQL 语句,其中 #{name} 为动态参数,也就是 "?" 占位符,该动态参数的名称要和
前面方法(void insertStudent(Student student))传过来的对象(student)的属性同名,这样 student 对象的属性值
就会给这些动态参数赋值
-->
<insert id="insertStudent" parameterType="Student">
insert into student(name,age,score) values(#{name},#{age},#{score})
</insert>

    <insert id="insertStudentCatchId">
insert into student(name,age,score) values(#{name},#{age},#{score})
<!--
<selectKey>:使用新插入记录的 id 值初始化被插入的对象,即初始化方法参数 student,它的属性有:
keyProperty="id":要插入这个对象的属性名,这里就是指给方法参数 Student 的 id 属性赋值
resultType="long":这个 id 属性的数据类型
order="AFTER":指明主键 id 的值在 insert 语句执行时的生成时机,MySQL 是 AFTER,即在 insert 之后生成 id 值,
Oracle 是 BEFORE,即在 insert 之前生成 id 值
-->
<selectKey keyProperty="id" resultType="long" order="AFTER">
select last_insert_id();
</selectKey>
</insert>

    <delete id="deleteStudentById">
<!--注意:如果动态参数只有一个,可以使用任意名称,不用和方法参数同名,例如这里的 #{xxx} 而不是 #{id}-->
delete from student where id=#{xxx}
</delete>

    <update id="updateStudent">
<!--这里除了 #{id} 是旧值,其他都是新值-->
update student set name=#{name},age=#{age},score=#{score} where id=#{id}
</update>

    <!--
resultType="Student":将返回结果集中的每一条记录封装成 Student 类型,这里要给出全类名,我们已经在主配置文件配置了
别名,就可以写别名
-->
<select id="selectAllStudents" resultType="Student">
select * from student
</select>

    <!--
<resultMap>:完成表字段到 JavaBean 属性的映射,从而可以将查询结果封装成 JavaBean 对象,它的属性:
id="studentMap":resultMap 的 id 名称
type="Student":查询记录封装成的 JavaBean 类型
-->
<resultMap id="studentMap" type="Student">
<!--完成表字段到 JavaBean 属性的映射-->
<!--<id>表示主键字段,column="id"是表的字段名,property="id"是 JavaBean 的属性名-->
<id column="id" property="id"/>
<!--其他的非主键字段的映射使用 <result> 标签-->
<result column="name" property="name"/>
<result column="age" property="age"/>
<result column="score" property="score"/>
</resultMap>
<select id="selectStudentById" resultMap="studentMap">
select id,name,age,score from student where id=#{xxx}
</select>

    <select id="selectStudentsByMap" resultType="Student">
select * from student where name=#{map.name} and age = #{map.age}
</select>

<!--    <select id="selectStudentsByName" resultType="Student">
select * from student where name like concat('%',#{xxx},'%')
</select>-->

    <select id="selectStudentsByName" resultType="Student">
<!--注意:'%' 和 #{xxx} 之间有一个空格-->
select * from student where name like '%' #{xxx} '%'
</select>
</mapper>

(9) 在测试类 StudentTest 中通过 SqlSession 的 getMapper() 方法获取 Dao 层接口的动态代理对象来测试

package com.edu.test;


import com.edu.beans.Student;
import com.edu.dao.IStudentDao;
import com.edu.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

//JUnit 的测试类
public class StudentTest {
private SqlSession session;
private IStudentDao studentDao;

    @Before //被 @Before 注解的方法为初始化方法,它会在每次 @Test 修饰的方法执行之前执行一次,完成初始化工作
public void setUp(){
session = MybatisUtils.getSqlSession();
//获取 Dao 层接口的动态代理对象(Mapper 的动态代理)
studentDao = session.getMapper(IStudentDao.class);
}

    @After //被 @After 注解的方法为销毁方法,它会在 @Test 修饰的方法执行之后执行一次,完成资源的销毁工作
public void tearDown(){
if(session != null){
session.close();
}
}

    @Test //被 @Test 注解的方法为测试方法,可以有多个这样的方法
public void testInsertStudent(){
studentDao.insertStudent(new Student("张三",21,98.5));
session.commit();//动态代理对象只会根据映射文件中的 SQL 标签去执行 SQL 语句,并不会提交事务,需要我们自己提交
}

    @Test
public void testInsertStudentCatchId(){
Student student = new Student("王五",21,98.5);
System.out.println("插入数据前,student=" + student);
studentDao.insertStudentCatchId(student);
System.out.println("插入数据后,student=" + student);
session.commit();//动态代理对象只会根据映射文件中的 SQL 标签去执行 SQL 语句,并不会提交事务,需要我们自己提交
}

    @Test
public void testDeleteStudentById(){
studentDao.deleteStudentById(4L);
session.commit();//动态代理对象只会根据映射文件中的 SQL 标签去执行 SQL 语句,并不会提交事务,需要我们自己提交
}

    @Test
public void testUpdateStudent(){
Student student = new Student(3,"小王",21,98.5);
studentDao.updateStudent(student);
session.commit();//动态代理对象只会根据映射文件中的 SQL 标签去执行 SQL 语句,并不会提交事务,需要我们自己提交
}

    @Test
public void testSelectAllStudents(){
List<Student> students = studentDao.selectAllStudents();
for (Student student :
students) {
System.out.println(student);
}
}

    @Test
public void testSelectStudentById(){
Student student = studentDao.selectStudentById(3L);
System.out.println(student);
}

    @Test
public void testSelectStudentsByMap(){
Map<String,Student> map = new HashMap<>();
Student student = new Student();
student.setName("晓晓");
student.setAge(21);
map.put("map", student);
List<Student> students = studentDao.selectStudentsByMap(map);
for (Student stu :
students) {
System.out.println(stu);
}
}

    @Test
public void testSelectStudentsByName(){
List<Student> students = studentDao.selectStudentsByName("晓");
for (Student student :
students) {
System.out.println(student);
}
}
}

然后我们在获取动态代理对象处打一个断点,以调试方式执行:

然后我们往下走一步,查看:

可以看到生成的 studentDao 是一个代理对象。
然后我们重新来调试执行一次,我们跟进到 getMapper() 方法中,不断跟进去:

可以看到,Mybatis 的 Mapper 动态代理使用的就是 JDK 的动态代理来创建代理对象的。


五、动态 SQL


1. 动态 SQL
主要用于解决查询条件不确定的情况,在程序运行期间,根据用户提交的查询条件进行查询,提交的条件不同,执行的 SQL 也不同,若将每个不同条件逐一列出,在进行排列组合,将会出现大量的 SQL 语句,我们可以使用动态 SQL 来解决这样的问题。
2. 动态 SQL 的示例

3. 动态 SQL 概述
动态 SQL,即通过 Mybatis 提供的各种标签对条件做出判断以实现动态拼接 SQL 语句, 常用的动态 SQL 标签有<if>、<where>、<choose>、<foreach>等等,有意思的是,这些动态 SQL 标签和 JSTL 语法非常相似。
4. 开发步骤
(1) 准备数据库表

(2) 定义实体类

package com.edu.beans;

public class Student {
private long id;
private String name;
private int age;
private double score;

    public Student() {
}

    public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}

    public Student(long id, String name, int age, double score) {
this.id = id;
this.name = name;
this.age = age;
this.score = score;
}

    public long getId() {
return id;
}

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

    public String getName() {
return name;
}

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

    public int getAge() {
return age;
}

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

    public double getScore() {
return score;
}

    public void setScore(double score) {
this.score = score;
}

    @Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
}

(3) 测试类:

package com.edu.test;

import com.edu.dao.IStudentDao;
import com.edu.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;

//JUnit 的测试类
public class DynamicSQLTest {
private SqlSession session;
private IStudentDao studentDao;

    @Before //被 @Before 注解的方法为初始化方法,它会在每次 @Test 修饰的方法执行之前执行一次,完成初始化工作
public void setUp(){
session = MybatisUtils.getSqlSession();
//获取 Dao 层接口的动态代理对象(Mapper 的动态代理)
studentDao = session.getMapper(IStudentDao.class);
}

    @After //被 @After 注解的方法为销毁方法,它会在 @Test 修饰的方法执行之后执行一次,完成资源的销毁工作
public void tearDown(){
if(session != null){
session.close();
}
}


}

5. <if> 标签
该标签中的 test 属性为 true 时,他会将它包含的 SQL 片段拼接在其所在 SQL 语句中
示例:查询满足动态条件的学生信息:
(1) 修改 Dao 层接口

package com.edu.dao;

import com.edu.beans.Student;

import java.util.List;

public interface IStudentDao {
List<Student> selectStudentIf(Student student);
}

(2) 修改 IStudentDao.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">
<!--
mybatis-3-mapper.dtd:是 mybatis 映射文件的约束文件,约束文件的位置在 mybatis 的核心jar包(mybatis-3.3.0.jar)
的这里:org.apache.ibatis.builder.xml.mybatis-3-mapper.dtd
-->
<mapper namespace="com.edu.dao.IStudentDao">
<select id="selectStudentIf" resultType="Student">
<!--这里的 where 1=1 是为了保证如果后面的 if 语句不满足,前面的 SQL 语句也是一条有效的语句,if 条件满足,也是一条有效的语句-->
select id,name,age,score from student where 1=1
<!--如果传过来的 name 属性不为 null,且不是空字符串,那么就拼接如下的 SQL 片段-->
<if test="name != null and name != ''">
and name like '%' #{name} '%'
</if>
<!--如果传过来的 age > 0,就拼接如下的 SQL 片段-->
<if test="age > 0">
and age > #{age}
</if>
</select>
</mapper>
(3) 测试类 DynamicSQLTest

6. <where>标签
<if> 标签有个比较麻烦的地方,就是必须使用 where 1=1 子句,因为若 where 条件后<if> 都不满足,需要 where 1=1 来保证前面的 SQL 语句是一个有效的语句,当然,<if>满足时, where 1=1 也能保证拼接后的 SQL 语句是有效语句。使用<where>标签,在有条件的时候,会自动添加 where 子句,没有条件的时候,不会添加 where 子句 
(1) 修改 IStudentDao.java
package com.edu.dao;

import com.edu.beans.Student;

import java.util.List;

public interface IStudentDao {
List<Student> selectStudentIf(Student student);
List<Student> selectStudentWhere(Student student);
}
(2) 修改 IStudentDao.xml 映射文件
<select id="selectStudentWhere" resultType="Student">
<!--这里的 where 1=1 是为了保证如果后面的 if 语句不满足,前面的 SQL 语句也是一条有效的语句,if 条件满足,也是一条有效的语句-->
select id,name,age,score from student
<!--如果下面的 <if> 语句都不满足条件,则不会条件 where 子句,如果有一个 <if> 条件满足,就会添加 where 子句-->
<where>
<!--如果传过来的 name 属性不为 null,且不是空字符串,那么就拼接如下的 SQL 片段-->
<if test="name != null and name != ''">
<!--第一个 <if> 语句可以省略 and,但是其他的 <if> 语句必须加上 and-->
and name like '%' #{name} '%'
</if>
<!--如果传过来的 age > 0,就拼接如下的 SQL 片段-->
<if test="age > 0">
<!--其他 <if> 语句的 and 不能省略-->
and age > #{age}
</if>
</where>
</select>
(3) 测试类 DynamicSQLTest

7. <choose>...<when>...<otherwise>:类似于switch...case
对于 <choose> 标签,会从第一个 <when> 开始逐个向后进行条件判断,若某个 <when> 的 test 属性值为 true 的情况,则拼接其 SQL 片段,然后直接结束 <choose> 标签,其他的不执行 <when>,直到所有的 <when> 都不满足时,执行 <otherwise>。
(1) 修改 IStudentDao.java

(2) 修改StudentDao.xml:

(3) 测试类

从上可知,“王”的姓名满足第一个 <when> 之后,就不会去判断第一个 age 的 <when>。
8. <foreach> 标签:遍历集合
(1) 遍历数组

1) 修改 IStudentDao.java

package com.edu.dao;

import com.edu.beans.Student;

import java.util.List;

public interface IStudentDao {
List<Student> selectStudentIf(Student student);
List<Student> selectStudentWhere(Student student);
List<Student> selectStudentChoose(Student student);
List<Student> selectStudentForEachArray(Object[] studentIds);
}

2) 修改 IStudentDao.xml
<select id="selectStudentForEachArray" resultType="Student">
select id,name,age,score from student
<!--
这里的 array 是指接口方法传过来的参数是一个数组,而且这里只是使用 array 这个名字,不能是其他名称,
array.length 表示数组的长度
-->
<if test="array != null and array.length > 0">
where id in
<!--
collection:待遍历的集合,这里是数组,统一写成 array
open:遍历项放入的地方,这里以"("开始
item:每一个遍历项
separator:每个遍历项之间以","分割
close:遍历项放入的地方,这里以")"结束
最终遍历出来得到的 SQL 语句形式如下:select id,name,age,score from student where id in (2,3,4)
-->
<foreach collection="array" open="(" item="myid" separator="," close=")">
#{myid}
</foreach>
</if>
</select>
3) 测试类

(2) 遍历泛型为基本类型的 List
1) 修改 IStudentDao.java

package com.edu.dao;

import com.edu.beans.Student;

import java.util.List;

public interface IStudentDao {
List<Student> selectStudentIf(Student student);
List<Student> selectStudentWhere(Student student);
List<Student> selectStudentChoose(Student student);
List<Student> selectStudentForEachArray(Object[] studentIds);
List<Student> selectStudentForEachList(List<Integer> studentIds);
}
2) 修改 IStudentDao.xml
<select id="selectStudentForEachList" resultType="Student">
select id,name,age,score from student
<!--
这里的 list 是指接口方法传过来的参数是一个 List,而且这里只是使用 list 这个名字,不能是其他名称,
list.size 表示集合的大小
-->
<if test="list != null and list.size > 0">
where id in
<!--
collection:待遍历的集合,这里是List,统一写成 list
open:遍历项放入的地方,这里以"("开始
item:每一个遍历项
separator:每个遍历项之间以","分割
close:遍历项放入的地方,这里以")"结束
最终遍历出来得到的 SQL 语句形式如下:select id,name,age,score from student where id in (2,3,5)
-->
<foreach collection="list" open="(" item="myid" separator="," close=")">
#{myid}
</foreach>
</if>
</select>
3) 测试类

(3) 遍历泛型为自定义类型的 List
1) 修改 IStudentDao.java
package com.edu.dao;

import com.edu.beans.Student;

import java.util.List;

public interface IStudentDao {
List<Student> selectStudentIf(Student student);
List<Student> selectStudentWhere(Student student);
List<Student> selectStudentChoose(Student student);
List<Student> selectStudentForEachArray(Object[] studentIds);
List<Student> selectStudentForEachList(List<Integer> studentIds);
List<Student> selectStudentForEachList2(List<Student> students);
}
2) 修改 IStudentDao.xml
<select id="selectStudentForEachList2" resultType="Student">
select id,name,age,score from student
<!--
这里的 list 是指接口方法传过来的参数是一个 List,而且这里只是使用 list 这个名字,不能是其他名称,
list.size 表示集合的大小
-->
<if test="list != null and list.size > 0">
where id in
<!--
collection:待遍历的集合,这里是List,统一写成 list
open:遍历项放入的地方,这里以"("开始
item:每一个遍历项
separator:每个遍历项之间以","分割
close:遍历项放入的地方,这里以")"结束
最终遍历出来得到的 SQL 语句形式如下:select id,name,age,score from student where id in (2,3,5)
-->
<foreach collection="list" open="(" item="student" separator="," close=")">
#{student.id}
</foreach>
</if>
</select>
3) 测试类

9. <sql> 标签
<sql> 标签可以用来定义一个 SQL 片段,以便复用,其他地方要用到的时候,通过 <include> 标签引入即可:
(1) 修改 IStudentDao.java
package com.edu.dao;

import com.edu.beans.Student;

import java.util.List;

public interface IStudentDao {
List<Student> selectStudentIf(Student student);
List<Student> selectStudentWhere(Student student);
List<Student> selectStudentChoose(Student student);
List<Student> selectStudentForEachArray(Object[] studentIds);
List<Student> selectStudentForEachList(List<Integer> studentIds);
List<Student> selectStudentForEachList2(List<Student> students);
List<Student> selectStudentBySQL(Student student);
}
(2) 修改 IStudentDao.xml
<sql id="selectHead">
select id,name,age,score from student
</sql>
<select id="selectStudentBySQL" resultType="Student">
<include refid="selectHead"/>
<!--如果下面的 <if> 语句都不满足条件,则不会条件 where 子句,如果有一个 <if> 条件满足,就会添加 where 子句-->
<where>
<!--如果传过来的 name 属性不为 null,且不是空字符串,那么就拼接如下的 SQL 片段-->
<if test="name != null and name != ''">
<!--第一个 <if> 语句可以省略 and,但是其他的 <if> 语句必须加上 and-->
and name like '%' #{name} '%'
</if>
<!--如果传过来的 age > 0,就拼接如下的 SQL 片段-->
<if test="age > 0">
<!--其他 <if> 语句的 and 不能省略-->
and age > #{age}
</if>
</where>
</select>
(3) 测试类:

10. @Param 注解
Mybatis 中的 @Param 注解:该注解指定的名称要作为 SQL 语句中动态参数的前缀,例如:
(1) 修改 IStudentDao.java
package com.edu.dao;

import com.edu.beans.Student;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface IStudentDao {
List<Student> selectStudentIf(Student student);
List<Student> selectStudentWhere(Student student);
List<Student> selectStudentChoose(Student student);
List<Student> selectStudentForEachArray(Object[] studentIds);
List<Student> selectStudentForEachList(List<Integer> studentIds);
List<Student> selectStudentForEachList2(List<Student> students);
List<Student> selectStudentBySQL(Student student);
List<Student> selectStudentWhereParam(@Param("stu") Student student, @Param("myage") int age);
}
(2) 修改 IStudenDao.xml
<select id="selectStudentWhereParam" resultType="Student">
select id,name,age,score from student
<!--如果下面的 <if> 语句都不满足条件,则不会条件 where 子句,如果有一个 <if> 条件满足,就会添加 where 子句-->
<where>
<!--如果传过来的 name 属性不为 null,且不是空字符串,那么就拼接如下的 SQL 片段-->
<!--如果接口方法参数是一个对象,并且使用的 @Param 注解,那么再使用方法参数时,要加上@Param指定的前缀 "stu."-->
<if test="stu.name != null and stu.name != ''">
<!--第一个 <if> 语句可以省略 and,但是其他的 <if> 语句必须加上 and-->
and name like '%' #{stu.name} '%'
</if>
<!--如果传过来的 age > 0,就拼接如下的 SQL 片段-->
<!--如果接口方法参数是基本类型,且被 @Param 注解,那么这里的动态参数名就是 @Param 指定的名称-->
<if test="myage > 0">
<!--其他 <if> 语句的 and 不能省略-->
and age > #{myage}
</if>
</where>
</select>
(3) 测试类

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

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

相关文章

大模型应用发展与Agent前沿技术趋势(下)

Agent技术的行业应用与实践案例 金融领域的Agent应用 金融行业是大模型Agent技术应用最为广泛的领域之一&#xff0c;涵盖了风险评估、投资决策、客户服务等多个方面。在金融风控领域&#xff0c;Agent系统通过结合大模型的语义理解能力和强化学习的决策优化能力&#xff0c;能…

94. 城市间货物运输 I, Bellman_ford 算法, Bellman_ford 队列优化算法

94. 城市间货物运输 IBellman_ford 算法Bellman_ford 算法 与 dijkstra算法 相比通用性更强。dijkstra算法解决不了负权边的问题&#xff0c;因为Dijkstra基于贪心策略&#xff0c;一旦一个节点被从队列中取出&#xff08;标记为已解决&#xff09;&#xff0c;它就假定已经找到…

如何使用Prometheus + Grafana + Loki构建一个现代化的云原生监控系统

如何使用 Prometheus + Grafana + Loki 构建一个现代化的云原生监控系统。这套组合被誉为监控领域的“瑞士军刀”,功能强大且生态极佳。 一、核心组件概念介绍 在搭建之前,深刻理解每个组件的角色和职责至关重要。 1. Prometheus(指标监控与时序数据库) 角色:系统的“核…

JavaScript Object 操作方法及 API

一、对象创建方式1.字面量创建&#xff08;最常用&#xff09;const obj { name: "张三", age: 25 };2.构造函数创建const obj new Object(); obj.name "李四";3.Object.create()&#xff08;指定原型&#xff09;const proto { greet: () > "…

pta乙级题目day1

第1天&#xff1a;输入输出与运算&#xff08;6题&#xff09;1001 害死人不偿命的(3n1)猜想&#xff08;基础运算&#xff09;★1006 换个格式输出整数&#xff08;格式化输出&#xff09;★1016 部分AB&#xff08;数字提取&#xff09;★★1046 划拳&#xff08;多输入处理&…

在VSCode中配置.NET项目的tasks.json以实现清理、构建、热重载和发布等操作

在 VS Code 中配置 .NET 开发任务的完整指南 引言 重要提醒&#xff1a;对于 .NET 开发&#xff0c;强烈推荐使用 Visual Studio&#xff0c;它提供了最完整和稳定的开发体验。如果你像我一样"蛋疼"想要尝试 VS Code&#xff0c;请确保安装了 C# 开发扩展包&#x…

EmEditor文本编辑器v25.3.0专业版,专业文本编辑,高亮显示,无限撤消

[软件名称]: EmEditor文本编辑器v25.3.0专业版 [软件大小]: 37.7 MB [软件大小]: 夸克网盘 | 百度网盘 软件介绍 EmEditor 是一款功能强大且非常实用的文本编辑器。它启动速度快&#xff0c;完全可以替代 Windows 自带的记事本&#xff0c;轻松应对日常文本编辑任务。它对 …

【spring security】权限管理组件执行流程详解

&#x1f3af; 权限管理组件执行流程详解 &#x1f3d7;️ 组件架构图 ┌─────────────────────────────────────────────────────────────┐ │ HTTP请求 …

redis怎么保障双写一致性

redis做为缓存&#xff0c;mysql的数据如何与redis进行同步呢&#xff1f;&#xff08;双写一致性&#xff09;候选人&#xff1a;嗯&#xff01;就说我最近做的这个项目&#xff0c;里面有xxxx&#xff08;根据自己的简历上写&#xff09;的功能&#xff0c;需要让数据库与red…

异常值检测:孤立森林模型(IsolationForest)总结

目录一、前言二、孤立森林算法2.1 算法简介2.2 基本原理2.3 算法步骤2.4 异常分数计算方式2.5 python调用方式三、python代码示例四、小结五、参考学习一、前言 近期在研究构建寿命预测模型&#xff0c;相信很多数据人都懂建模的过程&#xff0c;其实有80%的时间都是在和数据处…

Docker容器化部署实战:Tomcat与Nginx服务配置指南

部署Tomcat搜索镜像 使用以下命令搜索可用的Tomcat镜像&#xff1a;docker search tomcat拉取镜像 拉取官方Tomcat镜像&#xff1a;docker pull tomcat创建专用目录 为Tomcat配置和数据创建专用目录&#xff1a;mkdir tomcat运行临时容器并复制配置文件 启动临时容器以复制配置…

Go语言实战案例-使用SQLite实现本地存储

在开发工具类软件、桌面应用或者移动端时&#xff0c;我们经常需要一个轻量级数据库来做 本地存储。相比 MySQL、Postgres 等服务型数据库&#xff0c;SQLite 体积小、零配置、单文件存储&#xff0c;非常适合这种场景。Go 语言通过 GORM SQLite 驱动 就能轻松实现。本文将带你…

云计算学习100天-第23天

主机192.168.88.5 安装nginx#安装编译工具&#xff0c;正则表达式依赖包&#xff0c;SSL加密依赖包 yum -y install gcc make pcre-devel openssl-devel tar -xf /root/lnmp_soft.tar.gz cd lnmp_soft/ tar -xf nginx-1.22.1.tar.gz cd nginx-1.22.1/ #指定安装路径&…

【生成树+环】题解:P3907 环的异或_图论_环_异或_搜索_算法竞赛_C++

推销洛谷博客&#xff1a;https://www.luogu.com.cn/article/znmr9iu9 Link&#xff1a;Luogu - P3907 这里默认题目中指的环都是“简单环”&#xff08;即没有“环套环”的情况&#xff09;。 众所周知&#xff0c;树是图的一种特殊情况&#xff0c;且一定无环。如果我们想…

数据库优化提速(二)排序优化之搜索大数据酒店,进销存AI—仙盟创梦IDE

在 MySQL 数据库管理中&#xff0c;排序操作对于数据的有效展示和分析至关重要。本文将以一个实际的 SQL 查询为例&#xff0c;深入探讨排序优化方案&#xff0c;并结合进销存、酒店、知识库等大数据场景&#xff0c;阐述这些优化策略的应用价值。原始SELECT 应用编号, 应用序列…

Linux之Ansible自动化运维(二)

一、ansible Playbook应用由于服务器数量很多&#xff0c;配置信息比较多&#xff0c;因此可以利用Ansible Playbook编写任务自动化与流程化脚本Playbook 由一个或多个play组成的列表&#xff0c;play的主要功能Ansible中Task定义好的角色&#xff0c;指定剧本对应的服务器组二…

ArrayList线程不安全问题及解决方案详解

问题背景在多线程编程中&#xff0c;我们经常会遇到集合类的线程安全问题。Java中的ArrayList是一个常用的集合类&#xff0c;但它不是线程安全的。当多个线程同时操作同一个ArrayList实例时&#xff0c;可能会出现各种不可预料的问题。问题演示List<String> list new A…

车辆方向数据集 - 物体检测

关于数据集 包含超过50,000 张图像中具有方向的车辆的 50,000 多万个注释。它通过同时提供车辆类别和方向来减少对方向进行分类的辅助神经网络的需求。 预训练权重 我们将继续添加在车辆方向数据集和合成车辆方向数据集上训练的各种对象检测模型。如果您需要一些特定的预训练权…

Nextcloud搭建教程:使用Docker在腾讯云服务器上自建私人云盘

更多云服务器知识&#xff0c;尽在hostol.com你那百兆光纤的宽带。你是否也曾看着自己最珍贵的家庭照片、最私密的个人文档&#xff0c;静静地躺在某个科技巨头的服务器上&#xff0c;感到过一丝丝的不安&#xff1f;你的数据&#xff0c;到底被如何“阅读”和“分析”&#xf…

【操作记录】MNN Chat Android App 构建笔记(二)

&#x1f4d2; MNN Chat Android App 构建笔记 一、背景知识MNN 简介 MNN 是阿里开源的轻量级深度学习框架&#xff0c;支持 Android / iOS / Linux / Windows。提供推理、LLM、Vision、Audio 等模块。Android App 里用到的是 Java JNI 调用 MNN 库。CMake NDK 的作用 CMake&…