【问题标题】:Issue with Hibernate many to many mappingHibernate 多对多映射的问题
【发布时间】:2018-09-28 10:01:46
【问题描述】:

我有一个hibernate + oracle 程序。在那,我通过“ApplicationIdentityProviders”表在“Applications”和“IdentityProviders”表之间建立了多对多的关系。运行程序时出现以下错误:

Exception in thread "main" java.lang.RuntimeException: org.hibernate.MappingException: 
Could not determine type for: String, at table: identity_providers, for columns: [org.hibernate.mapping.Column(issuer)]
at com.oracle.hibernate.OCIAuthManager.setupTenant1Pdb1(OCIAuthManager.java:246)
at com.oracle.hibernate.OCIAuthManager.main(OCIAuthManager.java:283)

我无法弄清楚为什么。 Applications.java 是here。 IdentityProviders.java 是here。 ApplicationIdentityProviders.java 是here。主类是here。 Applications.hbm.xml如下:

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping>
 <class name = "Applications" table = "applications">

  <meta attribute = "class-description">
     This class contains the applications details. 
  </meta>

  <id name = "application_id" type = "int" column = "application_id">
     <generator class="native"/>
  </id>

  <set name = "application_id_providers" cascade="save-update" table="application_identity_providers">
     <key column = "application_id"/>
     <many-to-many column = "identity_provider_id" class="IdentityProviders"/>
  </set>

  <property name = "application_name" column = "application_name" type = "string"/>
  <property name = "attr" column = "attr" type = "short"/>
  <property name = "salary" column = "salary" type = "int"/>

 </class>

 <class name = "IdentityProviders" table = "identity_providers">

  <meta attribute = "class-description">
     This class contains the identity providers' details. 
  </meta>

  <id name = "identity_provider_id" type = "int" column = "identity_provider_id">
     <generator class="native"/>
  </id>

  <property name = "attr" column = "attr" type = "short"/>
  <property name = "protocols" column = "protocols" type = "short"/>
  <property name = "issuer" column = "issuer" type = "String"/>
  <property name = "cert1" column = "cert1" type = "String"/>
  <property name = "cert2" column = "cert2" type = "String"/>
  <property name = "is_tenant_default" column = "is_tenant_default" type = "short"/>

 </class>

</hibernate-mapping>

hibernate-1.cfg.xml如下:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>

    <property name="connection.url">jdbc:oracle:thin:@//localhost:1521/t1p1.oradev.oraclecorp.com</property>
    <property name="connection.username">username</property>
    <property name="connection.password">password</property>
    <property name="connection.driver_class">oracle.jdbc.OracleDriver</property>
    <property name="dialect">org.hibernate.dialect.Oracle12cDialect</property>

    <property name="show_sql">true</property>

    <property name="format_sql">true</property>
    <property name="hbm2ddl.auto">create</property>

    <!-- JDBC connection pool (use the built-in) -->
    <property name="connection.pool_size">1</property>
    <property name="current_session_context_class">thread</property>

    <mapping resource = "Applications.hbm.xml"/>

  </session-factory>
</hibernate-configuration>

我哪里错了?请帮忙。

更新 1:@Guillaume 的回答有效。但我现在收到以下错误:

Exception in thread "main" java.lang.RuntimeException:
org.hibernate.MappingException: An association from the table 
application_identity_providers refers to an unmapped class: 
IdentityProviders at
com.oracle.hibernate.OCIAuthManager.setupTenant1Pdb1(OCIAuthManager.java:246) 
at com.oracle.hibernate.OCIAuthManager.main(OCIAuthManager.java:283)

更新 2:我解决了更新 1 中的错误。现在我收到以下错误: 错误:ORA-01400:无法将 NULL 插入 ("SYS"."APPLICATION_IDENTITY_PROVIDERS"."APPLICATION_IDENTITY_PROVIDER_ID")

此错误发生在包含其他两个表的主键的中间表中,这些表具有多对多映射。在 ApplicationIdentityProviders.java 中,我有:

@Id
@SequenceGenerator(name="seq",sequenceName="oracle_seq",allocationSize=1)        
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="seq")
private int application_identity_provider_id;

当我运行程序时,相关的输出 sn -p 是: 休眠:

create table application_identity_providers (
application_identity_provider_id number(10,0) not null,
application_id number(10,0) not null,
identity_provider_id number(10,0) not null,
is_application_default number(5,0) not null,
primary key (application_id, identity_provider_id)
)

我哪里错了?

更新 3:给定“applications”表中的“application_name”,获取“identity_providers”和“saml_identity_providers”表中的全部内容。怎么做?

我尝试了以下方法:

Query query = entitymanager.createQuery("select a from Applications a join 
fetch a.ApplicationIdentityProviders ap " +
"join fetch ap.IdentityProviders ip where a.application_name = 
'newApplicationName'");

它给了我这个错误:

org.springframework.beans.factory.BeanCreationException: Error creating bean 
with name 'applicationsRepository' defined in file 
[D:\filepath\ApplicationsRepository.class]: Bean instantiation via 
constructor failed; nested exception is 
org.springframework.beans.BeanInstantiationException: Failed to instantiate 
[ApplicationsRepository]: Constructor threw exception; nested exception is 
java.lang.IllegalArgumentException: org.hibernate.QueryException: could not 
resolve property: ApplicationIdentityProviders of: Applications [select a 
from com.package.entities.Applications a join fetch 
a.ApplicationIdentityProviders ap join fetch 
ap.IdentityProviders ip where a.application_name = 'newApplicationName']

【问题讨论】:

  • @Guillaume,我无法解决更新 1 中提到的错误。如何解决?

标签: java xml hibernate many-to-many


【解决方案1】:

我认为对于这些行,您的类型应该是小写字符串(而不是字符串):

<property name = "issuer" column = "issuer" type = "string"/>
<property name = "cert1" column = "cert1" type = "string"/>
<property name = "cert2" column = "cert2" type = "string"/>

我认为您还需要在映射文件中声明 Java 类的限定名称,这可以通过在 hibernate 映射元素中添加包名来完成:

<hibernate-mapping package="com.oracle.hibernate">

【讨论】:

  • 那行得通。但我现在收到以下错误:线程“main”中的异常 java.lang.RuntimeException:org.hibernate.MappingException:来自表 application_identity_providers 的关联指的是未映射的类:com.oracle.hibernate.OCIAuthManager.setupTenant1Pdb1 的 IdentityProviders (OCIAuthManager.java:246) 在 com.oracle.hibernate.OCIAuthManager.main(OCIAuthManager.java:283)
  • 您必须为 Hibernate 提供合格的类名(包 + 名称)和/或在 hibernate-mapping 元素中声明包(请参阅我的编辑)
  • 我已经在 hibernate.cfg.xml 文件中给出了合格的类名。 我仍然收到与更新 1 中相同的错误。
  • 用于基于注释的映射,您没有使用注释。映射文件中应该加上限定名,我建议的改变你试过了吗?
  • 我尝试了您的更改,现在可以使用了。我有一个查询:给定“applications”表中的“application_name”,获取“identity_providers”和“saml_identity_providers”表中的全部内容。我该如何做到这一点?
【解决方案2】:

更快的方法是使用 Hibernate 工具自动生成映射文件。请参考以下文章。

How to install Hibernate Tools in Eclipse?
http://www.mkyong.com/hibernate/how-to-generate-code-with-hibernate-tools/

【讨论】:

  • 我收到更新 1 中发布的错误。我该如何解决?
  • 我做到了。我仍然遇到同样的错误。我哪里错了?我看不到关联在哪里引用未映射的类。请指导。
  • 只需尝试将此行中的以下属性(反向)设置为 false: 这将确保插入将在所有 3 个表中正常工作。
  • 它正在工作。给定“applications”表中的“application_name”,获取“identity_providers”和“saml_identity_providers”表中的全部内容。我该如何做到这一点?
【解决方案3】:

在 Application.java 中
删除以下行:

private Set<IdentityProviders> application_id_providers;

添加以下行:

@ManyToMany(cascade = { 
    CascadeType.PERSIST, 
    CascadeType.MERGE
})
@JoinTable(name = "application_identity_providers",
    joinColumns = @JoinColumn(name = "application_id"),
    inverseJoinColumns = @JoinColumn(name = "identity_provider_id")
)
private Set<IdentityProviders> id_providers;

在 IdentityProviders.java 中
添加以下行:

@ManyToMany(mappedBy = "id_providers")
private Set<Applications> applications;

@OneToMany(
    cascade = CascadeType.ALL, 
    orphanRemoval = true
)
private Set<SamlIdentityProviders> si_providers;

那么查询可能是:

SELECT a from Applications a JOIN fetch a.id_providers ip JOIN fetch ip.si_providers sip 
WHERE a.application_name = 'newApplicationName' AND ip.issuer = 'issuerName'

【讨论】:

  • 我需要 2 个不同的查询:1)在应用程序表中给定应用程序名称,在 identity_providers 和 saml_identity_providers 表中获取全部内容,2)在 identity_providers 表中给定颁发者,获取 saml_identity_providers 表。我能够执行 sql 命令来实现 1) 和 2) 但无法使用 JPA 查询来实现。
  • 另外,hbm.xml 将如何更改以反映 @OneToMany 映射? hbm.xml 文件:pastebin.com/1eyKErQk
  • 由于可以执行原生查询,请参考stackoverflow.com/questions/13012584/…并查找“随着JPA 2.1的到来,我们可以使用@SqlResultSetMapping注解来解决问题”
猜你喜欢
  • 2021-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-28
  • 2012-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多