THINKPHP在增加数量的时候获得主键id的值方法,获取自增ID值

在使用ThinkPHP新添多少后方可很有益于的拿走活动增加型的主键值。

前几天在行使MySQL时却不知怎么管理,插入记录后不知什么获得刚刚插入的id,查过文书档案后意识了select
last_insert_id(),在插入之后施行此询问,就能够获取自增id,喜笑颜开。
可用到和谐的顺序中之后却得不到想要的结果,于是就嘀咕到了Spring头上,因为通过骨干JDBC测验是从未其余难题的,所以就去追踪Spring
JDBC,
看过源码之后才振聋发聩,原本Spring中如此得到数据库Connection的:Connection con = DataSourceUtils.getConnection(getDataSource());,
哎,只可以怪本人Spring精晓相当不够好,所以就不可能在施行insert之后去施行select
last_insert_id()了,因为select
last_insert_id()是真对当前Connection插入和翻新操作的,那在Spring中什么获取新增添记录的键值呢,未有章程只好去Google了。

EF6中,要是将模型类的ID属性设置为主键自增,则大家在外表怎么对其赋值,数据库依旧会将该值自增,而不会管理外界给的值。

自动生成代码insert和insertSelective的区分

自动生成的mybatis对应布署文件之中,有三个措施,分别为insert和insertSelective。那四个艺术均是插入对象的方法。这里说一下两端的分别。
率先看一下五头代码:

  • insert

<insert id="insert" parameterType="com.cx.elearnning.model.SysSubject" >
    <!--
      WARNING - @mbggenerated
      This element is automatically generated by MyBatis Generator, do not modify.
    -->
    insert into sys_subject (SUBJECT_ID, SUBJECT_NAME, STATUS, 
      CREATE_TIME, PARENT_ID, sort
      )
    values (#{subjectId,jdbcType=INTEGER}, #{subjectName,jdbcType=VARCHAR}, #{status,jdbcType=BIT}, 
      #{createTime,jdbcType=TIMESTAMP}, #{parentId,jdbcType=INTEGER}, #{sort,jdbcType=INTEGER}
      )
  </insert>
  • insertSelective

<insert id="insertSelective" parameterType="com.cx.elearnning.model.SysSubject" >
    <!--
      WARNING - @mbggenerated
      This element is automatically generated by MyBatis Generator, do not modify.
    -->
    insert into sys_subject
    <trim prefix="(" suffix=")" suffixOverrides="," >
      <if test="subjectId != null" >
        SUBJECT_ID,
      </if>
      <if test="subjectName != null" >
        SUBJECT_NAME,
      </if>
      <if test="status != null" >
        STATUS,
      </if>
      <if test="createTime != null" >
        CREATE_TIME,
      </if>
      <if test="parentId != null" >
        PARENT_ID,
      </if>
      <if test="sort != null" >
        sort,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides="," >
      <if test="subjectId != null" >
        #{subjectId,jdbcType=INTEGER},
      </if>
      <if test="subjectName != null" >
        #{subjectName,jdbcType=VARCHAR},
      </if>
      <if test="status != null" >
        #{status,jdbcType=BIT},
      </if>
      <if test="createTime != null" >
        #{createTime,jdbcType=TIMESTAMP},
      </if>
      <if test="parentId != null" >
        #{parentId,jdbcType=INTEGER},
      </if>
      <if test="sort != null" >
        #{sort,jdbcType=INTEGER},
      </if>
    </trim>
  </insert>

分析
看完代码大要上就会分别两个的区分了吗?
insertSelective对应的sql语句到场了NULL校验,即只会插入数据不为null的字段值。
insert则会插入全体字段,会插入null。

