如果使用hibernate不存在该行,如何在表中添加行?

时间:2011-11-02 10:53:11

标签: java hibernate orm

我在数据库中有一个表,其中包含以下结构(数据):

+--------------------------+
      Organization
+--------------------------+
    org_id | name
---------------------------
   1       | IBM
---------------------------
   2       | Google
---------------------------
   3       | Yahoo
+--------------------------+

在上表中,org_id是主键。我想在此表中插入新行,只找到新的组织名称。

应该使用此表的其他表如下:

+--------------------------+
      Project
+--------------------------+
 project_id| description
---------------------------
   1       | foo
---------------------------
   2       | bar...
---------------------------
   3       | xyz
+--------------------------+

和连接项目和组织表的表格如下:

+--------------------------+
      Project_Client
+--------------------------+
pc_id | project_id | org_id
---------------------------
   1  | 1          | 1
---------------------------
   2  | 1          | 3
---------------------------
   3  | 2          | 2
+--------------------------+

我想使用hibernate实现类似的东西:

每个项目都有其描述和客户名称列表。客户名称只是组织名称。因此,为了避免重复数据,我创建了名为Organization的表。

在数据库中插入项目信息时,如果Organization表中已存在任何客户端名称,则在org_id表中插入行时应使用该客户端名称的Project_Client。如果Organization表中没有客户端名称,则应在Organization表中添加新行,然后在org_id表中使用相应的Project_Client

我们可以使用hibernate实现这样的东西吗?

  

编辑#1

之前我的课程如下:

class Project {
    int projectID;
    String description;
    set<String> clients;
    set<String> employers;
    set<String> technologies;
}

如您所见,每个项目也将拥有一个或多个客户,雇主和技术。我想避免跨多个项目重复组织名称和技术名称。例如,如果对于某些项目客户端是XYZ而对于其他项目,客户端是XYZ,那么我只想在org_id表中引用相同的organization,而不是为同一组织创建单独的行。

我希望hibernate能让我轻松实现这一目标,但我无法使用或使用和实现它。所以我改变了我的类结构如下:

class Entity {
    int id;
    String name;
}

class Client extends Entity {
    // nothing special here
}

class Employer extends Entity {
    // nothing special here
}

class Technology extends Entity {
    // nothing special here
}

class Project {
    int projectID;
    List<Client> clients;
    List<Employer> employers;
    List<Technology> technologies;
}

我为ClientEmployerTechnology类创建了单独的映射文件。即使这样也没有帮助我。

3 个答案:

答案 0 :(得分:1)

我没有完整的实施,但我希望如果您按照以下步骤实现这一目标。

第1步:创建与表Project_ClientOrganization对应的Bean。

第2步:organizationId bean中有一个字段Project_Client

第3步:准备Project_Client对象进行插入时,触发查询以查找已存在的Organization是否从中获取organizationId数据库并将其设置为Project_Client

第4步:另外在数据库中为Organization创建一个新条目,并在Project_Client bean中将其“id”设置为“organizationId”。

第5步:Project_Client bean保存到数据库。

答案 1 :(得分:1)

简单的one-to-many ProjectOrganization应该可以解决问题。 每当您尝试将组织添加到项目时

这些类可以定义为:

public class Project {
    private int projectId;
    private Set<Organization> clients;

    public void addClient(Organization org){
        if(clients==null){
            clients=new HashSet<Organization>();
        }
        org.setProject(this);
        clients.add(org);
    }
}

public class Organization{
    private int organizationId;
    private Project project;       //if bi-directional relation is required.
}

因此

  1. Project将映射到表项目
  2. Organization将映射到表格
  3. 该关系可以映射到Project_Client
  4. 该关系可以映射为:

    注意: many-to-manyunique=true一起使用,因为一对多不知道联接表

    <class name="Project" table="Project">
      <!-- just showing the relational mapping here , you can figure out the rest -->
      <set name="clients" table="Project_Client">
       <key column="project_id"/>
       <many-to-many class="Organization" unique="true" column="org_id"/>
      </set>
    </class>
    

    其他类正常映射

    如果您不想处理Organization的生命周期,可以考虑

    Cascading

    将组织添加到项目

    • 查询以查找具有名称的组织。
    • 如果组织发现使用帮助函数addClient()
    • 将组织添加到项目中
    • 如果找不到任何组织,请创建一个,然后使用addClient()

    希望这有帮助。

    编辑后的问题:

    编辑该问题以支持多个Set字符串[Client,Technology] 由于您的问题陈述要求EmployerTechnologyClient是独立的实体(即它们应该在不同的Projects之间共享),您需要将它们定义为单独的实体。在技​​术扩展实体的问题仅仅是因为它具有类似的属性(将来可能不会这样)。

    因此,我建议将组织,雇主和技术中的每一个映射到单独的表。由于这些与Project有多对多的关系,因此每个都有一个单独的关系表。以下是更新的表,类和hibernate映射:

    表结构

    Project (projectId, ...)
    Organization (orgId,name)
    Technology (technologyId,name)
    Employer(employerId,name)
    

    对应的关系表

    project_organization (projectid,orgid)
    project_employer (projectid,employerid)
    project_tecnology(projectid,technologyid)
    

    班级结构

    public class Project{
     private int projectId;
     private Set<Organization> clients;
     private Set<Employer> employer;
     private Set<Technology> technology;
    
      //..appropriate getter/setter and helper functions [like the one shown above]
    }
    

    Hibernate Mapping

    <class name="Project" table="Project">
      <!-- just showing the relational mapping here , you can figure out the rest -->
      <set name="clients" table="Project_Client">
       <key column="projectid"/>
       <many-to-many class="Organization" unique="true" column="org_id"/>
      </set>
      <set name="technology" table="Project_Technology">
       <key column="projectid"/>
       <many-to-many class="Technology" unique="true" column="technologyid"/>
      </set>
      <set name="employer" table="Project_Employer">
       <key column="projectid"/>
       <many-to-many class="Employer" unique="true" column="employerid"/>
      </set>
    </class>
    

    希望这有帮助

答案 2 :(得分:1)

是的,你会这样做:

public Organization getOrCreateOrganization(String name) {
    Criteria crit = session.createCriteria(Organization.class);
    crit.add(Restrictions.eq("name", name));
    Organization result = (Organization)crit.uniqueResult();
    if (result == null) {
        result = new Organization();
        result.setName(name);
        session.save(result);
    }
    return result;
}