【问题标题】:is this approach unidirectional or bidirectional这种方法是单向的还是双向的
【发布时间】:2017-12-08 09:04:23
【问题描述】:

考虑以下实体

用户详情(包括车辆)

@Entity
public class UserDetails {

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int userId;
private String userName;

@OneToMany(mappedBy="user",cascade=CascadeType.ALL,orphanRemoval=true)
private List<Vehicle> vehicleList = new ArrayList<>();

//getter setters
}

车辆

@Entity
public class Vehicle {

@Id 
@GeneratedValue(strategy=GenerationType.AUTO)
private int vehicleId;
private String vehicleName;

@ManyToOne
@JoinColumn(name="user_id")
private UserDetails user;

//getter setters
}
  1. 如果我们可以使用下面的代码实现相同的数据库表,为什么我们应该使用上面的@OneToMany 代码?这里使用@OneToMany是不是只是给出了从用户侧访问车辆的解决方案 如果我不需要任何用户访问车辆,这是正确的配置吗?

  2. 而且由于它提供与双向相同的表配置,所以 我们应该说它是单向还是双向的方法?我认为根据代码我们无法从用户侧访问车辆,但用户从车辆侧访问,所以它是一种单向的吗?

用户详情(不含车辆)

@Entity
public class UserDetails {

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int userId;
private String userName;

//getter setters
}

表格用户详情

mysql> select * from userdetails;
+--------+------------+
| userId | userName   |
+--------+------------+
|        | First User |
+--------+------------+
1 row in set (0.00 sec)

桌车

mysql> select * from vehicle;
+-----------+-------------+---------+
| vehicleId | vehicleName | user_id |
+-----------+-------------+---------+
|         2 | karizma     |         |
|         3 | scooty-pep  |         |
+-----------+-------------+---------+
2 rows in set (0.00 sec)

【问题讨论】:

    标签: hibernate jpa one-to-many many-to-one


    【解决方案1】:

    非常好的观察和问题。

    是的,如果真的需要,您应该质疑@OneToMany。问题是该列表中有多少元素以及如何在 UI 上使用这些元素。我的经验法则是 10 个元素。

    假设您有一个银行账户和@OneToMany 交易。在某些起始页的 UI 中,您只显示 10 个最新的,甚至在您进入历史记录时,您总是得到或想要一个过滤列表。您实际上永远不想看到所有交易。但是@OneToMany 集合并没有给你任何控制——你不能过滤、排序或分页。只需加载全部(或在FetchType.LAZY 的情况下不加载)。

    通过 JPQL 查询删除集合和加载实体更加灵活和更好:

    @Query("SELECT v FROM Vehicle v WHERE v.userDetails = :userDetails")
    List<Vehicle> getVehicles(UserDetails userDetails); 
    

    您可以对此类查询进行额外的分页、排序和过滤。您还可以在业务案例需要时加入 FETCH 特定属性。

    总之,Query 方法比集合提供了更多的控制和性能。 Query 方法的缺点是您必须编写更多代码,并且导航域模型也更加困难。

    【讨论】:

      【解决方案2】:

      1) 单向就足够了,即使对于架构生成h2ddl 工具也是如此。请记住,您也可以只定义@OneToMany 进行单向映射。

      2) 除了获得对集合的访问权限外,在您的情况下,最大的原因是能够将 UserDetails 操作级联到 Vehicle 实体上,同时删除当您从 vehicleList 集合中清除它们时,车辆的数量.. 我猜您不想在逻辑上这样做。

      3) 单向的唯一缺点是您需要编写自定义查询才能为用户获取所有车辆。通过双向,您可以找到一个用户,并且车辆集合已经准备好进行延迟加载。

      我个人会保留 OneToMany,但删除 cascadingorphanRemoval 选项。

      【讨论】:

      【解决方案3】:

      答案 -afaik- 和你说的差不多

      这里使用@OneToMany 是否只是提供了访问 用户侧的车辆

      所以有了这个

      如果我不需要访问 任何用户的车辆,这是正确的配置吗?

      它可能不是正确的配置。我能想到的唯一原因是它会影响性能:当填充车辆列表时,如果有很多 UserDetails 和很多 Vehicles。

      可以为 List&lt;Vehicle&gt; 设置 FetchType.LAZY,但取决于 JPA 实现如何进行其内部优化和缓存,这可能并不总是被遵守。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-04-14
        • 2021-07-18
        • 2014-03-24
        • 2011-10-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多