$Model = D(‘Blog');

$data['name'] = 'test';

$data['title'] = '测试标题';

$data['content'] = '测试内容';

$result = $Model->add($data);

if ($result){

  $id = $result; // 获取数据库写入数据的主键

}else{

  exit($Model->getError());

}

发觉了之类小说,来自IT168,标题为《Spring应用数据主键的生成战略盘点》,摘录如下:

固然我们在疯长多少未来,供给用到那一个自增的ID主键,怎么获取呢?EF6在实行完context.SaveChanges()之后,会自行将那么些自增ID主键值从数据库中回到并赋给当下ID属性。其实大家什么都毫无操作,直接获得。如下代码:

什么在实行插入数据现在回到新添多少的ID(自增)

那边大家须要选取多少个特性,分别为:useGeneratedKeys、keyColumn、keyProperty。
地点所说的七个插入方法,均不会重回新添多少的ID。原因就是从未配置这七个属性。

假设你的数据表主键是机动增加型的,那么add方法成功后的重回值正是该多少的主键值。不要求额外获取。

   
在一般景色下,在新增加领域对象后,都急需取得相应的主键值。使用应用层来维护主键,在肯定程度上方便程序质量的优化和行使移植性的增进。在行使数据库自增主键的方案里,假如JDBC驱动不能绑定新增加记录对应的主键,就必要手工业实施查询语句以获得相应的主键值,对于高并发的系统,这很轻巧重回错误的主键。通过带缓存的DataField马克斯ValueIncrementer,能够三次拿走批量的主键值,供多次布署领域对象时选用,它的实施质量是相当高的。

 using (DemoContext context = new DemoContext()) {
                //在使用模型类之前需要强制创建数据库 true:强制创建
                context.Database.Initialize(true);

                #region 新增

                Student stu = new Student {
                    Name = "赵子成",
                    BirthDay = DateTime.Parse("1990-08-01"),
                    Age = 27
                };

                //新增一个Student实体,相当于在Student表中,新增一条数据
                context.Students.Add(stu);

                Console.WriteLine("新增之前\nID={0} Name={1} BirthDay={2} Age={3} \n", stu.ID, stu.Name, stu.BirthDay.Value.ToString("yyyy/MM/dd"), stu.Age);
                //保存
                context.SaveChanges();

                Console.WriteLine("新增之后\nID={0} Name={1} BirthDay={2} Age={3}", stu.ID, stu.Name, stu.BirthDay.Value.ToString("yyyy/MM/dd"), stu.Age);


                #endregion
}

布置情势

第一,必要配备useGeneratedKeys属性,设置为true。表达将自动生成的主键值举办了获取。
此后,设置keyColumn(对应数据表字段)、keyProperty(对应对象属性)。就要自动生成的主键值赋值给这几个属性!
亲自过问如下:

<insert id="createSubject" parameterType="com.cx.elearnning.model.SysSubject" useGeneratedKeys="true" keyColumn="SUBJECT_ID" keyProperty="subjectId">
        INSERT INTO SYS_SUBJECT (
        <include refid="sys_subject_columns" />
        )
        VALUES (
        <include refid="sys_subject_properties" />
        )
    </insert>

表示将自增值赋值给了sunjectId属性

以上那篇THINKPHP在充分数码的时候获得主键id的值方法正是作者分享给大家的全体内容了,希望能给大家二个参阅,也指望大家多多援助脚本之家。

动用数据库的自增主键
   
大家日常应用数据的自增字段作为表主键,也即主键值不在应用层产生,而是在疯长记录时,由数据库发生。那样,应用层在保留对象前并不知道对象主键值,而必须在保存数据后本事从数据库中回到主键值。在十分多景观下,大家需求获得新对象长久化后的主键值。在Hibernate等ORM框架,新指标长久化后,Hibernate会自动将主键值绑定到对象上,给程序的付出拉动了非常多方便人民群众。

新扩张过后的结果:

你也许感兴趣的小说:

  • PHP获取MySql新添记录ID值的3种艺术

    在JDBC
3.0正经中,当新扩充记录时,允许将数据库自动发出的主键值绑定到Statement或PreparedStatement中。使用Statement时,可以因此以下形式绑定主键值:
int executeUpdate(String sql,int autoGeneratedKeys)
也足以透过Connection创制绑定自增值的PreparedStatement:
PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)

新增之前
ID=00000000-0000-0000-0000-000000000000 Name=赵子成 BirthDay=1990/08/01 Age=27

