在云笔记项目中,讲到了MySql的自增,MyBatis查询到自增类型数据后可以设置返回到参数属性,其中学习了MySql的自增写法,堆栈对象等知识。

MySql数据类型自增

建立一张Person表,其中id就是自增,而name为人为插入,以下就是MySql自增的写法,不同的数据库写法不太一致,个人比较熟悉的就是Oracle需要写一个Sequence来解决,而MySql的写法更加简单:

 --MyBatis数据自增,MySQL中使用AUTO_INCREMENT,ORACLE中使用SEQUENCE
CREATE TABLE P_PERSON(
id int not null AUTO_INCREMENT,
name VARCHAR(100),
PRIMARY KEY(id)
);

建立表后,插入的数据id自动增加,如图为插入一定数量的数据后所呈现的结果:

映射文件中写法

由于使用了MyBatis来插入数据,这次有两个新的属性“useGeneratedKeys”和“keyProperty”,其中useGeneratedKeys为true,代表可以读取自增的id,而keyProperty=“id”,代表MyBatis将读取的结果赋值给参数Person对象的id属性,以下是MyBatis映射文件的配置。

    <insert id="addPerson" parameterType="com.boe.Entity.Person" useGeneratedKeys="true" keyProperty="id">
insert into
p_person
values(
#{id},
#{name}
)
</insert>

使用Spring容器插入数据

简单的数据库插入操作,项目学习的过程中使用了DAO接口+映射文件+实体Person类+Spring启动容器的方式来完成,测试能否插入数据成功,以下是测试的代码,省略掉Spring初始化的部分代码,直接进入测试部分,看看能否完成数据插入。

     //测试插入一条Person信息
@Test
public void test() { Person person=new Person(null,"LOVE");
//第一次输出
System.out.println(person);//Person [id=null, name=LOVE]
//插入到数据库
int n=dao.addPerson(person);
System.out.println(n);
//第二次输出
System.out.println(person);//Person [id=5, name=LOVE]
}

测试结果能正常插入数据,输出结果如下:

可以看出第一次输出结果id为null,第二次输出结果却为5,并且name输出均为LOVE,关于这一块需要用到Java中的值传递,final关键字,堆栈等知识点。

第一次输出的id为null,第二次输出的id结果为5,其需要用堆栈的知识去理解, 第一次输出person,这个Person对象已经储存在堆中,并且Person对象包含两个属性,一个是Integer包装类属性,另一个是String类型属性。Person对象在堆中创建后,又分别创建Integer对象和String类型对象,其中Integer对象的值为null,而String类型对象底层使用一个Value数组来保存字符串,并且用final修饰,说明其长度不可以改变,如本次为数组长度4的LOVE。

接下来执行dao.addPerson(person)方法,底层会被MyBatis调用插入数据的操作,并且Java采用值传递,将Person对象的内存地址传递给方法中的person,因此方法中这个person地址跟前面那个一样,都指向堆中的Person对象。当MyBatis返回自增类型的id后,将值赋值到堆中的Integer,并覆盖为5,

最后MyBatis底层方法执行完成后,Spring会帮忙销毁addPersion()方法中的局部变量person,因此addPerson()方法中person变量在方法执行完成后在栈中消失,当第二次打印person对象时,此时其指向的对象id已经变成5,因此再次输出的结果就是5了。参考下图:

为了更好的理解堆栈对象概念,接下来刘老师又举了两个例子,如下所示:

测试内存堆栈对象-值传递String和StringBuilder

话不多说直接上测试代码,发现执行完add()方法后,String类型输出为A,而StringBuilder类型输出为AA。

     //再次测试内存堆栈,对象
@Test
public void test1() {
String s="A";
StringBuilder sb=new StringBuilder("A");
add(s,sb);
//输出
System.out.println(s);//A
System.out.println(sb);//AA
} /**
* 测试方法,传入一个String类型和StringBuilder类型
* @param s
* @param sb
*/
public static void add(String s,StringBuilder sb) {
s=s+"A";
sb.append("A");
}

