【问题标题】:jpa one-to-many sql error while initializing初始化时jpa一对多sql错误
【发布时间】:2012-10-17 05:20:54
【问题描述】:

在我的java spring webapp中我有关系:一个帐户可以有多个组,一个组只能有一个帐户。

集团实体:

@Entity
@Table(name = "group")
@Inheritance(strategy = InheritanceType.JOINED)
public class Group {

@Id
@GeneratedValue(generator = "group_id", strategy = GenerationType.SEQUENCE)
@SequenceGenerator(name = "group_id", sequenceName = "group_group_id_seq", allocationSize = 1)
@Column(name = "group_id")
private Long id;

@Basic
@NotBlank
@Column(name = "name")
private String name;

@ManyToOne(targetEntity = Account.class, fetch = FetchType.LAZY)
@JoinColumn(name = "account_id")
private Account account;

@Basic
@NotBlank
@Column(name = "all")
private boolean all;

@ManyToMany(targetEntity = Word.class, fetch = FetchType.LAZY)
@JoinTable(name = "group_word", joinColumns = {@JoinColumn(name="group_id")}, inverseJoinColumns = {@JoinColumn(name="word_id")})
private List<Word> words;

getters/setters...

账户实体:

@Entity
@JsonIgnoreProperties(ignoreUnknown = true)
@Table(name = "account")
@Inheritance(strategy = InheritanceType.JOINED)
public class Account  extends User implements UserDetails {

@Id
@GeneratedValue(generator = "account_id", strategy = GenerationType.SEQUENCE)
@SequenceGenerator(name = "account_id", sequenceName = "account_account_id_seq", allocationSize = 1)
@Column(name = "account_id")
private Long accountId;

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

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

@Transient
private String repeatedPassword;

@DateTimeFormat(iso = ISO.DATE_TIME)
@Column(name = "registration_date")
Date registrationDate = Calendar.getInstance().getTime();

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

@ManyToMany(targetEntity = Role.class, fetch = FetchType.LAZY)
@JoinTable(name = "account_role", joinColumns = {@JoinColumn(name="account_id")}, inverseJoinColumns = {@JoinColumn(name="role_id")})
private List<Role> roles;

public List<Role> getRoles() {
    return roles;
}

public void setRoles(List<Role> roles) {
    this.roles = roles;
}

@OneToMany(mappedBy="account", fetch = FetchType.LAZY)
private List<Group> groups;

public List<Group> getGroups() {
    return groups;
}

public void setGroups(List<Group> groups) {
    this.groups = groups;

getters/setters...

当我调用这个服务方法时:

public List<Group> listUserGroups(String username) {
    try {
        Account foundAccount = accountDao.findUserByUsername(username);
        List<Group> userGroups = foundAccount.getGroups();
        userGroups.size();
        return userGroups;
    } catch (UserNotFoundException unf) {
        logger.error("User not found: " + username, unf.getMessage());
        return Collections.emptyList();
    }
}

我在线出错:

userGroups.size();

错误:

00:27:27,528 DEBUG [org.hibernate.engine.StatefulPersistenceContext] - initializing non-lazy collections
00:27:27,528 DEBUG [org.hibernate.loader.Loader] - loading collection: [pl.net.grodek.snd.model.Account.groups#116]
00:27:27,528 DEBUG [org.hibernate.jdbc.AbstractBatcher] - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
00:27:27,528 DEBUG [org.hibernate.SQL] - select groups0_.account_account_id as account4_20_1_, groups0_.group_id as group1_1_, groups0_.group_id as group1_19_0_, groups0_.account_account_id as account4_19_0_, groups0_.all as all19_0_, groups0_.name as name19_0_ from group groups0_ where groups0_.account_account_id=?
00:27:27,544 DEBUG [org.hibernate.jdbc.AbstractBatcher] - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
00:27:27,544 DEBUG [org.hibernate.util.JDBCExceptionReporter] - could not initialize a collection: [pl.net.grodek.snd.model.Account.groups#116] [select groups0_.account_account_id as account4_20_1_, groups0_.group_id as group1_1_, groups0_.group_id as group1_19_0_, groups0_.account_account_id as account4_19_0_, groups0_.all as all19_0_, groups0_.name as name19_0_ from group groups0_ where groups0_.account_account_id=?]
org.postgresql.util.PSQLException: ERROR: syntax error near "group"
Position: 227
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2103)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1836)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:512)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:388)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:273)
at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeQuery(NewProxyPreparedStatement.java:76)
at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
at org.hibernate.loader.Loader.getResultSet(Loader.java:1953)
at org.hibernate.loader.Loader.doQuery(Loader.java:802)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
at org.hibernate.loader.Loader.loadCollection(Loader.java:2166)
at org.hibernate.loader.collection.CollectionLoader.initialize(CollectionLoader.java:62)
at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:627)
at org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:83)
at org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:1863)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:369)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:111)
at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:134)
at org.hibernate.collection.PersistentBag.size(PersistentBag.java:248)
at pl.net.grodek.snd.service.GroupServiceImpl.listUserGroups(GroupServiceImpl.java:47)
at pl.net.grodek.snd.service.GroupServiceImpl.listUserGroups(GroupServiceImpl.java:1)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at 