新增之后
ID=c4049f86-3d74-e711-970d-58fb84575557 Name=赵子成 BirthDay=1990/08/01 Age=27

   
当autoGeneratedKeys参数设置为Statement.RETUEscortN_澳门葡京备用网址,GENERATED_KEYS值时就可以绑定数据库发生的主键值,设置为Statement.NO_GENERATED_KEYS时,不绑定主键值。上面包车型客车代码演示了Statement绑定并获得数据库发生的主键值的历程:

THINKPHP在增加数量的时候获得主键id的值方法,获取自增ID值。ID正是Student模型类的自增主键。新增加之后方可一贯拿走该ID值。

Statement stmt = conn.createStatement(); String sql
= “INSERT
INTO t_topic(topic_title,user_id) VALUES(‘测量检验主旨’,’123′)
“;
stmt.executeUpdate(sql,Statement.RETU昂CoraN_GENERATED_KEYS);
①点名绑定表自增主键值 ResultSet rs = stmt.getGeneratedKeys(); if (
rs.next() ) { int key = rs.getInt();②获取相应的表自增主键值 }

 

Spring利用这一技能,提供了二个能够再次回到新扩大记录对应主键值的秘诀:
int update(PreparedStatementCreator psc, KeyHolder generatedKeyHolder)
org.springframework.jdbc.support.KeyHolder是三个回调接口,Spring使用它保存新添记录对应的主键,该接口的接口方法描述如下:
 Number getKey() throws InvalidDataAccessApiUsageException

仅插入一行数据,主键不是复合键且是数字类型时,通过该方法能够直接重临新的主键值。要是是复合主键,或然有三个主键重临时,该措施抛出
InvalidDataAccessApiUsageException。该措施是最常用的艺术,因为一般情状下,大家二次仅插入一条数据同一时间主键字段类型为数字类型;

但是有一个算是惯例优先进表率式的一个小坑。假诺大家给有个别模型类定义了贰个ID属性,如下代码:

 Map getKeys() throws InvalidDataAccessApiUsageException
设如若复合主键,则列名和列值构成Map中的八个Entry。如若回去的是几个主键,则该情势抛出InvalidDataAccessApiUsageException格外;

public class Course{
    public int ID{get;set;}
    public string Name{get;set;}  
}

 List getKeyList():
假设回到八个主键,即PreparedStatement新添了多条记下,则每贰个主键对应叁个Map,七个Map构成三个List。

在使用EF的时候,EF会将ID当做自增主键去管理。不过此时我们不期望ID是自增主键,只是把它看做一个普通的性子而已。那时要给其扩大三个约束特性[DatabaseGenerated(DatabaseGeneratedOption.None)]。代码如下:

   
Spring为KeyHolder接口指代了多少个通用的落到实处类GeneratedKeyHolder,该类再次回到新扩充记录时的自增进主键值。假诺大家期望在疯长论坛板块对象后,希望将主键值加载到指标中,则足以按以下代码进行调度:

public class Course{
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int ID{get;set;}
    public string Name{get;set;}  
}

public void addForum(final Forum forum) { final String
sql = “INSERT
INTO t_forum(forum_name,forum_desc) VALUES(?,?)”;
KeyHolder keyHolder =
new GeneratedKeyHolder();①创制三个主键执有者
getJdbcTemplate().update(new PreparedStatementCreator(){ public
PreparedStatement createPreparedStatement(Connection conn) throws
SQLException { PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, forum.getForumName());
ps.setString(2, forum.getForumDesc()); return ps; } },keyHolder);
forum.setForumId(keyHolder.getKey().intValue());②从主键执有者中获得主键
}

 

     那样,在调用addForum(final Forum
forum)新增加forum领域对象后,forum将装有相应的主键值,方便后继的使用。
在JDBC
3.0事先的本子中,PreparedStatement不可能绑定主键,假诺运用表自增键(如MySql的auto
increment或SqlServer的identity)将给拿走科学的主键值带来挑战——因为你必须在插入数据后,登时实行另一条得到新扩充主键的询问语句。表
1付出了不相同数据库获取最新自增主键值的查询语句:
       表 1 分裂数据库获取新添的主键值 

 