可以参考上面person两次输出结果的原理,再次可以得出此次结果的原理:

刚开始String类型变量s和StringBuilder类型变量sb初始化后,都会在堆中建立String对象和StringBuilder对象,s和sb会储存在栈中指向堆中的对象,当执行add()方法后,s和sb对应的对象地址值会传入到参数s和sb中,此时依然都指向以前的对象。

当执行s=s+“A”方法后,由于s是String类型,其底层是用final关键字修饰了保存字符的value[]数组,因此长度不可变,如果想增加一个字符,需要在堆中另外创建一个对象,用于储存增加A的结果,如图所示显示为AA,并且参数s的地址转而指向新建的对象。

而StringBuilder是长度可以变的,因此在append()方法执行后,不需要新建立一个对象,直接在原来的对象基础上加A,变成了AA。

最后执行完add()方法后,方法中的参数(局部变量)将在栈中因垃圾回收机制被删除,因此最后输出结果依然是上面的两个栈所指向的对象内容,分别为A和AA。

测试内存堆栈对象-值传递Integer和int[]数组

继续测试,发现执行完doSome()方法后,Integer类型输出为2,而int[]类型输出为3。

     //再次测试内存堆栈,对象
@Test
public void test2() {
Integer i=2;//Integer包装类跟String类型,也是final修饰的,是不可变量
int[] array= {2};
doSome(i,array);
//输出执行完后结果
System.out.println(i);//
System.out.println(array[0]);//
} /**
* 测试方法,传入Integer包装类和int数组
* @param i
* @param array
*/
public static void doSome(Integer i,int[] array) {
i=i++;
array[0]++;
}

可以参考上面结果的原理,再次可以得出此次结果的原理:

与上面的原因类似,由于Integer也是final关键字修饰的,是值不可变量,因此也需要在堆中为i++创建一个对象进行储存,如图结果为3储存在堆Integer对象中,而Int[]自增的结果3不需要单独再创建一个对象。在方法doSome()执行完成后,方法中的i和array参数销毁,重新输出指向的对象结果就是上面两个,依次输出2和3。

然后如果在上面的方法中,对array数组的修饰使用final关键字,变成final int[] array={2}后,结果分别会是多少呢?测试发现结果依然分别为2和3。为什么final关键字修饰的array结果不是2,而依然是3,按理来说修饰完后其值不应该改变才对的。后面通过学习其他前辈的经验,发现,被final关键字修饰的变量其实就相当于定义了一个常量,是无法被修改的变量,如果final修饰的是一个基本数据类型的变量,那么这个变量的值就定了,不能变了,而如果修饰的是一个引用变量,如本例修饰的引用类型变量array,那么该变量存的是一个内存地址,该地址就不能变了,但是该内存地址所指向的那个对象还是可以变的,所以上面的数组被final修饰后,返回的类型不是2,依然是3,对象中的值依然是可以改变的。

结论

(1)MySql和Oracle都可以返回自增类型,写法不一样,前者用AUTO_INCREMENT,后者用序列SEQUENCE。

(2)Java中参数的传递采用值传递,当方法执行完成后,方法中的参数将会销毁

(3)final关键字修饰的如果是基本数据类型变量,这个变量就不能动了,如果修饰的引用类型变量,只是引用类型变量的地址不能变了,但是引用类型变量指向的对象却可能可以变化。

参考博客:https://blog.csdn.net/u013781343/article/details/80548378

