学习springbootjap中所遇到的问题;@MapsId,@EmbeddedId,@Embeddable,@IdClass的使用

由于之前较多接触的是mybatis,当刚开始做springbootjpa项目是还是有些许困惑的;

@MapsId

官方的解释是

Designates a <code>ManyToOne</code> or
<code>OneToOne</code> relationship attribute that provides the
mapping for an {@link EmbeddedId} primary key, an attribute within
an <code>EmbeddedId</code> primary key, or a simple primary key of
the parent entity. The <code>value</code> element specifies the
attribute within a composite key to which the relationship
attribute corresponds. If the entity's primary key is of the same
Java type as the primary key of the entity referenced by the
relationship, the value attribute is not specified.

大概意思是:映射EmbeddedId主键中的一个属性,或者是父实体的普通主键,value元素指定复合主键的属性对应关系,如果实体的主键与关系引用的实体的主键具有相同的Java类型,则不指定value属性。(意思很难懂)

经过摸索,得到一些demo,如下

//包换复合主键的实体
@Entity
public class ClassStudent implements Serializable {

    @EmbeddedId
    private ClassStudentId id;//复合主键

    private String msg;

    @MapsId("studentId")
    @OneToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "student_id")
    private Student student;

    ...geter and setter
}
//可嵌入的类  在本例子中表示复合主键
@Embeddable//表示可内嵌
public class ClassStudentId implements Serializable {

    private Integer studentId;

    private Integer classId;

   //geter and setter

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ClassStudentId that = (ClassStudentId) o;
        return Objects.equals(studentId, that.studentId) &&
                Objects.equals(classId, that.classId);
    }

    @Override
    public int hashCode() {
        return Objects.hash(studentId, classId);
    }
}
//主题一对一对应的类
@Entity
public class Student implements Serializable {
    @Id
    @Column(name = "student_id",
            columnDefinition = "INT(11) UNSIGNED NOT NULL COMMENT '学生id'"
    )
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(name = "student_name",
            columnDefinition = "VARCHAR(255) COMMENT '学生姓名'"
    )
    private String name;
    @Column(name = "student_age",
            columnDefinition = "INT(11) UNSIGNED COMMENT '学生年龄'"
    )
    private Integer age;

    ...getter and setter
}

之前已经写出来了,查询没有问题,但是在保存的时候总是报错,大概是 assign id from null from property [student],表示需要相应的对应student,这是本人以为数据库中是不存在该字段的,所以就没有去管student,但是它们确实存在对应关系,保存时应该把student查询出来进行保存.具体代码如下:

@PostMapping
    public Object add(@RequestParam Integer studentId,@RequestParam Integer classId ){
        ClassStudent classStudent = new ClassStudent();
        Optional<Student> byId = studentRepository.findById(studentId);//报错时缺少的代码
        if(byId.isPresent()){
            ClassStudentId id = new ClassStudentId();
            id.setStudentId(studentId);//报错时缺少的代码
            id.setClassId(classId);
            classStudent.setId(id);
            classStudent.setMsg("走读");
            classStudent.setStudent(byId.get());
        }

@EmbeddedId和@IdClass

@EmbeddedId的用法上面已经展示,与之对应的有@IdClass,当使用idclass时,实体中须有和idclass类中属性个数的主键,并且一致.下边展示代码:

//作为主键id
@Data
public class StreamerSpecialityId implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 播主ID
     **/
    private Integer streamerId;

    /**
     * 播主服务ID
     */
    private Long specialityId;
}
//实体类
@Entity
@Table(name = "pls_service")
@IdClass(value = StreamerSpecialityId.class)
@Data
@EqualsAndHashCode(callSuper = true)
public class StreamerSpecialityEntity extends BaseEntity {

    private static final long serialVersionUID = 1L;

    /**
     * 播主ID
     */
    @Id
    @Column(
            name = "streamer_id",
            columnDefinition = "INT(11) UNSIGNED NOT NULL COMMENT '播主ID'"
    )
    private Integer streamerId = 0;

    /**
     * 专长ID
     */
    @Id
    @Column(
            name = "speciality_id",
            columnDefinition = "INT(11) UNSIGNED NOT NULL COMMENT '专长ID'"
    )
    private Long specialityId = 0L;

    /**
     * 专长
     */
    @MapsId("specialityId")//对应复合主键的其中一个
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "speciality_id")
    private SpecialityEntity speciality;
}
@Entity
@Table(name = "pls_speciality")
@Data
@EqualsAndHashCode(callSuper = true)
public class SpecialityEntity extends BaseEntity {

    private static final long serialVersionUID = 1L;

    /**
     * ID
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    /**
     * 播主ID
     */
    @Column(
            name = "streamer_id",
            columnDefinition = "INT(11) UNSIGNED NOT NULL COMMENT '播主ID'"
    )
    private Integer streamerId = 0;

    /**
     * 服务名称
     */
    @Column(
            name = "name",
            columnDefinition = "VARCHAR(32) NOT NULL COMMENT '服务名称'"
    )
    private String name = "";

    /**
     * 是否内置
     */
    @Column(
            name = "is_buildin",
            columnDefinition = "TINYINT(1) NOT NULL COMMENT '是否内置'"
    )
    private Boolean buildin = Boolean.FALSE;
}

保存和修改时需要报关联的实体设置上(对应关系是内联的),不然就走不通

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值