Java 为什么hibernate对可存储对象运行删除和插入命令
我试图创建一个简单的示例来理解基本类型和可存储类型的集合在Hibernate中是如何工作的 我创建了一个Java 为什么hibernate对可存储对象运行删除和插入命令,java,hibernate,Java,Hibernate,我试图创建一个简单的示例来理解基本类型和可存储类型的集合在Hibernate中是如何工作的 我创建了一个用户实体,其中有一组昵称,还有一组地址。以下是我的Java类: User.java @Entity @Table(name = "TB_User") public class User { @Id @GeneratedValue private int id; private String name; @ElementCollection @Co
用户
实体,其中有一组昵称
,还有一组地址
。以下是我的Java类:
User.java
@Entity
@Table(name = "TB_User")
public class User {
@Id
@GeneratedValue
private int id;
private String name;
@ElementCollection
@CollectionTable(name = "Nicknames", joinColumns = @JoinColumn(name = "user_id"))
@Column(name = "nickname")
private Set<String> nickNames = new HashSet<String>();
@ElementCollection
@CollectionTable(name = "Addresses", joinColumns = @JoinColumn(name = "user_id"))
@AttributeOverrides({ @AttributeOverride(name = "street1", column = @Column(name = "fld_street")) })
public Set<Address> addresses = new HashSet<Address>();
public User() {
}
public User(String name, Address... addresses) {
this.name = name;
this.addresses.addAll(Arrays.asList(addresses));
}
public void addNickName(String... nickNames) {
this.nickNames.addAll(Arrays.asList(nickNames));
}
// Setters & Getters
}
@Embeddable
public class Address {
private String street1;
public Address() {}
public Address(String street1) {
this.street1 = street1;
}
@Override
public String toString() {
return street1;
}
// Setters & Getters
}
现在我已经创建了一个简单的程序来在数据库中创建用户,然后显示用户列表。这是我的密码:
private static void saveUsers() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.getTransaction().begin();
User user = new User("User", new Address("abc"),
new Address("xyz"));
user1.addNickName("alpha", "beta");
session.save(user);
session.getTransaction().commit();
}
private static void showUsers() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.getTransaction().begin();
List<User> users = session.createQuery("from User").list();
for (User user : users) {
System.out.println(user.getName() + " -- > " + user.getNickNames()
+ " --> " + user.getAddresses());
}
session.getTransaction().commit();
}
如果我尝试使用会话中的用户.getAddresses()
获取地址列表,则Hibernate会删除并重新插入地址表中的记录
为什么hibernate尝试删除并重新创建地址表中的记录,因为这会导致性能问题。另外,为什么它不适用于基本类型,如我的示例中的昵称
,以及不为属性昵称
运行更新命令?此行为与存在非双向映射这一事实有关。要深入了解这一点,请阅读本文:
下面是如何使用注释实现这一点的方法:
让我从答案中引述:
我找到了答案。@OneToMany
注释的mappedBy
属性在xml文件中的行为与inverse=true相同
一些总结:
Hibernate可以发出我们期望的SQL语句。但只有在双向映射到位的情况下
然后,另一端(地址)将驱动持久性。它将/必须了解它的父级-这就是为什么可以发布一些直接更新语句的原因
因此,如果我们想避免删除和插入,我们必须使用逆映射。Hibernate将发布更多“可预期”的SQL 这一个很老,但可能与躯体有关。另一个帮助我的例子:如果你可以把读和写分开,考虑使用< /P>
@Transactional(readOnly = true)
这使得底层JPA框架知道当前事务中不需要修改。实际上,当您只想获取一些数据时,Hibernate不再运行delete
+insert
。因为我使用地址作为@embeddeble
我想我不能使用@OneToMany/@manytone
。因此,这意味着hibernate无法使用update
命令,因为Address
没有任何标识符,因此它正在删除和重新插入记录。我的理解正确吗?这意味着如果我们想使用可嵌入的集合,就无法控制生成的SQL。你完全明白了。优化此处生成的SQL的唯一方法是双向映射。如果这是@embeddeble。。。没有办法确定。(如果我们仔细想想,这是合乎逻辑的)。。。对不起,我没有“答案”。。。但希望能有所帮助;)
@Transactional(readOnly = true)