云笔记项目-MyBatis返回自增类型&堆栈对象补充理解的更多相关文章

  1. mybatis返回HashMap结果类型与映射

    <!-- 返回HashMap结果 类型--> <!-- 如果想返回JavaBean,只需将resultType设置为JavaBean的别名或全限定名 --> <!-- T ...

  2. mybatis返回自增主键踩坑记

    背景 MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map ...

  3. 杜绝网上压根没测过就乱写之 《oracle mybatis 返回自增主键 》

    面试过好多人,包括自己也属于这么一个情况: 遇到问题直接去网上查,一般都可以查到解决方案.其中也包括一些基本的面试资料的答案. 其实有很多答案也都是正确的,但是还是存在一些压根就是胡乱抄来的答案,也不 ...

  4. 转mybatis返回自增主键,亲测

    重点是获取对象的主键值而不是insert的返回值 Mybatis获取插入数据的主键时,返回值总是1xml里的写法 第一种方式 <insert id="insertLogin" ...

  5. mybatis返回自增主键问题踩坑

    1 <insert id="insert" keyProperty="id" useGeneratedKeys="true"
 par ...

  6. Mybatis返回表自增id

    在Mapper中,设置insert中添加useGeneratedKeys = "true"   keyProperty = "id" keyColumn=&qu ...

  7. 返回多个类型的对象,Tuple

    一个方法 通常只有一个 返回对象,有时候 我们遇到 要放回两个不同类型的值的时候, 这个时候可以使用Tuple. 对象. Tupele 只支持 .net framework 4.0 以上版本. 来!先 ...

  8. mybatis+sqlserver中返回非自增主键

    首先把实体类贴出来(这里只贴出属性,其它的就是getter和setter方法): public class Around {     private String xccd;  //对应主键      ...

  9. MyBatis 返回新增数据的自增id

    <insert id="save" parameterType="Vote" useGeneratedKeys="true" keyP ...

随机推荐

  1. OpenCV中feature2D——BFMatcher和FlannBasedMatcher

    作者:holybin 原文:https://blog.csdn.net/holybin/article/details/40926315 Brute Force匹配和FLANN匹配是opencv二维特 ...

  2. SqlServer高版本数据备份还原到低版本(转)

    原文地址:https://www.jb51.net/article/96454.htm 想要将Sqlserver2014高版本备份的数据还原到低版本SqlServer2008R2上去,但是这在SqlS ...

  3. RTP协议

    RTP协议格式: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+ ...

  4. MD5加密出现 无法启动:此实现不是Windows平台FIPS验证的加密算法的一部分

    出现问题: 出现这个问题的原因是订票助手.NET使用了MD5算法,而系统的组策略安全设置导致无法使用此算法.要修正此问题,请按照如下操作(两种方法任选其一). 注:(来源于  http://ask.f ...

  5. Kubernetes生态工具

    Helm Helm 是 Kubernetes 的包管理器,它是查找.共享和使用为 Kubernetes 开发的软件的最佳方式.Helm Charts 可用于定义.安装和升级复杂的 Kubernetes ...

  6. 5、分布式缓存Redis之bitmap、setbit

    基本语法: 1)SETBIT redis 127.0.0.1:6379> setbit KEY_NAME OFFSET VALUE //该命令用于对 key 所储存的字符串值,设置或清除指定偏移 ...

  7. Python绘图的颜色设置

    (转载):Python中的matplotlib函数中的颜色选取 转载链接:https://www.cnblogs.com/darkknightzh/p/6117528.html 原文内容:完全出自于自 ...

  8. Java垃圾回收(整理)

    Java垃圾回收 Garbage Collection:GC: 什么样的对象才是垃圾?怎样判断一个对象引用是不是垃圾? 垃圾回收算法:Mark-Sweep(标记-清除)算法,Copying(复制)算法 ...

  9. (简单)华为M3青春 CPN-AL10的Usb调试模式在哪里打开的步骤

    每次我们使用PC通过数据线连接到安卓手机的时候,如果手机没有开启usb开发者调试模式,PC则没能成功检测到我们的手机,有时候我们使用的一些功能比较强的的应用软件比如以前我们使用的一个应用软件引号精灵, ...

  10. Startup 类

    Startup 类的作用: 配置应用所需的任何服务 定义请求处理管道 配置(或注册)服务的代码添加到Startup.ConfigureServices方法中.服务是应用使用的组件.例如,Entity ...