对多表进行添加数据(获取最后一条插入的数据的ID)

本文介绍如何在MyBatis中实现多表关联插入,包括通过动态SQL插入数据并获取最后一次插入的ID,用于关联另一张表的插入操作。

有时我们会需要对多张表进行关联,今天我需要用到多表添加。不知道怎么弄但是想了下可以获取到第一张表最后一次进行添加的数据,我只会两种方法:一是获取到最后一次进行添加的时间,二是获取到最后进行添加的ID。我用的是第二种获取到最后进行操作添加的ID。

先将一张表进行添加数据的操作,写上查询语句“select LAST_INSERT_ID()”获取到最后一次添加的ID。获取到ID后返回一个int型的值,

映射文件:ordersMapper.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">
<mapper namespace="com.car.dao.OrdersMapper">
	<!-- 对user表进行插入,我这里用的是动态sql,也可以用普通的sql语句 -->
	<insert
		id="insertUser"
		parameterType="com.car.bean.User">
		insert into user
		<trim
			prefix="("
			suffix=")"
			suffixOverrides=",">
			<if test="uName != null"> u_name,
			</if>
			<if test="uPhone != null"> u_phone,
			</if>
		</trim>
		<trim
			prefix="values ("
			suffix=")"
			suffixOverrides=",">
			<if test="uName != null"> #{uName,jdbcType=VARCHAR},
			</if>
			<if test="uPhone != null"> #{uPhone,jdbcType=VARCHAR},
			</if>
		</trim>
		
		<!-- 获取到user最后一次插入的数据 -->
		<selectKey keyProperty="uId" resultType="int"> 
		select LAST_INSERT_ID()
		</selectKey>
	</insert>
	
<!-- 获取到user最后一次插入的数据,并返回一个int型的值 -->
<select id="selectLastId" resultType="int">
	select LAST_INSERT_ID()
</select>
<!-- 对orders表进行插入操作 --> <insertid="insertOrders"parameterType="com.car.bean.Orders">insert into orders<trimprefix="("suffix=")"suffixOverrides=","><if test="oMoney != null"> o_money,</if><if test="oPaytype != null"> o_payType,</if><if test="oStatus != null"> o_status,</if><if test="oDate != null"> o_date,</if><if test="oOther != null"> o_other,</if><if test="oServicetype != null"> o_serviceType,</if><if test="oServiceproto != null"> o_serviceProto,</if><if test="oShigong != null"> o_shigong,</if><if test="oXiaoshou != null"> o_xiaoshou,</if><if test="oShoping != null"> o_shoping,</if> <!-- 这里就是需要使用多表进行插入的ID --><if test="uId != null"> u_id,</if><if test="commentId != null"> comment_id,</if></trim><trimprefix="values ("suffix=")"suffixOverrides=","><if test="oMoney != null"> #{oMoney,jdbcType=FLOAT},</if><if test="oPaytype != null"> #{oPaytype,jdbcType=VARCHAR},</if><if test="oStatus != null"> #{oStatus,jdbcType=VARCHAR},</if><if test="oDate != null"> #{oDate,jdbcType=FLOAT},</if><if test="oOther != null"> #{oOther,jdbcType=VARCHAR},</if><if test="oServicetype != null"> #{oServicetype,jdbcType=VARCHAR},</if><if test="oServiceproto != null"> #{oServiceproto,jdbcType=VARCHAR},</if><if test="oShigong != null"> #{oShigong,jdbcType=VARCHAR},</if><if test="oXiaoshou != null"> #{oXiaoshou,jdbcType=VARCHAR},</if><if test="oShoping != null"> #{oShoping,jdbcType=VARCHAR},</if><if test="uId != null"> #{uId,jdbcType=INTEGER},</if><if test="commentId != null"> #{commentId,jdbcType=INTEGER},</if></trim></insert></mapper>

dao层(接口层):ordersMapper.java
package com.car.dao;


import com.car.bean.Orders;
import com.car.bean.User;

public interface OrdersMapper {

    //对orders表进行插入的方法
    int insertOrders(Orders record); 
    
    //对user表进行插入的方法
    int insertUser(User user);

    //获取最后一次对user表进行插入后的ID
    int selectLastId();
}
Service层:OrdersService.java
package com.car.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.car.bean.Orders;
import com.car.bean.User;
import com.car.dao.OrdersMapper;

@Service
public class OrdersService {
	@Autowired
	OrdersMapper ordersMapper;

	//获取user表最后一次进行插入的ID,返回一个int型
	public int selectLastId(){
		int id=ordersMapper.selectLastId();
		return id;
	}
	
	//对user表进行添加
	public void insertUser(User user){
		ordersMapper.insertUser(user);
	}
	
	//对order表进行添加
	public void insertOrders(Orders order){
		ordersMapper.insertOrders(order);
	}
	
}
Controller层:OrdersController
package com.car.controller;

import java.util.List;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.car.bean.Orders;
import com.car.bean.User;
import com.car.service.OrdersService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

@Controller
@RequestMapping("/orders")
public class OrdersController
{
	@Autowired
	OrdersService ordersService;

	@RequestMapping("/select")
	public String addTest(@RequestParam(value = "pn", defaultValue = "1") Integer pn, Model model)
	{
		PageHelper.startPage(pn, 4);
		List<Orders> list = ordersService.select();
		PageInfo page = new PageInfo(list, 4);
		model.addAttribute("pageInfo", page);
		return "orders";
	}
	
	//先对user表进行插入
	@RequestMapping("/insertUser")
	public String insertUser(User user,Orders order,Model model){
		ordersService.insertUser(user);
		//上面对user表进行插入后获取ID,返回int型
		int id=ordersService.selectLastId();
		order.setuId(id);
		return insertOrders(order,model);
	}
	
