【问题标题】:JPA join in spring boot applicationJPA 加入 Spring Boot 应用程序
【发布时间】:2016-02-02 09:08:44
【问题描述】:

我已阅读示例,但有我个人的问题要问您。 我有 2 张桌子:

Role: id, name User: id, login, name, role_id

角色实体

@Entity
@Table(name = "role")
public class Role {

@Id
@Column(name = "id")
private long id;

@Column(name = "name", length = 45)
private String name;

@OneToMany(cascade = CascadeType.ALL, mappedBy = "role")
private Set<User> user = new HashSet<>();

//getters and setters

用户实体

@Entity
@Table(name = "user")
public class User {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id",insertable = false, updatable = false)
private long id;

@Column(name = "login")
private String login;

@Column(name = "user_name")
private String userName;

@ManyToOne(fetch = FetchType.LAZY)
private Role role;

//getters and setters

和存储库:

public interface UserRepository extends JpaRepository<User, Long> {

String Q_GET_ALL_USERS = "from User u left join Role r on u.role_id=r.id";

@Query(Q_GET_ALL_USERS)
Collection<User> getAllUsers();

此代码显示:Caused by: java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: Path expected for join! [from com.example.jpa.model.User u left join Role r on u.role_id=r.id]

我如何理解实体不能包含“id”(在我的情况下为Role)作为参考,我应该删除此字段。但是实体应该有“@Id”。

在这种情况下,我应该在“角色”中创建新列吗?或者我可以使用更漂亮的决定?

我把所有项目都放到bb

【问题讨论】:

  • 您忘记了 JPQL 开头的“SELECT u”。
  • 是的,我忘了select u

标签: java spring hibernate jpa join


【解决方案1】:

不,您应该在User 中创建一个新列。

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "role_id")
private Role role;

【讨论】:

  • 请注意,如果我们使用@OneToMany 和mappedBy Hibernate 默认使用@JoinColumn。
  • @qizer 提醒您应该接受对您有帮助的答案。
【解决方案2】:

谢谢大家的回答。正确的实体和下面的查询(加上表架构)。

表(查询)

CREATE TABLE role (
  id   INT         NOT NULL PRIMARY KEY,
  name VARCHAR(45) NOT NULL
);

CREATE TABLE user (
  id        INT         NOT NULL PRIMARY KEY IDENTITY,
  login     VARCHAR(45) NOT NULL,
  user_name VARCHAR(45) NOT NULL,
  role_id   INT         NOT NULL,
  FOREIGN KEY (role_id) REFERENCES role (id)
);

实体:

@Entity
@Table(name = "user")
public class User {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id",insertable = false, updatable = false)
private long id;

@Column(name = "login")
private String login;

@Column(name = "user_name")
private String userName;

@ManyToOne(fetch = FetchType.LAZY)
private Role role;

//getters and setters
}

和

@Entity
@Table(name = "role")
public class Role {

@Id
@Column(name = "id")
private long id;

@Column(name = "name", length = 45)
private String name;

@OneToMany(cascade = CascadeType.ALL, mappedBy = "role")
private Set<User> user = new HashSet<>();

//getters and setters
}

存储库

public interface UserRepository extends JpaRepository<User, Long> {

String Q_GET_ALL_USERS = "select u from User u left join u.role";

@Query(Q_GET_ALL_USERS)
Collection<User> getAllUsers();
}

@v-ladynev 提议的替代决定(仅在User 中使用@ManyToMany)。您可以在 answer 下的 cmets 中找到更多详细信息。 当我检查这个决定时,我会更新这个答案(我希望我不会忘记它:-))

【讨论】:

    【解决方案3】:

    要在 HQL (JPQL) 中使用连接,您不需要 on 子句

    String Q_GET_ALL_USERS = "select u from User u left join u.role";
    

    这个查询没有任何意义,因为你没有在 where 子句中使用role。

    如果您想获取具有提取角色的用户,您可以使用join fetch

    String Q_GET_ALL_USERS = "select u from User u left join fetch u.role";
    

    更新

    User 和 Role 的架构不常用。我建议您将@ManyToMany 从用户关联到角色,并从Role 中删除任何user 关联

    @Entity
    @Table(name = "user")
    public class User {
    
        @ManyToMany(fetch = FetchType.LAZY)
        private Set<Role> roles;
    
    }
    
    @Entity
    @Table(name = "role")
    public class Role {
    
        @Id
        @Column(name = "id")
        private long id;
    
        @Column(name = "name", length = 45)
        private String name;
    
    }
    

    【讨论】:

    • 您好,感谢您的回复。在我的情况下,这两个查询都是正确的,但您的回答为我提供了有用的信息。
    • 我也对“角色”实体有疑问。我读过@OneToMany 必须是一个集合(集合)。我可以对代码进行任何更改,而不是 Set&lt;User&gt; user 使用 User user(不收集)吗?
    • @qizer 否。您需要一个集合用于@OneToMany 关联 — Set 或 List。我更新了我的答案。
    • @v.ladynev +1 建议使用@ManyToMany 关联。但是为什么User 类中的Role 不是List 或Set?
    • @v.ladynev 很好的建议,但我收到了您的建议:Caused by: org.hibernate.AnnotationException: Illegal attempt to map a non collection as a @OneToMany, @ManyToMany or @CollectionOfElements: com.example.jpa.model.User.role。如果我设置集合private Set&lt;Role&gt; role 我看到org.hsqldb.HsqlException: user lacks privilege or object not found: USER_ROLE
    【解决方案4】:

    模型

    @Entity
    @Table(name = "sys_std_user")
    public class StdUser {
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        @Column(name = "class_id")
        public int classId;
        @Column(name = "user_name")
        public String userName;
    }
    
    @Entity
    @Table(name = "sys_std_profile")
    public class StdProfile {
        @Id
        @Column(name = "pro_id")
        public int proId;
        @Column(name = "full_name")
        public String fullName;
    }
    

    控制器

    @PersistenceUnit
    private EntityManagerFactory emf;
    
    @GetMapping("/join")
        public List actionJoinTable() {
            EntityManager em = emf.createEntityManager();
            List arr_cust = em
                    .createQuery("SELECT u.classId, u.userName, p.fullName FROM StdUser u, StdProfile p WHERE u.classId=p.proId")
                    .getResultList();
            return arr_cust;
        }
    

    结果:

    [
        [
            1,
            "Ram",
            "Ram Pukar Chaudhary"
        ],
        [
            2,
            "Raja",
            "Raja Kishor Shah"
        ]
    ]
    

    【讨论】:

    • 我不推荐这种方法,另外,它不使用连接。
    猜你喜欢
    • 2020-12-21
    • 1970-01-01
    • 2020-10-19
    • 1970-01-01
    • 1970-01-01
    • 2018-12-01
    • 2020-12-09
    • 2016-10-12
    • 2018-09-17
    相关资源
    最近更新 更多