【问题标题】:Why hibernate session save update row instead of insert row?为什么休眠会话保存更新行而不是插入行?
【发布时间】:2018-06-10 05:30:15
【问题描述】:

我在 windows7x64 上安装了 Postgres 10.1 版。我有一个数据库“postgres”,其中有一个表“dbuser”和列“user_id”和“username”。我正在使用 Intelij 和 Maven。我正在使用休眠中的 Session 来尝试将一行插入到表中。

App.java

package com.hibernateTest;

import org.hibernate.Session;

public class App {
    public static void main(String[] args) {
        Session session = HibernateUtil.getSessionFactory().openSession();
    session.beginTransaction();
    dbuser dbuser = new dbuser();
    dbuser.setUser_id(556);
    dbuser.setUsername("waaagr");       
    session.save(dbuser);
    //session.merge(dbuser);//my mistake---old code
    session.getTransaction().commit();
    }
}

HibernateUtil.java

package com.hibernateTest;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {

    private static final SessionFactory sessionFactory = buildSessionFactory();

    private static SessionFactory buildSessionFactory() {
        try {
            return new Configuration().configure().buildSessionFactory();
        } catch (Throwable ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public static void shutdown() {
        getSessionFactory().close();
    }

}

dbuser.java:

    package com.hibernateTest;

import javax.persistence.*;

@Entity
@Table(name = "dbuser")
public class dbuser implements java.io.Serializable {

    @Id
    //@GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name = "user_id")
    private long user_id;

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


    public dbuser() {
    }

    public dbuser(long user_id, String username) {
        this.user_id = user_id;
        this.username = username;
    }

    @Column(name = "username")
    public String getUsername() {
        return this.username;
    }

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

    @Column(name = "user_id")
    public long getUser_id() {
        return user_id;
    }

    public void setUser_id(long user_id) {
        this.user_id = user_id;
    }
}

Hibernate.cfg.xml

<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>
        <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
        <property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
        <property name="hibernate.connection.username">postgres</property>
        <property name="hibernate.connection.password">password</property>
        <property name="hibernate.connection.url">jdbc:postgresql://localhost:5432/mydb</property>
        <property name="connection_pool_size">1</property>
        <property name="hbm2ddl.auto">create</property>
        <property name="show_sql">true</property>
        <mapping class="com.hibernateTest.User"/>
    </session-factory>
</hibernate-configuration>

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.mkyong.common</groupId>
    <artifactId>HibernateExample</artifactId>
    <packaging>jar</packaging>
    <version>1.0</version>
    <name>HibernateExample</name>
    <url>http://maven.apache.org</url>
    <repositories>
        <repository>
            <id>JBoss repository</id>
            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
        </repository>
    </repositories>
    <dependencies>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>9.4-1203-jdbc4</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>3.6.3.Final</version>
        </dependency>
        <dependency>
            <groupId>javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.12.1.GA</version>
        </dependency>
    </dependencies>
</project>

问题是当我运行我的应用程序时,我得到了:

Hibernate: select dbuser0_.user_id as user1_0_0_, dbuser0_.username as username0_0_ from dbuser dbuser0_ where dbuser0_.user_id=?
Hibernate: insert into dbuser (username, user_id) values (?, ?)

首先奇怪的是终端中有 (?, ?) 的值。而数据库中表中的数据只是更新,但我想插入新行而不更新行? 我不知道为什么这段代码更新一行而不是插入一个新行,一个新行? 非常感谢。

【问题讨论】:

  • 您提供的日志(可读性差)似乎指定了INSERT 语句,而不是UPDATE。那你为什么要不然呢? ? 是值的占位符。
  • “保存”是 INSERT 的同义词。
  • @Kayman “您提供的日志(以一种可读性差的形式)”-> 已更正(谢谢)。 duffymo 是的,我知道这就是为什么我要问它为什么当在这个表上进行选择时我看到该行是更新而不是新行。
  • dbuser.setUser_id(556); 这将使休眠状态以更新键为 556 的行。如果您不想插入新行,请将其删除。

标签: java postgresql hibernate maven java-ee-7


【解决方案1】:
dbuser dbuser = new dbuser();
dbuser.setUser_id(556);
dbuser.setUsername("waaagr");       
session.merge(dbuser);

所以你在这里所做的就是告诉休眠状态,数据库中可能存在一些 id=556 的用户,并且你想将你的更改合并到数据库中。这就是所谓的分离实体。

合并所做的是通过提供的 id 获取给定的实体(因此 SELECT),检查数据库中的数据和您的对象中的数据之间是否存在一些差异,并在“脏字段”上提交 UPDATE 操作。同时,merge 会返回 ma​​naged 实体。这就是 merge 根据 JPA 规范的一般工作方式。

在您的情况下,您谎称休眠该实体已经存在,但休眠知道这一点(因为 ID 获取的结果集为空)并且它执行 INSERT 而不是 UPDATE

总结一下:通过提供 ID,您表明给定实体应该已经存在于数据库中并且可以合并。如果您想创建新用户(即使给定 id),请使用 save 代替 merge

【讨论】:

  • 非常感谢,我附上了合并代码是我的错。我尝试使用“保存”而不是“合并”,但结果是一样的,我不知道为什么?也许我在配置中有一些错误。
  • 代码大同小异。而不是“session.merge(dbuser);”我有“session.save(dbuser);”。
  • 从实体中删除 id ,它将保存为新的而不选择。
  • 当我删除 id 时,我在终端“没有为实体指定标识符:com.hibernateTest.dbuser”得到一个通信
  • @user2856064 使用 persist isteed of save - 没有 ID ofc。
猜你喜欢
  • 2011-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-24
  • 2017-12-28
相关资源
最近更新 更多