数据库
获取新增主键的查询语句
DB2
IDENTITY_VAL_LOCAL()
Informix
SELECT dbinfo(‘sqlca.sqlerrd1’) FROM <TABLE>
Sybase
SELECT @@IDENTITY
SqlServer
SELECT SCOPE_IDENTITY()或SELECT @@IDENTITY
MySql
SELECT LAST_INSERT_ID()
HsqlDB
CALL IDENTITY()
Cloudscape
IDENTITY_VAL_LOCAL()
Derby
IDENTITY_VAL_LOCAL()
PostgreSQL
SELECT nextval(‘<TABLE>_SEQ’)

   
   
若是数据库的并发率极高,举个例子在插入记录后实行查询主键在此以前,数据库又实践了好些个条插入记录的SQL语句,那时,通过表
1
回到的主键值就是最后一条插入语句的主键值,而非我们目的在于的主键值了。所以利用查询语句获取表自增键值是不安全的,那也是干吗有个别数据库(如
Oracle、Firebird)故意不提供自增键,而只提供连串的缘由,体系强制须求您在新扩展记录前,先获得主键值。Oracle通过SELECT
<SEQUENCE_NAME>.nextval FROM
DUAL获取系列的下三个值,而FireBird通过SELECT
GEN_ID(<SEQUENCE_NAME> 1) FROM
LANDDB$DATABASE获取体系的下三个值。在10.4.1小节中,我们还将执教使用层自增键的相干知识。

应用层发生主键
    Spring
JDBC提供了自增键以及行集的支撑,自增键对象让大家能够不依赖数据库的自增键,在应用层为新记录提供主键值。在JDK
1.4中引进了RowSet,它同目的在于接连断开的情景下操作数据,在那节里,我们将介绍如何在Spring
JDBC中运用RowSet。

自增键的选拔
   
一般数据库都提供了自增键的功效,如MySql的auto_increment、SqlServerr的identity字段等。Spring允许你在应用层发生主键值,为此概念了
org.springframework.jdbc.support.incrementer.DataField马克斯ValueIncrementer
接口,提供三种发生主键的方案:第一,通过系列发生主键;第二,通过表产生主键。依据主键爆发办法和数据库的不等,Spring提供了大多落实类,如图
1所示: 

      图 1 DateFieldValueIncrementer承接类图
   
依照区别的主键产生艺术,恐怕必要安插表名、主键字段名或种类名等音信。下边,我们以Oracle和MySql为例分别授课使用体系及表字段爆发主键值的方法。

DataField马克斯ValueIncrementer接口定义了3个获得下二个主键值的主意:
 int nextIntValue():获取下二个主键值,主键数据类型为int;
 long nextLongValue():获取下壹个主键值,主键数据类型为long;
 String nextStringValue():获取下三个主键值,主键数据类型为String;
   
在其抽象达成类AbstractDataField马克斯ValueIncrementer中,提供了多少个第一的天性,个中incrementerName定义连串或主键表的称谓;如若回到的主键是String类型,则paddingLength属性大概会派上用场,它同意你钦定重临主键的尺寸,不足的局地前边补0。

   
Hsql马克斯ValueIncrementer和MySQLMaxValueIncrementer七个主键值发生器基于表展开职业。通过
columnName属性定义主键列的名字,通过cacheSize属性定义缓存的主键个数,当内部存款和储蓄器中的主键值用完后,发生器将一回性猎取cacheSize个主键,那样能够收缩多少访谈的次数,提升运用的习性。

   
大家因此DateFieldValueIncrementer从数据库中赢得主键值来弥补这几个毛病。首先,调节PostJdbcDao的代码,增加DateFieldValueIncrementer属性,并经过它从种类中收获下三个主键值:
    代码清单 13 使用DateFieldValueIncrementer发生主键