	//最后对orders表进行插入
	@RequestMapping("/insertOrders")
	public String insertOrders(Orders orders,Model model){
		ordersService.insertOrders(orders);
		return addTest(1,model);
	}
}


<think>嗯,用户问的是如何在PostgreSQL的最后一行插入一条数据。首先,我需要确认用户的具体需求。通常来说,数据库中的没有固定的“最后一行”概念,因为数据行的顺序取决于查询时的ORDER BY子句。如果没有指定排序,数据库返回的顺序是不确定的。所以,用户可能误解了数据的位置,或者他们想根据某个自增的ID或时间戳来找到最近插入的行,并在其后添加数据。 接下来,我需要回忆PostgreSQL的INSERT语句的基本结构。标准的INSERT命令是向插入新行,但需要指定列和对应的值。例如:INSERT INTO (列1, 列2) VALUES (值1, 值2);。但是用户想要的是在“最后一行”插入,这可能需要先确定最后一行的位置。 可能的场景是用户有一个自增主键,比如id,他们想找到最大的id,然后插入新的数据。这时候可以使用子查询来获取最大值,然后插入id+1的值。或者用户可能有一个时间戳列,想要找到最新的时间戳,然后插入比这个时间戳更晚的数据。不过,通常情况下,插入数据时不需要显式指定id或时间戳,尤其是当这些列设置为自增或默认当前时间戳时。 用户可能没有意识到,数据中的行并没有固定的物理顺序,每次查询时如果没有指定ORDER BY,结果的顺序可能会变化。因此,所谓的“最后一行”实际上是逻辑上的,需要根据某个排序字段来确定。例如,按id降序排列后的第一行就是最大的id,也就是最后插入的行。 因此,正确的做法应该是插入数据时,让数据库自动处理自增字段,而不是手动指定。例如,使用SERIAL或IDENTITY列来自动生成id。这样每次插入时,id会自动递增,无需用户自己查询最大值。 如果用户确实需要手动获取最大值并插入,可以使用INSERT INTO ... SELECT语句结合MAX函数。例如:INSERT INTO (id, 列) SELECT MAX(id)+1, '值' FROM 名;。但这种方法在并发环境下可能会有问题,因为插入操作可能同时读取相同的MAX(id),导致主键冲突。因此,推荐使用自增字段,让数据库自动处理。 另外,用户可能误以为数据中是按插入顺序存储的,但实际上,PostgreSQL使用堆结构,数据行的物理存储顺序并不保证与插入顺序一致。只有通过逻辑排序(如ORDER BY)才能确定行的顺序。 总结来说,用户的需求可能是想插入一条数据,使其在按某个字段排序后出现在最后。正确的做法是使用标准的INSERT语句,并依赖自增字段或时间戳来自动处理,而不是手动定位最后一行。需要向用户解释清楚数据中行的顺序概念,并提供正确的插入方法,同时指出潜在的问题和最佳实践。</think>在 PostgreSQL 中,**没有绝对的“最后一行”概念**(数据行的物理存储顺序与逻辑顺序无关),但可以通过以下两种方式实现类似需求: --- ### **一、基于自增主键插入“逻辑最后一行”** #### **1. 标准写法** ```sql -- 假设有自增主键(id),直接插入数据即可 INSERT INTO your_table (column1, column2, ...) VALUES (value1, value2, ...); ``` - **原理**:自增主键(如`SERIAL`或`IDENTITY`列)会自动生成递增的值,新插入的行在按主键排序时会处于“最后”。 - **示例**: ```sql -- 创建带自增主键的 CREATE TABLE users ( id SERIAL PRIMARY KEY, name TEXT, created_at TIMESTAMP DEFAULT NOW() ); -- 插入数据(无需指定id) INSERT INTO users (name) VALUES ('Alice'); ``` --- ### **二、按特定排序插入到“查询结果的最后”** #### **1. 动态获取最大值后插入** ```sql -- 假设要根据某字段(如时间戳)插入到“最后” INSERT INTO your_table (id, timestamp_column, ...) SELECT (SELECT MAX(id) FROM your_table) + 1, -- 生成新ID NOW(), -- 当前时间作为新时间戳 'new_value' -- 其他字段值 FROM your_table LIMIT 1; ``` - **适用场景**:无自增主键,需手动控制排序字段。 - **风险**:高并发下可能产生主键冲突(需事务隔离或改用自增字段)。 --- ### **三、注意事项** 1. **避免手动计算最大值** - 自增主键(`SERIAL`/`IDENTITY`)是线程安全的,而手动`MAX(id)+1`在并发写入时会导致主键冲突。 - **正确做法**:始终优先使用自增字段。 2. **按业务需求排序** - 若需按时间戳或其他字段排序,查询时应显式指定`ORDER BY`: ```sql SELECT * FROM your_table ORDER BY created_at DESC LIMIT 1; -- 获取最后一行” ``` --- ### **四、总结** | **场景** | **推荐方法** | **示例** | |----------------------------|----------------------------------|----------------------------------| | 有自增主键 | 直接插入,依赖自动递增 | `INSERT INTO users (name) VALUES ('Bob');` | | 无自增主键需按字段排序 | 插入时指定排序字段的递增值 | `INSERT ... SELECT MAX(sort_column)+1 ...` | | 查询时获取最后一行” | 使用`ORDER BY`和`LIMIT 1` | `SELECT * FROM logs ORDER BY id DESC LIMIT 1;` | 实际开发中应优先使用自增主键,避免手动管理行顺序。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值