我认为问题出在 jpa 生成的查询中:

select groups0_.account_account_id as account4_20_1_, groups0_.group_id as group1_1_, groups0_.group_id as group1_19_0_, groups0_.account_account_id as account4_19_0_, groups0_.all as all19_0_, groups0_.name as name19_0_ from group groups0_ where groups0_.account_account_id=?

account_id 和 group_id 加倍的地方。但我的问题是为什么会这样。请为我澄清这个问题,因为我没有想法:(

编辑:

哦,我忘记了数据库表:

CREATE TABLE "group"
(
    group_id bigserial NOT NULL,
    name character varying(150)[] NOT NULL,
    "all" boolean NOT NULL DEFAULT false,
    account_id bigint NOT NULL,
    CONSTRAINT group_id_pk PRIMARY KEY (group_id ),
    CONSTRAINT account_id_fk FOREIGN KEY (account_id)
    REFERENCES account (account_id) MATCH SIMPLE
    ON UPDATE NO ACTION ON DELETE NO ACTION
)

CREATE TABLE account
(
    account_id bigserial NOT NULL,
    username character varying(32),
    password character varying(64),
    email character varying(100),
    registration_date timestamp with time zone NOT NULL,
    word_for_today bigint,
    groups_on_page integer NOT NULL,
    CONSTRAINT account_pk PRIMARY KEY (account_id ),
    CONSTRAINT word_fk FOREIGN KEY (word_for_today)
  REFERENCES word (word_id) MATCH SIMPLE
  ON UPDATE NO ACTION ON DELETE NO ACTION,
    CONSTRAINT unique_mail UNIQUE (email ),
    CONSTRAINT unique_username UNIQUE (username )
)

【问题讨论】:

  • 从组到账户的关系是ManyToOne。您不需要连接表。您似乎没有连接表,但您使用的是@JoinTable
  • 不知道是不是因为“group”实际上是SQL中的一个关键字。换成别的东西有用吗?
  • 你觉得呢?正如您在我自己的回答中看到的那样,我将其更改为组并且它可以正常工作,但我不确定为什么会这样。

标签: java spring jpa jpql


【解决方案1】:

根据我的经验,问题与持久性上下文的范围有关。 您正在使用 DAO 来检索实体,因此您可能会假装访问已分离实体的属性。
说得轻巧,也许是在 accountDao.findUserByUsername() 函数的范围内,当您通过实体管理器检索实体时初始化/实例化持久性上下文,但在对象返回后,此函数的范围和持久性的实例结束上下文(实体管理器)。换句话说,在 Java SE 应用程序环境中,您不会以静态方式引用 entityManager 以使其在所有应用程序运行范围内保持活动状态。

除此之外,Hibernate 还与代理一起工作。这意味着,按照您的示例,您检索加载了所有基本属性的对象 Account ,但相反的是惰性关系(组、角色等)。 调用 getGroups() 时不会强制代理查询组列表,但是当您调用 size 时,代理必须查询它们。 为了更好地理解这一点和一般的 Hibernate 行为,我建议您阅读 Hibernate in Action - Java Persistence with Hibernate 一书的第 13 章理解代理(isbn 1-932394-88 -5)

问候

【讨论】:

  • 我认为这不是原因,因为我有其他关系使用这个 dao 并且没有这样的问题。
【解决方案2】:

我将组表名称更改为组,它可以工作。但请谁能告诉我为什么会这样。在早期的关系中,我没有这样神秘的问题。我正在失去理智。 :(

也许有人发现我的代码有问题?我的帐户->群组关系是否设置良好?

编辑:正如@AdrianShum 所说,组是一个 SQL 关键字,因此当我更改为另一个名称时,我的映射工作

【讨论】:

    猜你喜欢
    • 2011-08-21
    • 2022-01-04
    • 2017-05-16
    • 2021-12-13
    • 1970-01-01
    • 2012-03-03
    • 2014-03-01
    • 2014-06-12
    • 1970-01-01
    相关资源
    最近更新 更多