JDBCTemplate + MySQL 主键到外键

Posted

技术标签:

【中文标题】JDBCTemplate + MySQL 主键到外键【英文标题】:JDBCTemplate + MySQL Primary Key to Foreign Key 【发布时间】:2015-07-05 05:26:31 【问题描述】:

我是 JDBC 以及它如何使用数据库的新手。我们看到了一个示例,但没有数据库或显示任何类型的工作功能。我想要做的是同时创建一个用户名和一个用户。

必须先创建用户名,因为它包含主键。我遇到的问题是当我创建用户和用户名时,用户表中用户名的外键为空。

CREATE TABLE `username` ( `UserNameId` int(11) NOT NULL AUTO_INCREMENT, `UserName` varchar(55) DEFAULT NULL,   `Password` varchar(100) DEFAULT NULL `RoleId` int(11) DEFAULT NULL,`enabled` tinyint(4) DEFAULT '1',PRIMARY KEY (`UserNameId`),KEY `fkrole_idx` (`RoleId`),CONSTRAINT `fkrole` FOREIGN KEY (`RoleId`) REFERENCES `role` (`roleId`) ON DELETE NO ACTION ON UPDATE NO ACTION ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8;


CREATE TABLE `user` (`UserID` int(11) NOT NULL AUTO_INCREMENT, `FirstName` varchar(55) DEFAULT NULL, `LastName` varchar(55) DEFAULT NULL,`BirthDate` date DEFAULT NULL,`Address` varchar(55) DEFAULT NULL,`StateId` int(11) DEFAULT NULL,`Zip` int(9) DEFAULT NULL,`EducationID` int(11) DEFAULT NULL,`UserNameID` int(11) DEFAULT NULL,`Email` varchar(55) DEFAULT NULL,`PhoneNumber` varchar(55) DEFAULT NULL,`description` varchar(500) DEFAULT NULL,`Resume` varchar(4000) DEFAULT NULL,PRIMARY KEY (`UserID`),UNIQUE KEY`UserNameID_UNIQUE` (`UserNameID`),KEY `fkstateID`(`StateId`),KEY`fkeducationID` (`EducationID`),KEY `fkusername` (`UserID`),KEY `fkusernameID_idx` (`UserNameID`),CONSTRAINT `fkeducationID` FOREIGN KEY(`EducationID`) REFERENCES `education` (`EducationId`) ON DELETE NO ACTION ON UPDATE NO ACTION,CONSTRAINT `fkstateID` FOREIGN KEY (`StateId`) REFERENCES `state` (`StateId`) ON DELETE NO ACTION ON UPDATE NO ACTION,CONSTRAINT `fkusernameID` FOREIGN KEY (`UserNameID`) REFERENCES `username` (`UserNameId`) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE=InnoDB AUTO_INCREMENT=144 DEFAULT CHARSET=utf8;

private static final String INSERT_USER = "INSERT INTO USER (`firstName`, `lastName`, `birthdate`,`address`,`stateid`,`zip`,`educationId`,`userNameId`,`email`,`phoneNumber`,`description`) VALUES (?,?,?,?,?,?,?,?,?,?,?);";
private static final String INSERT_USERNAME = "INSERT INTO USERNAME (`userName`, `password`, `roleId`,`enabled`) VALUES (?,?,?,?)";


@Override
public void add(UserName userName) 
    this.jdbcTemplate.update(INSERT_USERNAME, 
            userName.getUserName(),
            userName.getPassword(),
            userName.getRole().getRoleId(),
            userName.isEnabled());


@Override
public void add(User user) 
    this.jdbcTemplate.update(INSERT_USER,user.getFirstName(),
            user.getLastName(),user.getBirthdate(),user.getAddress(),user.getState().getStateId(),
            user.getZip(),user.getEducation().getEducationId(),user.getUserName().getUserNameId(),user.getEmail(),user.getPhoneNumber(),
            user.getDescription());

public class UserNameRowMapper implements RowMapper<UserName> 

private static final int USERNAMEID_FIELD = 1;
private static final int USERNAME_USERNAME_FIELD = 2;
private static final int USERNAME_PASSWORD_FIELD = 3;
private static final int USERNAME_ROLE_FIELD = 4;
private static final int USERNAME_ENABLED_FIELD = 5;

@Override
public UserName mapRow(ResultSet rs, int rowNum) throws SQLException 
    UserName userName = new UserName();
    userName.setUserNameId(rs.getInt(USERNAMEID_FIELD));
    userName.setUserName(rs.getString(USERNAME_USERNAME_FIELD));
    userName.setPassword(rs.getString(USERNAME_PASSWORD_FIELD));
    Role role = new Role();
        role.setRoleId(rs.getInt(USERNAME_ROLE_FIELD));
    userName.setRole(role);
    userName.setEnabled(rs.getBoolean(USERNAME_ENABLED_FIELD));
    return userName;


public class UserRowMapper implements RowMapper<User> 

private static final int USERID_FIELD = 1;
private static final int USER_FIRSTNAME_FIELD = 2;
private static final int USER_LASTNAME_FIELD = 3;
private static final int USER_BIRTHDATE_FIELD = 4;
private static final int USER_ADDRESS_FIELD = 5;
private static final int USER_STATE_FIELD = 6;
private static final int USER_ZIP_FIELD = 7;
private static final int USER_EDUCATION_FIELD = 8;
private static final int USERNAME_FIELD = 9;
private static final int USER_EMAIL_FIELD = 10;
private static final int USER_PHONENUMBER_FIELD = 11;
private static final int USER_DESCRIPTION_FIELD = 12;

@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException 
    User user = new User();
        user.setUserId(rs.getInt(USERID_FIELD));
        user.setFirstName(rs.getString(USER_FIRSTNAME_FIELD));
        user.setLastName(rs.getString(USER_LASTNAME_FIELD));
        user.setBirthdate(rs.getDate(USER_BIRTHDATE_FIELD));
        user.setAddress(rs.getString(USER_ADDRESS_FIELD));
        State state = new State();
            state.setStateId(USER_STATE_FIELD);
        user.setState(state);
        user.setZip(rs.getInt(USER_ZIP_FIELD));
        Education education = new Education();
        education.setEducationId(rs.getInt(USER_EDUCATION_FIELD));
            user.setEducation(education);
        Integer userNameID = rs.getInt(USERNAME_FIELD);
          if (userNameID != 0) 
              UserName username = new UserName();
              username.setUserNameId(userNameID);
              user.setUserName(username);

          
        user.setEmail(rs.getString(USER_EMAIL_FIELD));
        user.setPhoneNumber(rs.getString(USER_PHONENUMBER_FIELD));
        user.setDescription(rs.getString(USER_DESCRIPTION_FIELD));

    return user;


@Override
public void add(User user) 
    user.getUserName().setPassword(encoder.encode(user.getUserName().getPassword()));
    unDao.add(user.getUserName());

    userDao.add(user);


【问题讨论】:

【参考方案1】:

由于用户名id是在数据库端生成的(使用AUTO_INCREMENT

`UserNameId` int(11) NOT NULL AUTO_INCREMENT

您需要先使用GeneratedKeyHolder 来检索生成的主键 值。这样做的缺点是您还需要编写一些粗略的 JDBC 代码。您需要按如下方式更改add(UserName un) 方法。您也可以选择让它返回 主键

@Override
public Number add(UserName userName) 
    KeyHolder holder = new GeneratedKeyHolder();
    this.jdbcTemplate.update(
        new PreparedStatementCreator() 
          public PreparedStatement createPreparedStatement(Connection connection)
                                                            throws SQLException 
            PreparedStatement pstmt = connection.prepareStatement(
                                      INSERT_USERNAME, new String[] "UserNameId");
            pstmt.setString(1, userName.getUserName());
            pstmt.setString(2, userName.getPassword());
            pstmt.setInt(3, userName.getRole().getRoleId());
            pstmt.setBoolean(4, userName.isEnabled());
            return pstmt;
          
        , holder);
    Number key = holder.getKey();
    userName.setUserNameId(key.intValue());
    return key;

由于传递给该方法的 userName 对象也得到更新,因此后续的 userDao.add(user); 语句应该按原样开始工作。

【讨论】:

以上是关于JDBCTemplate + MySQL 主键到外键的主要内容,如果未能解决你的问题,请参考以下文章

在MySQL或者SQLServer中,添加对象后自动返回主键到对象模型中的配置方式

SQLAlchemy 一个映射类中的多个外键到同一个主键

JdbcTemplate 如何自动生成主键

SpringJDBC jdbcTemplate获取自增主键

PostgreSQL自增主键的用法以及在mybatis中的使用

spring jdbcTemplate insert插入Oracle数据库后返回当前主键id