前言
这次大创有个需求,在数据库建表时发现,user表与project表的关系表 user_project的主键为复合主键:
CREATE TABLE user_project( user_id INT(20), project_id INT(20), timestamp VARCHAR (50), donate_money DOUBLE(10,2), PRIMARY KEY (user_id,project_id) );
在网上看了几篇博客,以及在spring boot干货群咨询(感谢夜升额耐心解答)过后总算是做出来了。这里做个总结,方便日后查阅。
正文
这里采用@IdClass注解的方式来实现复合主键;
思路
实现
复合主键类
package com.hzy.Model; import java.io.Serializable; /** * Created by huangzhenyang on 2017/9/7. * UserProject的复合主键类 * * @Param userId * @Param projectId * @Param timestamp * 由这三个共同组成复合主键 */ public class UserProjectMultiKeysClass implements Serializable { private Integer userId; private Integer projectId; private String timestamp; //Constructor public UserProjectMultiKeysClass() { } public UserProjectMultiKeysClass(Integer userId, Integer projectId, String timestamp) { this.userId = userId; this.projectId = projectId; this.timestamp = timestamp; } //Setter and Getter public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } public Integer getProjectId() { return projectId; } public void setProjectId(Integer projectId) { this.projectId = projectId; } public String getTimestamp() { return timestamp; } public void setTimestamp(String timestamp) { this.timestamp = timestamp; } // ***重写hashCode与equals方法*** 划重点! @Override public int hashCode() { final int PRIME = 31; int result = 1; result = PRIME * result + ((userId == null) ? 0 : userId.hashCode()); result = PRIME * result + ((projectId == null) ? 0 : projectId.hashCode()); result = PRIME * result + ((timestamp == null) ? 0 : timestamp.hashCode()); return result; } @Override public boolean equals(Object obj){ if(this == obj){ return true; } if(obj == null){ return false; } if(getClass() != obj.getClass()){ return false; } final UserProjectMultiKeysClass other = (UserProjectMultiKeysClass)obj; if(userId == null){ if(other.userId != null){ return false; } }else if(!userId.equals(other.userId)){ return false; } if(projectId == null){ if(other.projectId != null){ return false; } }else if(!projectId.equals(other.projectId)){ return false; } if(timestamp == null){ if(other.timestamp != null){ return false; } }else if(!timestamp.equals(other.timestamp)){ return false; } return true; } }
注意:
复合主键类必须满足:
1. 实现Serializable接口;
2. 有默认的public无参数的构造方法;
3. 重写equals和hashCode方法。equals方法用于判断两个对象是否相同,EntityManger通过find方法来查找Entity时,是根据equals的返回值来判断的。hashCode方法返回当前对象的哈希码;
实体类
package com.hzy.Model; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.IdClass; import javax.persistence.Table; import java.io.Serializable; /** * Created by huangzhenyang on 2017/9/7. * */ @Entity @Table(name = "user_project") @IdClass(UserProjectMultiKeysClass.class) public class UserProject implements Serializable { private double donateMoney; private Integer userId; private Integer projectId; private String timestamp; @Id public Integer getUserId(){ return this.userId; } @Id public Integer getProjectId(){ return this.projectId; } @Id public String getTimestamp(){ return this.timestamp; } //getter and setter public double getDonateMoney() { return donateMoney; } public void setDonateMoney(double donateMoney) { this.donateMoney = donateMoney; } public void setUserId(Integer userId) { this.userId = userId; } public void setProjectId(Integer projectId) { this.projectId = projectId; } public void setTimestamp(String timestamp) { this.timestamp = timestamp; } @Override public String toString() { return "UserProject{" + "donateMoney=" + donateMoney + ", userId=" + userId + ", projectId=" + projectId + ", timestamp='" + timestamp + '\'' + '}'; } }
注意:
1. @IdClass标注用于标注实体所使用主键规则的类;
2. 在实体中同时标注主键的属性,比如这段代码中的userId,projectId以及timestamp ;
获取数据
方法一: 通过EntityManager获取,比如方法testUserProjectRepository()
方法二:通过Repository获取;这里记得在extends JpaRepository<UserProject,UserProjectMultiKeysClass>时把id的主键类指定为复合主键类UserProjectMultiKeysClass
public interface UserProjectRepository extends JpaRepository<UserProject,UserProjectMultiKeysClass>{ // 根据用户Id,找出用户参与的所有UserProject // TEST PASS List<UserProject> findByUserId(Integer userId); // 根据项目id,找出参与项目的所有UserProject // TEST PASS List<UserProject> findByProjectId(Integer projectId); // 根据用户id和项目id 找出所有的UserProject // TEST PASS List<UserProject> findByUserIdAndProjectId(Integer userId,Integer projectId); }
单元测试的代码
package com.hzy; import com.hzy.Model.UserProject; import com.hzy.Model.UserProjectMultiKeysClass; import com.hzy.Repository.UserProjectRepository; import com.hzy.Service.UserProjectService; import com.hzy.Service.UserService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.transaction.Transactional; import java.util.List; /** * Created by huangzhenyang on 2017/9/8. */ @RunWith(SpringRunner.class) @SpringBootTest public class UserProejctRepositoryTest { @Autowired @PersistenceContext private EntityManager entityManager; @Autowired private UserProjectRepository userProjectRepository; @Test public void testUserProjectRepository(){ UserProjectMultiKeysClass userProjectMultiKeysClass = new UserProjectMultiKeysClass(1, 1, "2017-09-08"); UserProject userProject = entityManager.find(UserProject.class,userProjectMultiKeysClass); System.out.println(userProject.toString()); } @Test public void testFindByUserId(){ List<UserProject> userProjects = userProjectRepository.findByUserId(1); for(UserProject userProject:userProjects){ System.out.println(userProject.toString()); } } @Test public void testFindByProjectId(){ List<UserProject> userProjects = userProjectRepository.findByProjectId(1); for(UserProject userProject:userProjects){ System.out.println(userProject.toString()); } } @Test public void testFindByUserIdAndProjectId(){ List<UserProject> userProjects = userProjectRepository.findByUserIdAndProjectId(1,1); for(UserProject userProject:userProjects){ System.out.println(userProject.toString()); } } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
问题内容: 我正在设计一个数据库,该数据库将用于存储来自许多不同来源的数据。我存储的实例由原始来源分配了唯一的ID。我存储的每个实例都应包含有关其来源的信息,以及与此来源相关联的ID。 作为示例,请考虑说明该问题的下表: 请注意,尽管每个来源的唯一,但有可能在不同来源中找到相同的来源。 我对关系数据库有一个不错的了解,但是与专家甚至是经验丰富的用户都相去甚远。我在此设计中面临的问题是应该用作主键。
问题内容: 我的JPA模型中有以下类(省略了getters,setters和无关字段): 我需要定义一个类,使得当从所述类生成DDL时,相应的表的主键被由密钥和。我尝试了以下方法: 但这会为表生成以下内容: 请注意,和都是可为空的,当我尝试将DDL加载到SQL Server时会导致以下错误 无法在表“ PRICE”中的可为空的列上定义PRIMARY KEY约束 我不明白为什么这些可以为空,因为在域
我在使用复合主键的hibernate实体集时遇到了问题。 我们的应用程序中有一个概念“Target”。目标id应该是其他三个表(实体)主id的组合。目标也有一个int标记。员工应该有一系列目标。SQL如下所示: 这个SQL工作正常,它允许我每个role_id(员工)多个目标,只要应用程序和项目分类不同。 这是目标ID类 这是目标类 这是employee类,我想在其中为每个员工存储一组目标。 通过h
JFinal ActiveRecord 从 2.0 版本开始,采用极简设计支持复合主键,对于 Model 来说需要在映射时指定复合主键名称,以下是具体例子: ActiveRecordPlugin arp = new ActiveRecordPlugin(druidPlugin); // 多数据源的配置仅仅是如下第二个参数指定一次复合主键名称 arp.addMapping("user_role",
EmbeddedId或IdClass注释用于表示复合主键。如何在没有(EmbeddedId或IdClass)的情况下使用复合主键? 如果可以在没有(EmbeddedId或IdClass)的情况下使用复合主键,那么如何使用EntityManager.find(Entity Class,Object primaryKey)方法在复合主键(Multiple primaryKey)的情况下查找实体(因为没
问题内容: 创建一个名为“ sqlite_autoindex_mytable_1”的索引。我在“ SQlite Expert”中看到了它。在“要索引的字段”框中,它同时显示col1和col2。 在这篇文章中:https : //dba.stackexchange.com/a/14260 它说如果我想在没有col1的JOIN查询中使用col2,则必须为col2创建单独的索引。 因此,我需要添加: 如