public class PostJdbcDao extends
JdbcDaoSupport implements PostDao { private DataField马克斯ValueIncrementer
incre; ①主键值发生器 public void addPost(final Post post) { …
getJdbcTemplate().execute( sql,new AbstractLobCreatingPreparedStatementCallback(
this.lobHandler) { protected void setValues(PreparedStatement ps, LobCreator
lobCreator) throws SQLException { ps.setInt(1,
incre.nextIntValue());②获取下三个主键值 … } }); } …//省略get/setter方法 }

在②处,大家经过incre.nextIntValue()获取下五个主键值。

以类别格局发出主键值
   
在Oracle数据库中开创一个seq_post_id系列,使用这么些队列为t_post提供主键值,以下是创立seq_post_id的脚本: 

create sequence seq_post_id increment by 1start with 1;

  
接着,调治Spring的安顿,使用OracleSequence马克斯ValueIncrementer作为主键爆发器:

<bean id=”incre” class=”org.springframework.jdbc.support.incrementer.OracleSequenceMaxValueIncrementer”><property name=”incrementerName” value=”seq_post_id”/> ①点名系列名 <property name=”dataSource” ref=”dataSource”/> ②设置数据源 </bean><bean id=”postDao” parent=”dao” class=”com.baobaotao.dao.jdbc.PostJdbcDao”><property name=”lobHandler” ref=”oracleLobHandler”/><property name=”incre” ref=”incre”/> ③增加主键主键发生器 </bean>

  以表格局发生主键值 
 在Mysql中创制一张用于维护t_post主键的t_post_id表,以下是制造该表及插入伊始化的SQL脚本:

澳门葡京备用网址 1create
table t_post_id(sequence_id int)
type =
MYISAM;
澳门葡京备用网址 2insert into
t_post_id values(0);
澳门葡京备用网址 3

   
由于主键维护表的并发访谈量相当的大,所以最棒将其注脚为MYISAM类型,别的部须求要为该表提供伊始值,以便后续主键值在此之上进行递增。
调动为MySql数据库后,大家仅必要对Spring配置实行小小的调节就足以了:

<bean id=”incre”class=”org.springframework.jdbc.support.incrementer.MySQLMaxValueIncrementer”><property name=”incrementerName” value=”t_post_id”/> ①设置保证主键的表名 <property name=”columnName” value=”sequence_id”/>②用以转移主键值的列名 <property name=”cacheSize” value=”10″/> ③缓存大小 <property name=”dataSource” ref=”dataSource”/></bean><bean id=”postDao” parent=”dao” class=”com.baobaotao.dao.jdbc.PostJdbcDao”><property name=”lobHandler” ref=”defaultLobHandler”/><property name=”incre” ref=”incre”/></bean>

   
incrementerName和columnName都很轻易了然,cacheSize决定叁遍回到的主键个数,这里大家设置为10。当第贰回通过
MySQL马克斯ValueIncrementer#
nextIntValue()获取主键值时,MySQL马克斯ValueIncrementer将使t_post_id.
sequence_id递增10,而后续9次调用nextIntValue()方法时,都从缓存中获得主键值。直到第12次重复调用
nextIntValue()方法时,才会另行将t_post_id.
sequence_id字段值递增10,如此循环反复。

小结
   
主键的生产格局从产生地方上能够分成应用层发生和数据库发生二种办法。应用层借助数据库的连串或表产生主键,这种方式能够保证程序的可移植性和安全性,同有的时候间能够由此缓存机制升高运营效能。有些数据库协理数据表自增键的主键发生体制,在JDBC
3.0在此以前的本子中,无法透过Statement自动得到新增添记录的对应主键。那时急需在插入数据后,立刻奉行一条数据库相关的主键获取SQL语句以获得相应的主键值,在数据库高并发的情形下,有非常大大概获得到不科学的主键值。在这种情况下,在插入数据前先行在应用层希图好主键值是很好的计划方案。

其他补充某个在SqlUpdate实行update以前需安装setReturnGeneratedKeys(true);

你也许感兴趣的稿子:

  • Spring MVC
    框架搭建配置方式及详解
  • struts2+spring+hibernate分页代码[比较多]
  • Spring中的事务管理实例详解
  • Spring事务管理只对现身运营期万分举办回滚
  • SpringMVC文件上传
    多文本上传实例
  • 读取spring配置文件的艺术(spring读取能源文件)
  • Spring达成文件上传(示例代码)
  • java
    Spring整合Freemarker的详细步骤
  • spring快速入门实例教程
  • Spring测验 其实很简单

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*
*
Website