Hibernate @ManyToOne 和@OneToMany 获取数据作为列表(记录数)

标签 hibernate spring-mvc hibernate-mapping entity-relationship hbmxml

  • 我有 2 个表
    1.Org[ORG_ID,PARENT_ID,LANG_ID(REFERENCES LANG)] 2.语言[LANG_ID,LANG_NAME]

  • 我的 JAVA 实体文件

    语言.java

    @Entity
    @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "langId")
    @JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
    @SuppressWarnings("serial")
    public class Lang implements java.io.Serializable {
        private BigDecimal langId;
        private String langName;
        private Set<Org> orgs = new HashSet<Org>(0);
        public Lang() {
        }
        public Lang(BigDecimal langId, Set<Org> orgs) {
            this.langId = langId;
            this.orgs = orgs;
        }
        public BigDecimal getLangId() {
            return this.langId;
        }
        public void setLangId(BigDecimal langId) {
            this.langId = langId;
        }
        public String getLangName() {
            return this.langName;
        }
        public void setLangName(String langName) {
            this.langName = langName;
        }public void setOrgs(Set<Org> orgs) {
            this.orgs = orgs;
        }
    }
    

    Org.java

        @Entity
    @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "orgId")
    @JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
    @SuppressWarnings("serial")
    public class Org implements java.io.Serializable {
        @Id
        @Column(name = "orgId")
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private BigDecimal orgId;   
        private BigDecimal parentOrgId;
        @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "langId",scope=Lang.class)
        public Org() {
        }
        public Org(BigDecimal orgId, BigDecimal parentOrgId, Lang lang) {
            this.orgId = orgId;
            this.parentOrgId = parentOrgId;
            this.lang = lang;
        }
        public BigDecimal getOrgId() {
            return this.orgId;
        }
        public void setOrgId(BigDecimal orgId) {
            this.orgId = orgId;
        }
        public BigDecimal getParentOrgId() {
            return this.parentOrgId;
        }
        public void setParentOrgId(BigDecimal parentOrgId) {
            this.parentOrgId = parentOrgId;
        }
        @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
        public Lang getLang() {
            return this.lang;
        }
        public void setLang(Lang lang) {
            this.lang = lang;
        }
    }
    
  • 我的 HBM Xml 文件

    Org.hbm.xml

        <hibernate-mapping package="com.test.entity">
        <class name="com.test.entity.Org" table="ORG">
        <id name="orgId" type="big_decimal">
            <column name="ORG_ID" precision="22" scale="0" />
            <generator class="increment" />
        </id>        
        <property name="parentOrgId" type="big_decimal">
            <column name="PARENT_ORG_ID" precision="22" scale="0" not-null="true" />
        </property>
        <many-to-one name="lang" class="com.test.entity.Lang" fetch="select">
            <column name="LANG_ID" precision="22" scale="0" not-null="true" />
        </many-to-one>        
        </class>
    </hibernate-mapping>
    

    Lang.hbm.xml

        <hibernate-mapping package="com.test.entity">
        <class name="com.test.entity.Lang" table="LANG">
        <id name="langId" type="big_decimal">
            <column name="LANG_ID" precision="22" scale="0" />
            <generator class="increment" />
        </id>
        <property name="langName" type="string">
            <column name="LANG_NAME" length="32" not-null="true" unique="true" />
        </property>
        <set name="orgs" table="ORG" inverse="true" lazy="true" fetch="select">
            <key>
            <column name="LANG_ID" precision="22" scale="0" not-null="true" />
            </key>
            <one-to-many class="com.test.entity.Org" />
        </set>
        </class>
    </hibernate-mapping>
    
  • 我的 Hibernate 查询是:"FROM Org as org WHERE org.parentOrgId = :parentOrgId or org.orgId=:parentOrgId"

  • 数据库图像 DATABASE

  • 当我从 Controller 运行时 List listOrganization = organizationService.getAllChildWithParetOrgs(parentId);//parentId = 0

  • 我得到结果 ObjectList/JSON 结果是

        [
      {
        "orgId": 1,
        "parentOrgId": 0,    
        "lang": {
          "langId": 1,
          "langName": "EN",
          "orgs": [
        {
          "orgId": 2,
          "parentOrgId": 1,
          "lang": 1,
          "currency": {
            "currencyId": 1,
            "currencyCode": "INR",
            "currencyName": "INR",
            "currencyDescription": "INDIAN RUPEE",
            "orgs": [
              2,
              1,
              {
            "orgId": 3,
            "parentOrgId": 1,
            "lang": 1,
            "currency": 1,                
              }
            ]
          }
        },
        1,
        3
          ]
        },
        "currency": 1
      },
      2, //---> Here No 2nd Organization Data
      3  //---> Here No 3rd Organization Data
    ]
    
  • 此处的Currency 也与Lang 表相同,它的Currency_Id 引用了Currency
  • 我无法在数组中获取第二和第三个组织数据,它在 Lang.Orgs 和 Lang.Orgs.Currency 中可用

  • 请帮忙解决这个问题。谢谢。

