Hibernate父子关联

时间:2014-09-25 04:23:42

标签: java hibernate

正如标题所示,我在使用hibernate进行父子关联设计和执行基本CRUD操作时遇到了一些问题。我的方案如下:

POJO

User.java

public class User {
    private int uid;
    private String name;
    private String address;
    private String email;
    private int phone;

    // Getters and setters
}

ProUser.java

public class ProUser extends User{
    private String company;
    private String position;

    // Getters and Setters
}



TABLES:

用户

CREATE TABLE USER (
    UID INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
    NAME VARCHAR(20),
    ADDRESS VARCHAR(100),
    EMAIL VARCHAR(50),
    PHONE INT
)

PRO_USER

CREATE TABLE PRO_USER (
    UID INT NOT NULL PRIMARY KEY,
    COMPANY VARCHAR(20),
    POSITION VARCHAR(20),
    FOREIGN KEY (UID) REFERENCES USER (UID) ON DELETE CASCADE
)


现在,设计必须是这样的。无论是简单用户还是专业用户,用户表都会获取记录。当它是专业用户时,只需将附加数据存储在PRO_USER表中,将公共字段存储在USER表中。
在研究了一些hibernate方法之后,我使用了 table per subclass mapping strategy XML 。我能够INSERT记录,这很简单,好像我只保存一个用户对象,它只将它保存在USER表中,如果我保存一个prouser对象,那么它将保存在USER表和PRO_USER表中。

代码:
我没有提到 hibernate.cfg.xml 代码,这是每个hibernate应用程序的基础代码。对于这种情况,我只将 user.hbm.xml 映射为资源。

user.hbm.xml

<hibernate-mapping package="com.vsharma.entity">

<class name="User" table="USER">
    <id name="uid" column="UID">
        <generator class="increment" />
    </id>

    <property name="name" column="NAME" />
    <property name="address" column="ADDRESS" />
    <property name="email" column="EMAIL" />
    <property name="phone" column="PHONE" />

    <joined-subclass name="ProUser" extends="User">
            <key column="UID" />
            <property name="company" column="COMPANY" />
            <property name="position" column="POSITION" />
    </joined-subclass>
</class>
</hibernate-mapping>


MainApp.java     包com.vsharma;

import org.hibernate.*;
import org.hibernate.cfg.*;
import com.vsharma.entity.*;

public class MainApp {

public static void main(String[] args)
{
    Configuration cfg = new Configuration();
    cfg.configure("hibernate.cfg.xml");

    SessionFactory factory = cfg.buildSessionFactory();
    Session session = factory.openSession(); 

    User normal = new User();
         normal.setName("XXX");
         normal.setAddress("123 Street");
         normal.setEmail("blahblah@test.com");
         normal.setPhone(1234567890);

    ProUser pro = new ProUser();
         pro.setName("YYY");
         pro.setAddress("456 Street");
         pro.setEmail("problah@test.com");
         pro.setPhone(9876543210);
         pro.setCompany("ABC Tech");
         pro.setPosition("Testter");

    Transaction tx = session.beginTransaction();
    session.save(normal); // This saves only in USER Table
    session.save(pro);     // This saves in both USER and PRO_USER Table
    System.out.println("Object saved successfully.....!!");
    tx.commit();
    session.close();
    factory.close();
}


这用于插入的目的,但我不会混淆仅使用uid检索数据,也不会更新和删除。如何在java代码中执行SELECT,DELETE和UPDATE操作?我不知道传入的记录集是普通用户还是prouser。我用google搜索谷歌,我发现没有文章/帖子演示所有CRUD操作。可能是我用来满足要求的技术是不合适的,所以我请求这里的人找出我的问题,或者建议我可以达到目的的其他策略。
从字面上理解并提前表示感谢。

3 个答案:

答案 0 :(得分:1)

这是一个显示CRUD操作的简单示例:

- 选择

您可以使用HQLCriteria执行选择操作:

    Query query = session.createQuery("from User user where user.uid=:uid");
    query.setInteger("uid", 2);
    User user = (User) query.uniqueResult();
    System.out.println("User name before update = " + user.getName());

    // Here just check the type of object and do the explicit casting to access child properties.

    if(user instanceof ProUser){
        System.out.println(((ProUser) user).getCompany());
    }

现在显示基于以下查询的其他操作:

Query query = session.createQuery("from User user where user.uid=:uid");
query.setInteger("uid", 1);

- 更新

选择实体后,您可以调用session.update()方法来更新实体:

User user = (User) query.uniqueResult();
System.out.println("User name before update = " + user.getName());
user.setName("ZZZ");
session.update(user);

- 删除

您可以通过传递实体并从DB中删除记录来调用session.delete方法。

User user = (User) query.uniqueResult();
System.out.println("User name before delete = " + user.getName());
session.delete(user);

以下是一个示例程序:

private static void updateUser() {
    Session session = factory.openSession();
    Transaction tx = session.beginTransaction();
    Query query = session.createQuery("from User user where user.uid=:uid");
    query.setInteger("uid", 1);
    User user = (User) query.uniqueResult();
    System.out.println("User name before update = " + user.getName());
    user.setName("ZZZ");
    tx.commit();
    session.close();    
}

private static void deleteUser(Session session) {
    Session session = factory.openSession();
    Transaction tx = session.beginTransaction();
    Query query = session.createQuery("from User user where user.uid=:uid");
    query.setInteger("uid", 2);
    User user = (User) query.uniqueResult();
    System.out.println("User name before delete = " + user.getName());
    session.delete(user);
    tx.commit();
    session.close();    
}

根据您的计划,uid 2代表记录f PROUSER,因此数据将显示在表USER和&amp; PROUSER。因此,在我的示例中,如果您使用UID查询数据库为2,然后删除实体意味着您要告知hibernate从两个表中删除id为2的记录。

答案 1 :(得分:0)

使用以下示例代码进行CRUD操作

// for create

Contact contact1 = new Contact("Nam", "hainatuatgmail.com", "Vietnam", "0904277091");
session.persist(contact1);
Contact contact2 = new Contact("Bill", "billatgmail.com", "USA", "18001900");
Serializable id = session.save(contact2);
System.out.println("created id: " + id);


//for Read
Contact contact = (Contact) session.get(Contact.class, new Integer(2));
if (contact == null) {
    System.out.println("There is no Contact object with id=2");
} else {
    System.out.println("Contact3's name: " + contact.getName());
}



//To update a detached instance, call either the update() or saveOrUpdate() method, for example:

Contact contact = new Contact("Jobs", "jobsatapplet.com", "Cupertino", "0123456789");
session.update(contact);


//To delete an object with a given identifier, use the delete() method, for example:

Contact contactToDelete = new Contact();
contactToDelete.setId(4);
session.delete(contactToDelete);

答案 2 :(得分:0)

感谢您的回复,但当我尝试使用uid说2时,我又遇到了错误。 在你的程序

User user = (User) session.load(User.class, new Integer(2)); 

这会产生错误,因为hibernate知道它已插入的ProUser记录,但考虑到它在java代码端不知道哪种类型的对象即将到来,将其更改为

ProUser pro =  (ProUser) session.load(ProUser.class, new Integer(2));

这可能有用,但是如果我将uid 1传递给这个,那么hibernate uid 1再次是一个普通的用户记录....