Sping Data Jpa 一对多单向映射

本文介绍在Java持久化API (JPA) 中如何实现一对多的关系映射。主要探讨了两种方法:一是通过第三方表,二是通过外键列,并提供了具体的代码示例。

/**
* @author StormMaybin
* @date 2017-01-17
*/


生命不息,奋斗不止!


一对多映射关系

 在JPA中,用@OneToMany来标识一对多的关系。实现一对多的单向关联,只需在代表一的实体(Company)中使用@OneToMany映射标注就可以了,代表多的实体不需要使用任何映射标注。

  有两种方式实现一对多的单向关联。一种是在只使用@OneToMany来标识,这种方式是通过一张第三方表来保存关系。还有一种是使用@OneToMany和@JoinColumn来标注,这种方式是在多的一方(Employee)的表中增加一个外键列来保存关系。

OneToMany

Company.java

package com.stormma.model;

import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

/**
 * Created by mayongbin01 on 2017/1/17.
 */
@Entity
@Table(name = "company")
public class Company {

    //唯一标识公司
    @Id
    @GeneratedValue
    private int id;

    //公司名字
    private String name;

    @OneToMany(cascade = {CascadeType.ALL})
    private List<Employee> employees;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Employee.java

package com.stormma.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * Created by mayongbin01 on 2017/1/17.
 */
@Entity
@Table(name = "employee")
public class Employee {

    //唯一标识雇员
    @Id
    @GeneratedValue
    private int id;

    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

生成的表结构

CREATE TABLE `employee` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

DROP TABLE IF EXISTS `company`;
CREATE TABLE `company` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

DROP TABLE IF EXISTS `company_employees`;
CREATE TABLE `company_employees` (
  `company_id` int(11) NOT NULL,
  `employees_id` int(11) NOT NULL,
  UNIQUE KEY `UK_lg2r1rg13q18sa62l1y7un4or` (`employees_id`),
  KEY `FKd66w6jx84tydyd8sf9mpqh5je` (`company_id`),
  CONSTRAINT `FKd66w6jx84tydyd8sf9mpqh5je` FOREIGN KEY (`company_id`) REFERENCES `company` (`id`),
  CONSTRAINT `FKnntnqhhla66c4h9ddbnlvqk2x` FOREIGN KEY (`employees_id`) REFERENCES `employee` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

OneToMany+JoinColumn

Company.java

package com.stormma.model;

import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;

/**
 * Created by mayongbin01 on 2017/1/17.
 */
@Entity
@Table(name = "company")
public class Company {

    //唯一标识公司
    @Id
    @GeneratedValue
    private int id;

    //公司名字
    private String name;

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "company_id")
    private List<Employee> employees;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Employee.java

package com.stormma.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * Created by mayongbin01 on 2017/1/17.
 */
@Entity
@Table(name = "employee")
public class Employee {

    //唯一标识雇员
    @Id
    @GeneratedValue
    private int id;

    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

结构

Hibernate: create table company (id integer not null auto_increment, name varchar(255), primary key (id))
Hibernate: create table employee (id integer not null auto_increment, name varchar(255), company_id integer, primary key (id))
Hibernate: alter table employee add constraint FK5v50ed2bjh60n1gc7ifuxmgf4 foreign key (company_id) references company (id)
### Spring Data JPA 注解使用方法 #### 实体类注解 实体类是映射到数据库表的对象。为了将 Java 类声明为持久化实体,需使用 `@Entity` 和其他相关注解。 - **@Entity** 此注解用来标记一个普通的Java类作为实体,使之成为JPA管理的一部分[^5]。 ```java @Entity public class User { } ``` - **@Table** 当需要指定实体对应的具体数据库表名称时可以使用该注解。如果未提供,则默认采用无下划线的小写形式的类名作为表名。 ```java @Table(name = "users") ``` - **@Id** 用于标识唯一主键字段,在每个实体中至少存在一个这样的属性来表示记录的身份[^3]。 ```java @Id private Long id; ``` - **@GeneratedValue** 配合 `@Id` 使用,指明主键生成策略,默认情况下会根据底层数据源自动选择合适的算法(如序列号、UUID等)。常见的配置方式有: - `GenerationType.AUTO`: 让框架自己决定最适合的方式; - `GenerationType.IDENTITY`: 利用数据库自身的自增列特性; - `GenerationType.SEQUENCE`: 基于特定的数据序列表达式创建新值; - `GenerationType.TABLE`: 维护一张额外表格存储版本信息并从中读取下一个可用编号。 ```java @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; ``` #### 关联关系注解 描述不同实体之间的联系也是开发过程中不可或缺的一环。以下是几种常用的关联类型及其相应的注解说明: - **一对一 (OneToOne)** 适用于两个对象之间仅能建立单向或双向一对一的关系场景。比如用户与其个人资料页之间的绑定就可以通过这种方式建模。 ```java @OneToOne(cascade = CascadeType.ALL) @JoinColumn(name = "profile_id", referencedColumnName = "id") private Profile profile; ``` - **一对 / 对一 (OneToMany & ManyToOne)** 最常见的情况莫过于父级分类下的子项集合或是订单明细中的商品条目了。前者是从整体视角出发定义个个体隶属于同一个上级单位;后者则是强调各个成员各自归属哪个集体。 ```java // Parent side, OneToMany example @OneToMany(mappedBy = "parent", cascade = {CascadeType.PERSIST, CascadeType.MERGE}) private Set<Child> children; // Child side, ManyToOne example @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "parent_id") private Parent parent; ``` - ** (ManyToMany)** 对于那些既不是单一也不是层次结构而是网状交错存在的事物间相互作用模式而言,“”的概念就显得尤为重要了。例如学生选课系统里每位同学可以选择若干门课程而每门科目也可能被名学员修习。 ```java @ManyToMany @JoinTable( name = "student_courses", joinColumns = @JoinColumn(name = "student_id"), inverseJoinColumns = @JoinColumn(name = "course_id")) private List<Course> courses; ``` #### 查询方法支持 除了上述基础功能外,Spring Data JPA 还提供了便捷的方法命名约定机制以及基于接口的仓库定制能力,使得开发者几乎不需要编写任何SQL语句就能完成大部分CRUD操作[^4]。 例如要查找所有姓张的人的信息,只需简单地在Repository接口内增加如下签名即可: ```java List<User> findByLastName(String lastName); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值