最佳答案

这会让你入门,我正在使用 Spring JPA2 与 Hibernate 和 Jackson。

我让 Hibernate 从实体创建我的表。

Spring 应用程序上下文如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:cache="http://www.springframework.org/schema/cache"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
    http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">

    <context:component-scan base-package="com.greg" />
    <tx:annotation-driven />
    <jpa:repositories base-package="com.greg.repository" />

    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="org.h2.Driver" />
        <property name="url" value="jdbc:h2:mem:test;DB_CLOSE_DELAY=-1" />
        <property name="username" value="sa" />
        <property name="password" value="" />
    </bean>

    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan" value="com.greg.entity" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
        </property>
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.hbm2ddl.auto">create</prop>
                <prop key="hibernate.show_sql">false</prop>
                <prop key="hibernate.format_sql">false</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.H2Dialect</prop>
            </props>
        </property>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

</beans>

Lang 实体看起来像这样:

@Entity
public class Lang {

    @Id
    @Column(name = "lang_id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long langId;

    @Column(name = "lang_name")
    private String langName;

    @OneToMany(fetch = FetchType.EAGER)
    @JoinColumn(name = "lang_id", referencedColumnName = "lang_id")
    private Set<Org> orgs;

组织实体如下所示:

@Entity
public class Org {

    @Id
    @Column(name = "org_id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long orgId;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "lang_id", referencedColumnName = "lang_id", updatable = false, insertable = false, nullable = false)
    private Lang lang;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "parent_id", referencedColumnName = "org_id", updatable = false, insertable = false, nullable = false)
    private Org parent;

这会在您的问题中创建表格。

Spring JPA 存储库很简单:

@Repository
@Transactional
public interface OrgRepository extends CrudRepository<Org, Long> {
}

@Repository
@Transactional
public interface OrgRepository extends CrudRepository<Lang, Long> {
}

如果我让 Jackson 连载我得到:

    {
    "orgId": 4,
    "lang": {
        "langId": 1,
        "langName": "EN",
        "orgs": null
    },
    "parent": {
        "orgId": 3,
        "lang": {
            "langId": 1,
            "langName": "EN",
            "orgs": null
        },
        "parent": {
            "orgId": 2,
            "lang": {
                "langId": 1,
                "langName": "EN",
                "orgs": null
            },
            "parent": null
        }
    }
}

我的测试是:

    @Test
@Transactional
public void test1() {

    try {
        Lang lang = makeLang("EN");
        langRepository.save(lang);
        assertNotNull(lang.getLangId());

        Org org1 = new Org();
        org1.setLang(lang);
        orgRepository.save(org1);

        Org org2 = new Org();
        org2.setLang(lang);
        org2.setParent(org1);
        orgRepository.save(org2);

        Org org3 = new Org();
        org3.setLang(lang);
        org3.setParent(org2);
        orgRepository.save(org3);

        assertEquals("EN", orgRepository.findOne(org1.getOrgId()).getLang().getLangName());
        assertNull(orgRepository.findOne(org1.getOrgId()).getParent());

        assertEquals("EN", orgRepository.findOne(org2.getOrgId()).getLang().getLangName());
        assertEquals(org1.getOrgId().longValue(), orgRepository.findOne(org2.getOrgId()).getParent().getOrgId().longValue());

        assertEquals("EN", orgRepository.findOne(org3.getOrgId()).getLang().getLangName());
        assertEquals(org2.getOrgId().longValue(), orgRepository.findOne(org3.getOrgId()).getParent().getOrgId().longValue());

        System.out.println(new ObjectMapper().writeValueAsString(org3));

        showTables("ORG");
        showTables("LANG");
    } catch (Exception e) {
        e.printStackTrace();
        fail();
    }
}

private Lang makeLang(String name) {
    Lang lang = new Lang();
    lang.setLangName(name);
    return lang;
}

关于Hibernate @ManyToOne 和@OneToMany 获取数据作为列表(记录数),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38875657/

相关文章:

java - NoSuchMethodError : javax. persistence.JoinColumn.foreignKey()

java - Struts Hibernate 以不同格式检索数据

java - Spring MVC 将对象绑定(bind)解释为字符串

java - 在 hibernate 生成的 Oracle 数据库模型类中更改主键类型

带内连接的 Hibernate 更新查询

java - postInstantiate buildSessionFactory 慢/内存巨大的数据库

java - Hibernate映射异常

java - Autowired 在自定义注销处理程序和自定义用户详细信息中给出 null

java - 在部署到 tomcat 服务器的 Spring Web 应用程序中,catalina.properties 文件由 spring 自动加载和检测。如何?

mysql - Hibernate 相当于分页查询