正如标题所示,我在使用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操作。可能是我用来满足要求的技术是不合适的,所以我请求这里的人找出我的问题,或者建议我可以达到目的的其他策略。
从字面上理解并提前表示感谢。
答案 0 :(得分:1)
这是一个显示CRUD操作的简单示例:
您可以使用HQL
或Criteria
执行选择操作:
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
再次是一个普通的用户记录....