Ary*_*rya 7 java postgresql hibernate
这是我第一次使用Hibernate,当我在一个循环中插入多行时,hibernate会为每一行插入以下内容
Hibernate: select nextval ('hibernate_sequence')
Run Code Online (Sandbox Code Playgroud)
在它为循环中的所有数据执行此操作后,它开始插入数据
Hibernate: insert into user_data (age, location, sent_count, user_id, username, id) values (?, ?, ?, ?, ?, ?)
Run Code Online (Sandbox Code Playgroud)
这是hibernate总是如何运作的?数据库是否无法处理序列?我觉得这真的会减慢插入行的过程.我正在使用PostgreSQL作为我的数据库.
这是我的相关代码user_data
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
我的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();
}
}
Run Code Online (Sandbox Code Playgroud)
以及插入行的相关部分
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();
Run Code Online (Sandbox Code Playgroud)
调用时session.save(),您尚未向数据库中插入任何内容。您只是将对象注册到会话缓存中,在该缓存中,Hibernate会跟踪最终将需要在数据库中插入/更新的所有对象。但是Hibernate立即需要的是新对象的标识符,因此它可以连接通过外键引用它的其他对象。
默认情况下,Hibernate将使用一个由本机DB序列支持的思想简单的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;
Run Code Online (Sandbox Code Playgroud)
以上内容必须保存在名为的文件中package-info.java。它所实现的是在名称下定义一个包范围的自定义ID生成器optimized-sequence。您可以像这样使用它:
@Id @GeneratedValue(generator = "optimized-sequence") public long id;
Run Code Online (Sandbox Code Playgroud)
这会给您带来的好处是一个本机序列支持的ID生成器,但是每生成50个(可配置的)对象,只需一次更改DB序列即可。它更改了基础序列的语义,例如,这currval = 1意味着当前的Hibernate会话为其本身保留了ID范围1-50。是的,这将在您的ID空间中造成“漏洞”,但是由于有2 64个漏洞,您不应该很快担心这一点。
Hed*_*ley -1
您的 id 设置为 @GenerateValue 但您尚未设置生成策略。看起来它默认是一个序列。我建议设置:
@GeneratedValue(strategy = GenerationType.IDENTITY)
Run Code Online (Sandbox Code Playgroud)
您需要有一个序列类型的列来充当您的 id 列。
| 归档时间: |
|
| 查看次数: |
7186 次 |
| 最近记录: |