通常來說對於mysql數據庫插入數據獲取主鍵的方法是采用selectKey的方式,特別是當你持久層使用mybatis框架的時候。
本文除此之外介紹其它兩種獲取主鍵的方式。
為了方便描述我們先建一張mysql數據庫的表:
CREATE TABLE `company_01` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='company_01';
一、 jdbc PreparedStatement方式
首先介紹一種jdbc獲取主鍵的方式,其它兩種方式也是對它的封裝的實現,方便我們使用mybatis框架的時候獲取主鍵值。
代碼如下:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.ResourceBundle; public class InformationSchema { private static Connection con=null; private static PreparedStatement ps=null; private static ResultSet rs=null; static{ ResourceBundle resourceBundle = ResourceBundle.getBundle("jdbc"); String driverName = resourceBundle.getString("jdbc.driverClassName"); String jdbc = resourceBundle.getString("jdbc.url"); String user = resourceBundle.getString("jdbc.username"); String password = resourceBundle.getString("jdbc.password"); try { Class.forName(driverName); con=DriverManager.getConnection(jdbc, user, password); } catch (Exception e) { e.printStackTrace(); } } public static void insertTable(String sql) { try { //Statement.RETURN_GENERATED_KEYS,為必傳參數 ps = con.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS); int count = ps.executeUpdate(); rs= ps.getGeneratedKeys(); rs.next(); System.out.println(rs.getInt(1)); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { String sql = "INSERT INTO company_01 (`name`) VALUES ('阿里巴巴')"; insertTable(sql); } }
以上這種方式,使用了 PreparedStatement 的getGeneratedKeys()方法,在插入的執行之后,獲取主鍵值。
二,mybatis useGeneratedKeys方式
這種方式主要使用了<insert id="insertCompany_01" useGeneratedKeys="true" keyProperty="id"></insert>標簽的這兩個屬性給傳進來的map的key或者對象的id屬性進行賦值(若為對象,keyProperty的值須跟屬性名進行對應)
spring和mybatis集成的xml文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 注冊屬性文件 --> <context:property-placeholder location="classpath:jdbc.properties"/> <!-- 阿里 druid數據庫連接池 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <!-- 數據庫基本信息配置 --> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <property name="driverClassName" value="${jdbc.driverClassName}" /> <!-- 初始化連接大小 --> <property name="initialSize" value="${jdbc.initialSize}"></property> <!-- 連接池最大數量 --> <property name="maxActive" value="${jdbc.maxActive}"></property> <!-- 連接池最大空閑 --> <property name="maxIdle" value="${jdbc.maxIdle}"></property> <!-- 連接池最小空閑 --> <property name="minIdle" value="${jdbc.minIdle}"></property> <!-- 獲取連接最大等待時間 --> <property name="maxWait" value="${jdbc.maxWait}"></property> </bean> <!-- 配置mybatis --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation" value="classpath:mybatis-config.xml"></property> <!-- mapper掃描 --> <property name="mapperLocations"> <array> <value>classpath*:mapper/*.xml</value> </array> </property> </bean> <!-- 配置映射掃描配置器 --> <!-- 可以幫助我們掃描dao包下的所有接口生成代理實現類 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" /> <property name="basePackage" value="com.opensource.dao" /> </bean> </beans>
mybatis的sql配置文件
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.opensource.dao.CompanyDao"> <insert id="insertCompany_01" useGeneratedKeys="true" keyProperty="id"> INSERT INTO `company_01` (`name`) VALUES (#{name}) </insert>
</mapper>
dao的接口:
import java.io.Serializable; public interface CompanyDao { /** * 這里傳參使用Serializable 是為了同時兼容map和實體類的情況 * @param serializable * @return */ public int insertCompany_01(Serializable serializable); }
實體類:
import java.io.Serializable; public class Company01 implements Serializable{ private Integer id; private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
測試類:
public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"spring/spring-mybatis.xml"}); CompanyDao companyDao = context.getBean(CompanyDao.class); //聲明這里要用Hashmap,可序列化的 HashMap<String,Object> map = new HashMap<String, Object>(); map.put("name", "阿里巴巴"); companyDao.insertCompany_01(map); System.out.println(map.get("id")); Company01 c01 = new Company01(); c01.setName("騰訊"); companyDao.insertCompany_01(c01); System.out.println(c01.getId()); }
三、mybatis selectKey方式
這種方式大家用的最多,就不再過多描述了,具體的測試方法同上
<insert id="insertCompany_01"> INSERT INTO `company_01` (`name`) VALUES (#{name}) <selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id"> SELECT LAST_INSERT_ID(); </selectKey> </insert>
有必要提出一點的是,order有兩個值,AFTER或BEFORE,獲取自增id時須用AFTER,BEFORE是用來給map的key或者對象的id屬性進行賦值的,用的不多。
最后說一點,我們作為程序員,研究問題還是要仔細深入一點的。當你對原理了解的有夠透徹,開發起來也就得心應手了,很多開發中的問題和疑惑也就迎刃而解了,而且在面對其他問題的時候也可做到觸類旁通。當然在開發中沒有太多的時間讓你去研究原理,開發中要以實現功能為前提,可等項目上線的后,你有大把的時間或者空余的時間,你大可去刨根問底,深入的去研究一項技術,為覺得這對一名程序員的成長是很重要的事情。
