JPA外键不是对象
Posted
技术标签:
【中文标题】JPA外键不是对象【英文标题】:JPA foreign key NOT AS OBJECT 【发布时间】:2018-02-19 01:51:36 【问题描述】:我在 mysql 中有两个简单的表
User ---(one-to-many)--- Expense
我正在使用 Spring JPA 来生成这两个实体。费用有 'user_id' 外键字段,它引用用户表中的 'id' 字段。
我在请求中使用 JSON 来填充表格
User
"id":1, "username":"user"
Expense
"id":1,
"user_id":1, <--- this value is not null in MySQL
"expense":"expense"
调用 API 时,我已经有了 user_id 值,我不想传递整个对象。
有没有办法告诉 Spring 这是引用 'User' 表中的 'id' 列的 INTEGER FOREIGN KEY?
我在网上找到的所有示例都只显示了如何通过在 JSON 中传递整个“用户”对象来实现。
我目前的实现:
@Entity
public class User
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", updatable = false, nullable = false)
private int id;
private String username;
@Entity
public class Car
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", updatable = false, nullable = false)
private int id;
@ManyToOne
private User user_id;
private String expense;
【问题讨论】:
【参考方案1】:您为什么涉及Car
实体?
对我来说这很简单:
@Entity
@Table(xxxx)
public class Expense implements Serializable
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
够了。 JPA 知道它是一个 FK,并将搜索 User
中的 ID 列。
【讨论】:
【参考方案2】:对于遇到此问题的任何人: 您可以像这样映射 user_id 列:
@Entity
@Data
public class Expense
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", updatable = false, nullable = false)
private Integer id;
@Column(name = "user_id", nullable = false)
private Integer userId;
@ManyToOne
@JoinColumn(name = "user_id", insertable = false, updatable = false)
private User user;
private String expense;
如果您只是曾经要像这样使用 user_id 来节省开支:
@Test
void saveExpense_withUserId_expenseSaved()
Expense expense = new Expense();
expense.setUserId(1);
assertTrue(expenseRepository.save(expense).getId() != null);
要非常小心!如果您尝试通过设置用户对象来保存费用,这将导致 user_id 为空
@Test
void saveExpense_withUser_throwsNullUserId()
User testUser = userRepository.findById(1).orElseThrow();
Expense expense = new Expense();
expense.setUser(testUser);
assertThrows(DataIntegrityViolationException.class, () -> expenseRepository.save(expense));
一种更简洁的方法是仅映射关系并在持久化引用时获取对 User 对象的引用:
@Entity
public class Expense
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", updatable = false, nullable = false)
private Integer id;
@ManyToOne
@JoinColumn(name = "user_id", nullable = false)
private User user;
private String expense;
@Test
void saveExpense_withUserReference_expenseSaved()
Expense expense = new Expense();
expense.setUser(userRepository.getById(1));
assertTrue(expenseRepository.save(expense).getId() != null);
您使用getById
获得的引用不会生成 SELECT 查询,因此与 findById
不同,它非常有效。注意:您可以通过使用 @ 切换提交来比较这两个代码987654321@
【讨论】:
【参考方案3】:您不应在请求中传输 JPA 实体。
为您要执行的功能创建具有必要 ID 的 POJOS,并在服务层中映射 Java 实体。
例如,对于查询,您只需实例化实体并设置 ID,如果您需要更多字段,您可以通过 id 执行 find() 并通过直接访问对象获取其余属性
【讨论】:
以上是关于JPA外键不是对象的主要内容,如果未能解决你的问题,请参考以下文章