数据库主键与索引、hashcode、文件hash

本文详细介绍了数据库中的主键概念及其作用,解释了如何通过主键来确保数据记录的唯一性。此外,还探讨了数据库索引的定义及其实现原理,包括索引如何提升查询效率以及其在实际应用中的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据库主键:数据库某个表中,唯一表示记录的符号。

主要用户插入时,判断主键是否重复,唯一性是否破坏。

数据库索引:在数据库表中一列或者多列,进行值排序,从而提高查询效率的数据结构。

主要用于用户查询时,提高查询效率,提升效率很高。

HashCode:

用于配合Hashtable、HashMap等散列集合的比较,查询。

两个对象相等equal(),两个对象hashcode相等,是充分非必要条件。

从写equal()方法时,尽量重写hashcode方法,保持一致。


补充说明:

文件的hash值,是文件的唯一内容的唯一标识。

文件内容被改动后,hash值会变化。如MD5.


参考文章:

1、http://www.cnblogs.com/dolphin0520/p/3681042.html

2、http://blog.youkuaiyun.com/fenglibing/article/details/8905007

<think>我们被要求使用MyBatis-Plus处理MySQL中具有多个主键(复合主键)的表。MyBatis-Plus默认使用单主键策略,但可以通过自定义方式支持复合主键。步骤:1.实体类中需要使用`@TableId`注解,但复合主键需要特殊处理。MyBatis-Plus不支持直接在字段上使用多个`@TableId`。因此,我们需要使用`@TableId`的`type`属性设置为`IdType.INPUT`,并实现一个自定义的主键生成策略,但更常见的做法是使用`@KeySequence`(针对序列)或使用复合主键类。2.实际上,MyBatis-Plus官方文档并没有直接支持复合主键,但我们可以通过以下方式实现:-创建一个复合主键的类(这个类需要实现`Serializable`接口,并重写`equals`和`hashCode`方法)。-在实体类中,我们不再使用多个`@TableId`,而是使用一个字段来表示复合主键(这个字段的类型就是复合主键类),并在这个字段上使用`@TableId(type=IdType.INPUT)`。3.另一种方式(也是更常见的方式)是使用MyBatis-Plus的注解`@TableId`配合`@TableField`来映射多个主键字段,但需要告诉MyBatis-Plus这些字段共同构成主键。然而,MyBatis-Plus目前(截至3.5.3版本)没有提供直接的多主键注解。因此,我们采用复合主键类的方式。具体操作:步骤1:创建复合主键类例如,我们有一个表`user_role`,有两个主键:`user_id`和`role_id`。创建复合主键类`UserRoleKey`:```javaimportjava.io.Serializable;publicclassUserRoleKeyimplementsSerializable{privateLonguserId;privateLongroleId;//无参构造器publicUserRoleKey(){}//有参构造器publicUserRoleKey(LonguserId,LongroleId){this.userId=userId;this.roleId=roleId;}//getter和setter//重写equals和hashCode方法@Overridepublicbooleanequals(Objecto){if(this==o)returntrue;if(o==null||getClass()!=o.getClass())returnfalse;UserRoleKeythat=(UserRoleKey)o;returnObjects.equals(userId,that.userId)&&Objects.equals(roleId,that.roleId);}@OverridepublicinthashCode(){returnObjects.hash(userId,roleId);}}```步骤2:在实体类中使用复合主键在实体类中,我们定义一个字段,类型为`UserRoleKey`,并用`@TableId`注解标记,同时设置`type=IdType.INPUT`(因为复合主键的值是由我们输入的,不是自动生成的)。```javaimportcom.baomidou.mybatisplus.annotation.TableId;importcom.baomidou.mybatisplus.annotation.TableName;@TableName("user_role")publicclassUserRole{@TableId(type=IdType.INPUT)privateUserRoleKeyid;//复合主键//其他字段...privateStringremark;//getter和setter}```步骤3:Mapper接口创建Mapper接口,继承`BaseMapper`,并指定实体类。```javaimportcom.baomidou.mybatisplus.core.mapper.BaseMapper;publicinterfaceUserRoleMapperextendsBaseMapper<UserRole>{}```步骤4:使用在Service中,我们可以像操作单主键一样操作复合主键。例如,插入一条记录:```javaUserRoleKeykey=newUserRoleKey(1L,2L);UserRoleuserRole=newUserRole();userRole.setId(key);userRole.setRemark("test");userRoleMapper.insert(userRole);```注意:在查询时,我们也需要使用复合主键对象作为参数。```javaUserRoleKeykey=newUserRoleKey(1L,2L);UserRoleuserRole=userRoleMapper.selectById(key);```但是,请注意,MyBatis-Plus的`selectById`方法只接受一个参数,所以我们把复合主键对象作为整体传入。步骤5:配置(如果需要)在配置文件中,确保MyBatis-Plus的配置正确。例如,在`application.yml`中:```yamlmybatis-plus:#配置Mapper.xml的位置,如果有的话mapper-locations:classpath*:mapper/**/*.xml#其他配置```如果遇到问题,可能需要自定义一个主键生成器,但复合主键通常由业务决定,所以使用`IdType.INPUT`即可。另外,注意在复合主键类中,字段名称需要数据库中的列名保持一致(或者使用`@TableField`注解指定),但在这个复合主键类中,字段名不需要数据库列名一致,因为我们在实体类中只有一个字段(id)映射到复合主键。但是,在复合主键类中的字段名应该数据库列名一致,或者通过注解指定。然而,实际上,MyBatis-Plus在处理复合主键类时,会将其拆分为多个属性,所以复合主键类中的属性名必须数据库主键列名一致(或者通过`@TableField`注解指定)。如果不一致,则需要使用`@TableField`注解。例如,在复合主键类中:```javapublicclassUserRoleKeyimplementsSerializable{@TableField("user_id")//如果数据库列名是user_id,而属性名是userId,则可以这样指定privateLonguserId;privateLongroleId;//如果属性名和列名一致,则可以不加注解}```但是,由于复合主键类本身不是实体,这个注解可能不起作用。因此,更常见的做法是保持属性名数据库列名一致(使用下划线命名法或驼峰命名法,并在配置中开启驼峰映射)。在MyBatis-Plus配置中,默认开启了驼峰映射,所以如果数据库列名是`user_id`,属性名是`userId`,则不需要注解。如果仍然有问题,可以在实体类中使用`@TableField`注解来指定复合主键类中的字段对应的数据库列名。但是,这通常不需要,因为MyBatis-Plus会自动处理。另一种做法:不使用复合主键类,而是将多个主键字段直接放在实体类中,并分别用`@TableId`标注(尽管官方不允许多个@TableId)。但是,在MyBatis-Plus中,不允许在多个字段上标注`@TableId`,因为主键只有一个。因此,复合主键类的方式是唯一的选择。总结:通过复合主键类,我们可以处理多主键表。注意事项:-在编写条件构造器时,如果要用到主键条件,需要传入复合主键对象。-在自定义SQL时,在XML中需要写多个主键条件。例如,在XML中写一个根据主键查询的SQL:```xml<selectid="selectById"resultType="UserRole">SELECT*FROMuser_roleWHEREuser_id=#{id.userId}ANDrole_id=#{id.roleId}</select>```但是,我们通常不需要写这个,因为MyBatis-Plus的`selectById`方法已经通过复合主键类实现了。因此,按照上述步骤,即可在SpringBoot项目中配置MyBatis-Plus以支持具有多个主键的MySQL表。参考引用:[^2]提到了MySQL驱动的依赖方式。[^3]提供了MyBatis-Plus的配置示例。[^4]介绍了MyBatis-Plus的特性,包括无侵入、强大的CRUD操作等。根据引用[^3],我们可以在`application.yml`中配置MyBatis-Plus,但不需要特别为复合主键做配置。因此,我们按照上述步骤编写代码即可。相关问题:1.在MyBatis-Plus中,如何处理复合主键的自动生成(如自增)?注意:复合主键通常不能使用数据库自增,因为自增只能作用于一个列。所以,复合主键的值需要由程序指定。2.使用复合主键时,如何实现分页查询?3.在MyBatis-Plus的条件构造器(如QueryWrapper)中,如何构建复合主键的查询条件?</think>### 在 Spring Boot 中使用 MyBatis-Plus 处理 MySQL 多主键表 MyBatis-Plus 默认支持单主键表,处理复合主键(多列主键)需要特殊配置。以下是完整实现步骤: --- ### 一、核心配置步骤 1. **创建复合主键类**(实现 `Serializable`) ```java public class UserRoleKey implements Serializable { private Long userId; // 对应第一个主键字段 private Long roleId; // 对应第二个主键字段 // 必须实现 equals() 和 hashCode() @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; UserRoleKey that = (UserRoleKey) o; return userId.equals(that.userId) && roleId.equals(that.roleId); } @Override public int hashCode() { return Objects.hash(userId, roleId); } } ``` 2. **实体类中使用复合主键** ```java @TableName("user_role") // 表名注解 public class UserRole { @TableId(type = IdType.INPUT) // 关键配置 private UserRoleKey id; // 复合主键字段 // 其他普通字段 private Integer status; private LocalDateTime createTime; } ``` 3. **Mapper 接口配置** ```java public interface UserRoleMapper extends BaseMapper<UserRole> { // 自定义复合主键查询方法 @Select("SELECT * FROM user_role WHERE user_id = #{userId} AND role_id = #{roleId}") UserRole selectByCompositeKey(@Param("userId") Long userId, @Param("roleId") Long roleId); } ``` --- ### 二、使用示例 ```java // 插入数据 UserRoleKey key = new UserRoleKey(1001L, 2001L); UserRole record = new UserRole(); record.setId(key); record.setStatus(1); userRoleMapper.insert(record); // 复合主键查询 UserRole result = userRoleMapper.selectByCompositeKey(1001L, 2001L); // 通过Wrapper查询 QueryWrapper<UserRole> wrapper = new QueryWrapper<>(); wrapper.eq("user_id", 1001L) .eq("role_id", 2001L); List<UserRole> list = userRoleMapper.selectList(wrapper); ``` --- ### 三、关键配置说明 1. **主键类型必须设置为 `IdType.INPUT`** 在实体类主键字段添加注解: `@TableId(type = IdType.INPUT)` 表示主键值由用户输入而非自动生成[^4] 2. **MyBatis-Plus 配置(application.yml)** ```yaml mybatis-plus: mapper-locations: classpath*:mapper/**/*.xml global-config: db-config: id-type: input # 全局主键策略 configuration: map-underscore-to-camel-case: true # 开启驼峰映射 ``` 3. **依赖配置(pom.xml)** ```xml <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.5</version> </dependency> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> </dependency> ``` --- ### 四、注意事项 1. **复合主键限制** - 不支持自动生成主键(如自增ID) - `selectById()` 方法不可用,需自定义查询方法 - 更新操作需通过Wrapper指定所有主键字段 2. **事务管理** 在Service层添加 `@Transactional` 保证多主键操作原子性: ```java @Transactional public void updateUserRole(UserRoleKey key, Integer newStatus) { QueryWrapper<UserRole> wrapper = new QueryWrapper<>(); wrapper.eq("user_id", key.getUserId()) .eq("role_id", key.getRoleId()); UserRole entity = new UserRole(); entity.setStatus(newStatus); userRoleMapper.update(entity, wrapper); } ``` 3. **性能优化** 确保所有主键字段都建立索引: ```sql ALTER TABLE user_role ADD PRIMARY KEY (user_id, role_id); ``` --- ### 常见问题解决 - **报错:`Primary key not exist in entity`** 检查是否漏加 `@TableId(type = IdType.INPUT)` 注解 - **查询结果为空** 确认Wrapper中所有主键字段名称数据库列名一致(开启SQL日志调试) ```yaml mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl ``` - **插入时报主键冲突** 复合主键需保证 `equals()` 和 `hashCode()` 正确实现 通过以上配置,Spring Boot 项目可正确处理多主键表的 CRUD 操作[^3][^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值