JpaRepository 注解 如何根据某非主键属性删除一个(或一批)记录?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JpaRepository 注解 如何根据某非主键属性删除一个(或一批)记录?相关的知识,希望对你有一定的参考价值。

比如有一个User表,有如下属性:
id,username,displayname,age
如何在JpaRepository的注解接口中注册删除的方法,
条件为username='abc',
或者age介于20到35?

参考技术A 两种方式:
方式1:假设Bean的属性xxx为主键,则在getXxx() 前添加以下注解
@Id
@SequenceGenerator(name="名称A", sequenceName="库中已存在的sequence名称",allocationSize=递增值)
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="名称A")

方式2:假设Bean的属性xxx为主键,则在getXxx() 前添加以下注解
@Id
@TableGenerator(name="名称A",allocationSize=递增值)//若不指定递增值,则生成的主键值不一定连续
@GeneratedValue(strategy=GenerationType.TABLE, generator="名称A")

总结:方式1:针对Oracle效率略高,但需要手工创建sequence才能使用。
方式2:不依赖数据库,可移植性好,但相比方式1,效率略低。
参考技术B @Entity(username="abc")

如何使用 JPA 和 Hibernate 在非主键上连接表

【中文标题】如何使用 JPA 和 Hibernate 在非主键上连接表【英文标题】:How to join tables on non Primary Key using JPA and Hibernate 【发布时间】:2015-06-15 14:45:21 【问题描述】:

我有 3 个模型 UserHouseUserHouseMap。我需要通过地图访问用户的房子。唯一的问题是这是一个旧数据库,我无法改变我需要使用非主键 user.nameUser 映射到 UserHouseMap 的事实。

Hibernate 不断给我错误提示我需要将它作为主键,否则我收到错误提示 A JPA error occurred (Unable to build EntityManagerFactory): Unable to find column with logical name: name in org.hibernate.mapping.Table(users) and its related supertables and secondary tables

我已尝试将@Formula 作为一种解决方法,但没有奏效。我也试过@JoinColumnOrFormula,但也没有用。这是我的解决方案@Formula

@Expose
@ManyToOne(targetEntity = House.class)
@Formula("(select * from houses inner join user_house_map on houses.house_name = user_house_map.house_name where user_house_map.user_name=name)")
public House house;

这是我对@JoinColumnOrFormula 解决方案的尝试。

@Expose
@ManyToOne(targetEntity = House.class)
@JoinColumnsOrFormulas(
        @JoinColumnOrFormula(formula=@JoinFormula(value="select name from users where users.id= id", referencedColumnName="name")),
        @JoinColumnOrFormula(column = @JoinColumn(name= "house_name", referencedColumnName="house_name"))
)
public House house;

这是我的地图

@Id
@GeneratedValue
@Expose
public Long id;

@Expose
@Required
@ManyToOne
@JoinTable(
        name="user_house_map",
        joinColumns=
        @JoinColumn(unique=true,name="user_name", referencedColumnName="name"),
        inverseJoinColumns=
        @JoinColumn(name="house_name", referencedColumnName="house_name"))
private House house;

这里是数据库架构

用户

                               Table "public.users"
        Column         |            Type             |          Modifiers          
-----------------------+-----------------------------+-----------------------------
 name                  | character varying(255)      |
 id                    | integer                     | not null 
Indexes:
    "user_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
    "housing_fkey" FOREIGN KEY (name) REFERENCES user_house_map(user_name) DEFERRABLE INITIALLY DEFERRED

房屋

                Table "public.houses"
    Column     |          Type          | Modifiers 
---------------+------------------------+-----------
 house_name    | character varying(255) | not null
 address       | text                   | 
 city          | text                   | 
 state         | text                   | 
 zip           | integer                | 
 zip_ext       | integer                | 
 phone         | text                   | 
Indexes:
    "house_pkey" PRIMARY KEY, btree (house_name)
Referenced by:
    TABLE "user_house_map" CONSTRAINT "house_map_fkey" FOREIGN KEY (house_name) REFERENCES house(house_name) DEFERRABLE INITIALLY DEFERRED

用户住宅地图

         Table "public.user_house_map"
   Column    |          Type          | Modifiers 
-------------+------------------------+-----------
 user_name   | character varying(255) | not null
 house_name  | character varying(255) | not null
Indexes:
    "user_house_map_pkey" PRIMARY KEY, btree (user_name)
    "user_house_map_house_key" btree (house_name)
Foreign-key constraints:
    "user_house_map_house_fkey" FOREIGN KEY (house_name) REFERENCES houses(house_name) DEFERRABLE INITIALLY DEFERRED
Referenced by:
    TABLE "users" CONSTRAINT "housing_fkey" FOREIGN KEY (name) REFERENCES user_house_map(user_name) DEFERRABLE INITIALLY DEFERRED

【问题讨论】:

【参考方案1】:

您的映射应该是这样的:

@Entity
public class User 

    @Id
    private Long id;

    private String name;

    @OneToMany(mappedBy = "user")
    private List<UserHouseMap> houses = new ArrayList<>();


@Entity
public class House 

    @Id
    @Column(name = "house_name", nullable = false, unique = true) 
    private String house_name;

    private String address;

    @OneToMany(mappedBy = "house")
    private List<UserHouseMap> users = new ArrayList<>();


@Entity
public class UserHouseMap implements Serializable 

    @Id @ManyToOne
    @JoinColumn(name = "user_name", referencedColumnName = "name")
    private User user;

    @Id @ManyToOne
    @JoinColumn(name = "house_name", referencedColumnName = "house_name")
    private House house;

UserHouse 都可以访问与数据库架构匹配的关联 UserHouseMap 实体。

【讨论】:

我知道这很旧,但我遇到了同样的错误。您的解决方案有效,但是我必须稍作更改,但我必须添加 @Column(name = "name", nullable = false) private String name;如果我不得不猜测原因,我的变量/属性名称与数据库表中的列名称不同。仅供遇到相同/类似问题的其他人参考。 谢谢。我添加了nullable=falseunique=true,它们必须由任何标识符列强制执行。 如果 user_name 和 house_name 是非主键,这将不起作用!!

以上是关于JpaRepository 注解 如何根据某非主键属性删除一个(或一批)记录?的主要内容,如果未能解决你的问题,请参考以下文章

数据库基础常用知识

具有非主键值的 FindAsync

如何将自动增量设置为非主键?

如何自动增加非主键? - SQL 服务器

如何使用 JPA 和 Hibernate 在非主键上连接表

MySQL主键索引非主键索引以及SQL语句中如何利用索引的