本文目录导读:

我来详细说明Java MyBatis新增数据的实现方法,包括常见场景和最佳实践。
基础新增实现
1 Mapper接口定义
public interface UserMapper {
// 单个新增
int insert(User user);
// 返回自增主键
int insertWithKey(User user);
// 选择性新增(不为null的字段才插入)
int insertSelective(User user);
}
2 XML映射文件
<!-- 基础新增 -->
<insert id="insert" parameterType="User">
INSERT INTO user(name, age, email, create_time)
VALUES(#{name}, #{age}, #{email}, #{createTime})
</insert>
<!-- 返回自增主键 -->
<insert id="insertWithKey" useGeneratedKeys="true" keyProperty="id">
INSERT INTO user(name, age, email, create_time)
VALUES(#{name}, #{age}, #{email}, #{createTime})
</insert>
<!-- 选择性新增 -->
<insert id="insertSelective" parameterType="User">
INSERT INTO user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="name != null">name,</if>
<if test="age != null">age,</if>
<if test="email != null">email,</if>
<if test="createTime != null">create_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="name != null">#{name},</if>
<if test="age != null">#{age},</if>
<if test="email != null">#{email},</if>
<if test="createTime != null">#{createTime},</if>
</trim>
</insert>
获取生成的主键
1 使用自增主键
// 方式一:自动获取(推荐)
@Insert("INSERT INTO user(name, age) VALUES(#{name}, #{age})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(User user);
// 使用
User user = new User("张三", 25);
userMapper.insert(user);
System.out.println("生成的主键:" + user.getId()); // 直接获取
2 使用UUID主键
<!-- 在插入前生成UUID -->
<insert id="insertWithUUID">
<selectKey keyProperty="id" resultType="String" order="BEFORE">
SELECT REPLACE(UUID(), '-', '')
</selectKey>
INSERT INTO user(id, name, age)
VALUES(#{id}, #{name}, #{age})
</insert>
批量新增
1 使用foreach
<!-- 批量新增 -->
<insert id="batchInsert" parameterType="java.util.List">
INSERT INTO user(name, age, email)
VALUES
<foreach collection="list" item="item" separator=",">
(#{item.name}, #{item.age}, #{item.email})
</foreach>
</insert>
2 MyBatis Plus批量新增
// 使用MyBatis Plus
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
implements UserService {
// 批量保存(分批插入)
@Transactional
public boolean batchSave(List<User> userList) {
return saveBatch(userList, 1000); // 每批1000条
}
}
高级新增场景
1 联合插入(多表)
<!-- 插入用户和角色关联 -->
<insert id="insertUserAndRole">
<!-- 插入用户 -->
<selectKey keyProperty="userId" resultType="Long" order="AFTER">
SELECT LAST_INSERT_ID()
</selectKey>
INSERT INTO user(name, age) VALUES(#{name}, #{age})
</insert>
<insert id="insertUserRole">
INSERT INTO user_role(user_id, role_id)
VALUES(#{userId}, #{roleId})
</insert>
2 存在则更新,不存在则插入
<insert id="insertOrUpdate">
INSERT INTO user(name, age, email)
VALUES(#{name}, #{age}, #{email})
ON DUPLICATE KEY UPDATE
age = VALUES(age),
email = VALUES(email)
</insert>
完整示例代码
1 实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("user")
public class User {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
private Integer age;
private String email;
private LocalDateTime createTime;
private LocalDateTime updateTime;
}
2 Service层
@Service
@Transactional
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public User createUser(User user) {
// 补全信息
user.setCreateTime(LocalDateTime.now());
user.setUpdateTime(LocalDateTime.now());
// 执行新增
int result = userMapper.insert(user);
if (result > 0) {
return user; // 包含生成的主键
}
throw new RuntimeException("新增用户失败");
}
@Override
@Transactional(rollbackFor = Exception.class)
public void batchCreateUsers(List<User> userList) {
// 批量处理
userList.forEach(user -> {
user.setCreateTime(LocalDateTime.now());
user.setUpdateTime(LocalDateTime.now());
});
// 分批插入,每批500条
int batchSize = 500;
for (int i = 0; i < userList.size(); i += batchSize) {
int end = Math.min(i + batchSize, userList.size());
List<User> batch = userList.subList(i, end);
userMapper.batchInsert(batch);
}
}
}
3 Controller层
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@PostMapping
public Result<User> createUser(@Valid @RequestBody UserCreateDTO dto) {
User user = new User();
BeanUtils.copyProperties(dto, user);
User created = userService.createUser(user);
return Result.success(created);
}
@PostMapping("/batch")
public Result<Void> batchCreateUsers(@RequestBody List<UserCreateDTO> dtos) {
List<User> users = dtos.stream()
.map(dto -> {
User user = new User();
BeanUtils.copyProperties(dto, user);
return user;
})
.collect(Collectors.toList());
userService.batchCreateUsers(users);
return Result.success();
}
}
最佳实践
1 参数校验
@PostMapping
public Result<User> createUser(@Valid @RequestBody UserCreateDTO dto) {
// 业务校验
if (userService.existsByEmail(dto.getEmail())) {
return Result.error("邮箱已存在");
}
// ... 执行新增
}
2 事务管理
@Transactional(rollbackFor = Exception.class)
public User createUserWithRoles(User user, List<Long> roleIds) {
// 插入用户
userMapper.insert(user);
// 插入角色关联
if (CollectionUtils.isNotEmpty(roleIds)) {
userRoleMapper.batchInsert(user.getId(), roleIds);
}
return user;
}
3 性能优化
// 批量插入时关闭自动提交
@Transactional
public void batchInsertOptimized(List<User> list) {
SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH);
try {
UserMapper mapper = session.getMapper(UserMapper.class);
for (User user : list) {
mapper.insert(user);
}
session.commit();
} finally {
session.close();
}
}
常见问题处理
1 特殊字符转义
<!-- 使用CDATA转义 -->
<insert id="insertWithSpecialChar">
<![CDATA[
INSERT INTO user(name, description)
VALUES(#{name}, #{description})
]]>
</insert>
2 时间字段处理
// 使用数据库默认值 @TableField(fill = FieldFill.INSERT) private LocalDateTime createTime; // 或手动设置 user.setCreateTime(LocalDateTime.now());
通过以上方式,你可以根据具体场景选择合适的MyBatis新增实现方案,建议在实际开发中结合业务需求、数据量大小和性能要求来选择合适的方式。