云笔记项目-MyBatis返回自增类型&堆栈对象补充理解
在云笔记项目中,讲到了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返回自增类型&堆栈对象补充理解的更多相关文章
- mybatis返回HashMap结果类型与映射
<!-- 返回HashMap结果 类型--> <!-- 如果想返回JavaBean,只需将resultType设置为JavaBean的别名或全限定名 --> <!-- T ...
- mybatis返回自增主键踩坑记
背景 MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map ...
- 杜绝网上压根没测过就乱写之 《oracle mybatis 返回自增主键 》
面试过好多人,包括自己也属于这么一个情况: 遇到问题直接去网上查,一般都可以查到解决方案.其中也包括一些基本的面试资料的答案. 其实有很多答案也都是正确的,但是还是存在一些压根就是胡乱抄来的答案,也不 ...
- 转mybatis返回自增主键,亲测
重点是获取对象的主键值而不是insert的返回值 Mybatis获取插入数据的主键时,返回值总是1xml里的写法 第一种方式 <insert id="insertLogin" ...
- mybatis返回自增主键问题踩坑
1 <insert id="insert" keyProperty="id" useGeneratedKeys="true" par ...
- Mybatis返回表自增id
在Mapper中,设置insert中添加useGeneratedKeys = "true" keyProperty = "id" keyColumn=&qu ...
- 返回多个类型的对象,Tuple
一个方法 通常只有一个 返回对象,有时候 我们遇到 要放回两个不同类型的值的时候, 这个时候可以使用Tuple. 对象. Tupele 只支持 .net framework 4.0 以上版本. 来!先 ...
- mybatis+sqlserver中返回非自增主键
首先把实体类贴出来(这里只贴出属性,其它的就是getter和setter方法): public class Around { private String xccd; //对应主键 ...
- MyBatis 返回新增数据的自增id
<insert id="save" parameterType="Vote" useGeneratedKeys="true" keyP ...
随机推荐
- declaration may not appear after executable statement in block
keil 编译时出现 declaration may not appear after executable statement in block,找到keil工程对应的函数 定义的地方出现在了赋值的 ...
- python读写文件\r\n问题
newline controls how universal newlines mode works (it only applies to text mode). It can be None, ' ...
- bzoj5104: Fib数列
Description Fib数列为1,1,2,3,5,8... 求在Mod10^9+9的意义下,数字N在Fib数列中出现在哪个位置 无解输出-1 Input 一行,一个数字N,N < = 10 ...
- win10 vs2015源码编译tesseract4.0
1.安装软件 cmake 下载地址 cppan 下载地址 安装完毕后,需要将cmake.exe和cppan.exe加入环境变量PATH中 cmake简介 CMake全称为“cross platf ...
- 理解OpenShift(7):基于 Prometheus 的集群监控
理解OpenShift(1):网络之 Router 和 Route 理解OpenShift(2):网络之 DNS(域名服务) 理解OpenShift(3):网络之 SDN 理解OpenShift(4) ...
- symfony generate bundle autoload failed的解决办法
I also encountered this problem,I add new bundle namespace in composer.json"autoload": { & ...
- Tree Traversals Again
An inorder binary tree traversal can be implemented in a non-recursive way with a stack. For example ...
- AX2012 ERP 维度相关表数据关系图
AX2012比AX2009可怜的几个维度来说,太丰富了,可以无数个啊.维度多了,如何使用以及管理是个问题.这个需要在做调研时,充分分析讨论确定.以下为维度表关联关系,在做SQL取值时需要了解下,比如在 ...
- Spring AOP Capabilities and Goal
Spring AOP是用纯的java实现的.不需要任何个性的实现过程.Spring AOP不需要控制类加载器,并且它适用于Servlet容器或者应用服务器. Spring AOP当前只支持方法执行的连 ...
- Kubernetes及Dashboard详细安装配置(Ubuntu14.04)
前些日子部门计划搞并行开发,需要对开发及测试环境进行隔离,所以打算用kubernetes对docker容器进行版本管理,搭建了下Kubernetes集群,过程如下: 本流程使用了阿里云加速器,配置流程 ...