gpt4 book ai didi

java - 为使用 hibernate 插入的每一行选择 nextval

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:17:21 26 4
gpt4 key购买 nike

这是我第一次使用 Hibernate,当我在循环中插入多行时,hibernate 会为插入的每一行打印出以下内容

Hibernate: select nextval ('hibernate_sequence')

在它对循环中的所有数据执行此操作后,它开始插入数据

Hibernate: insert into user_data (age, location, sent_count, user_id, username, id) values (?, ?, ?, ?, ?, ?)

hibernate 总是这样运作的吗?数据库不可能处理序列吗?我觉得这确实减慢了插入行的过程。我正在为我的数据库使用 PostgreSQL。

这是我的相关代码用户数据

@Entity
@Table(name = "user_data")
public class UserData
{
@Id @GeneratedValue
@Column(name = "id")
private int id;

@Column(name = "user_id")
private String userid;

@Column(name = "username")
private String username;

@Column(name = "age")
private int age;

@Column(name = "location")
private int location;

@Column(name = "sent_count")
private int sentCount;

public int getId()
{
return id;
}

public void setId(int id)
{
this.id = id;
}

public String getUserid()
{
return userid;
}

public void setUserid(String userid)
{
this.userid = userid;
}

public String getUsername()
{
return username;
}

public void setUsername(String username)
{
this.username = username;
}

public int getAge()
{
return age;
}

public void setAge(int age)
{
this.age = age;
}

public int getLocation()
{
return location;
}

public void setLocation(int location)
{
this.location = location;
}

public int getSentCount()
{
return sentCount;
}

public void setSentCount(int sentCount)
{
this.sentCount = sentCount;
}
}

我的 Hibernate 助手类

public class HibernateUtil
{
static SessionFactory sessionFactory;
static ServiceRegistry serviceRegistry;

static
{
try
{
Configuration configuration = new Configuration();
configuration.setProperty("hibernate.temp.use_jdbc_metadata_defaults", "false");
configuration.configure();
serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
}
catch (Throwable ex)
{
// Make sure you log the exception, as it might be swallowed
System.err.println("Initial SessionFactory creation failed." + ex);
closeSessionFactory();
throw new ExceptionInInitializerError(ex);
}
}

public static SessionFactory getSessionFactory()
{
return sessionFactory;
}

public static void closeSessionFactory()
{
sessionFactory.close();
}

}

和插入行的相关部分

    Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();

for (String memberId : memberIds)
{
System.out.println(memberId);
UserData user = new UserData();
user.setUserid(memberId);
session.save(user);
}

session.getTransaction().commit();
session.close();
HibernateUtil.closeSessionFactory();

最佳答案

当您调用 session.save() 时,您还没有向数据库中插入任何内容。您只是将对象注册到 session 缓存,Hibernate 会在其中跟踪最终需要在数据库中插入/更新的所有对象。但是 Hibernate 立即需要的是新对象的标识符,因此它可以连接通过外键引用它的其他对象。

默认情况下,Hibernate 将使用一个由本地数据库序列支持的简单的 ID 生成器,从该序列中为每个保存的对象获取一个 ID。只要您不进行批量插入(在同一事务中插入很多东西),这就可以正常工作。不过,您的 for 循环确实使它看起来就像您正在做的那样。

如果您在执行批量插入时需要良好的性能,则需要处理一些问题(四处搜索),但在这里我将针对您的紧迫问题提供解决方案:优化序列生成器。这是我使用的:

@GenericGenerator(name = "optimized-sequence", strategy = "enhanced-sequence", parameters = {
@Parameter(name = "prefer_sequence_per_entity", value = "true"),
@Parameter(name = "optimizer", value = "hilo"),
@Parameter(name = "increment_size", value = "50") })
package org.example.myproject;

import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;

以上内容必须保存在名为package-info.java 的文件中。它实现的是在名称 optimized-sequence 下定义一个包范围的自定义 ID 生成器。你可以像这样使用它:

@Id @GeneratedValue(generator = "optimized-sequence") public long id;

这将为您购买一个本地序列支持的 ID 生成器,但它只需要为每 50 个(可配置的)保存对象碰撞数据库序列一次。它改变了底层序列的语义,例如,currval = 1 表示当前 Hibernate session 为自己保留了 ID 范围 1-50。是的,这会在您的 ID 空间中产生“漏洞”,但是由于要绕过 264,您不应该很快开始担心这个问题。

关于java - 为使用 hibernate 插入的每一行选择 nextval,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26982990/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com