【问题标题】:Java Hibernate delete ObjectJava Hibernate 删除对象
【发布时间】:2018-01-28 20:20:15
【问题描述】:

今天我用hibernate做了一些实验。 首先,我的程序背后没有更深层次的意义。我只是想试试这个框架。 我计划了以下数据库表:

  • 汽车(汽车)
  • 司机(Fahrer)
  • Wohnung(平)
  • 客人(法尔加斯特)

具有以下双向映射:

  • 司机 - 单人驾驶
  • 司机 - 单车
  • 汽车 - 客人多头

在准备好单个类之后,我写了我的工人来插入一些演示数据。到目前为止,一切都按预期工作。 最后,我想删除我的一个驱动程序。但是hibernate告诉我,它会被某个客人重新保存。不幸的是,我不明白为什么。 从相应汽车的驱动程序集合中删除驱动程序后,我预计一切都会好起来的。

类车

package mycode;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name="auto")
public class Auto {

@Id @GeneratedValue
private int id;
@Column(name="nummernschild", nullable = false)
private String nummernschild;
@OneToMany(cascade=CascadeType.ALL, mappedBy="auto")
private List<Fahrer>fahrers = new ArrayList<Fahrer>();
@ManyToMany(cascade=CascadeType.ALL)
private List<Fahrgast>fahrgasts = new ArrayList<Fahrgast>();

public List<Fahrgast> getFahrgasts() {
    return fahrgasts;
}
public void setFahrgasts(List<Fahrgast> fahrgasts) {
    this.fahrgasts = fahrgasts;
}
public List<Fahrer> getFahrers() {
    return fahrers;
}
public void setFahrers(List<Fahrer> fahrers) {
    this.fahrers = fahrers;
}
private LocalDate kaufdatum;
public LocalDate getKaufdatum() {
    return kaufdatum;
}
public void setKaufdatum(LocalDate kaufdatum) {
    this.kaufdatum = kaufdatum;
}
public int getId() {
    return id;
}
public void setId(int id) {
    this.id = id;
}
public String getNummernschild() {
    return nummernschild;
}
public void setNummernschild(String nummernschild) {
    this.nummernschild = nummernschild;
}

}

类驱动

package mycode;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity
@Table(name="fahrer")
public class Fahrer {
@Id @GeneratedValue()
private int id;
private String vorname, nachname;
private int alter;

@OneToOne (cascade=CascadeType.ALL)
@JoinColumn(name="id")
private Wohnung wohnung;
@ManyToOne(cascade=CascadeType.ALL)
private Auto auto;


public Auto getAuto() {
    return auto;
}
public void setAuto(Auto auto) {
    this.auto = auto;
}
public Wohnung getWohnung() {
    return wohnung;
}
public void setWohnung(Wohnung wohnung) {
    this.wohnung = wohnung;
}

public int getId() {
    return id;
}
public void setId(int id) {
    this.id = id;
}
public String getVorname() {
    return vorname;
}
public void setVorname(String vorname) {
    this.vorname = vorname;
}
public String getNachname() {
    return nachname;
}
public void setNachname(String nachname) {
    this.nachname = nachname;
}
public int getAlter() {
    return alter;
}
public void setAlter(int alter) {
    this.alter = alter;
}

}

班级公寓

package mycode;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;

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

@Entity
@Table(name="wohnung")
public class Wohnung {
    @Id @GeneratedValue(generator = "newGenerator")
    @GenericGenerator(name="newGenerator", strategy="foreign" , parameters= {@Parameter(value="fahrer", name="property")})
private int id; 
@Column(nullable=false)
private String ort, straße;
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="id")
private Fahrer fahrer;
public int getId() {
    return id;
}
public void setId(int id) {
    this.id = id;
}
public String getOrt() {
    return ort;
}
public void setOrt(String ort) {
    this.ort = ort;
}
public String getStraße() {
    return straße;
}
public void setStraße(String straße) {
    this.straße = straße;
}
public Fahrer getFahrer() {
    return fahrer;
}
public void setFahrer(Fahrer fahrer) {
    this.fahrer = fahrer;
}


}

班级嘉宾

package mycode;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

@Entity
@Table(name="fahrgast")
public class Fahrgast {
@Id @GeneratedValue
private int id;
@Column(nullable=false)
private int kundennummmer;
private String vornname, nachname;
@ManyToMany(mappedBy="fahrgasts")
private List<Auto>autos = new ArrayList<Auto>();

public List<Auto> getAutos() {
    return autos;
}
public void setAutos(List<Auto> autos) {
    this.autos = autos;
}
public int getId() {
    return id;
}
public void setId(int id) {
    this.id = id;
}
public int getKundennummmer() {
    return kundennummmer;
}
public void setKundennummmer(int kundennummmer) {
    this.kundennummmer = kundennummmer;
}
public String getVornname() {
    return vornname;
}
public void setVornname(String vornname) {
    this.vornname = vornname;
}
public String getNachname() {
    return nachname;
}
public void setNachname(String nachname) {
    this.nachname = nachname;
}


}

工人阶级

package mycode;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;

public class Worker {

    private Session session;
    private SessionFactory sf;
    public static void main(String[] args) {

        Worker worker = new Worker();
        worker.work();
    }

    private void init()
    {
        Configuration configuration = new Configuration().configure();

        sf = configuration.buildSessionFactory();
        session = sf.openSession();

    }

    private void work()
    {
        init();
        Auto auto = new Auto(); 
        auto.setNummernschild("HH:MK:"+1);
        LocalDate ld = LocalDate.now();
        auto.setKaufdatum(ld);

        session.beginTransaction();
        for (int i=0; i<10; i++)
        {


            auto = new Auto();
            auto.setNummernschild("HH:MK:"+i);
            ld = LocalDate.now();
            auto.setKaufdatum(ld);

            Auto auto2 = new Auto();

            auto2.setNummernschild("HH:MK:"+i);
            ld = LocalDate.now();
            auto2.setKaufdatum(ld);

            //auto.setId(i);

            Fahrer fahrer = new Fahrer(); 
            fahrer.setVorname("Hans");
            fahrer.setNachname("Huber");
            Fahrer fahrer2 = new Fahrer(); 
            fahrer2.setVorname("Anna");
            fahrer2.setNachname("Schmidt");
            double temp = Math.random();
            int alter = (int)(temp*50);
            fahrer.setAlter(alter);

            fahrer2.setAlter(alter);

            fahrer.setAuto(auto);
            fahrer2.setAuto(auto2);
            Wohnung wohnung = createWohnung(i);
            wohnung.setFahrer(fahrer);
            fahrer.setWohnung(wohnung);
            Wohnung wohnung2 = createWohnung(i*10);
            fahrer2.setWohnung(wohnung2);
            wohnung2.setFahrer(fahrer2);
            auto.getFahrers().add(fahrer);
            auto2.getFahrers().add(fahrer2);

            double zufall = Math.random()*100;
            int zu = (int)zufall;
            for (int z=0; z<zu; z++)
            {
                Fahrgast fahrgast = new Fahrgast(); 
                fahrgast.setVornname("Hans"+z);
                fahrgast.setNachname("Dampf"+z);
                double kundennummer = Math.random()*10000;
                fahrgast.setKundennummmer((int)kundennummer);
                fahrgast.getAutos().add(auto);
                fahrgast.getAutos().add(auto2);
                auto.getFahrgasts().add(fahrgast);
                auto2.getFahrgasts().add(fahrgast);

            }
//          session.save(fahrer);
//          session.save(fahrer2);
            session.save(auto);
            session.save(auto2);

        }

        Fahrer abfrage = session.get(Fahrer.class, 2);
        List<Fahrer>fahrers = session.createCriteria(Fahrer.class).list();
        List<Fahrer>tobedeletet = new ArrayList<Fahrer>();
        for (Fahrer aktuell : fahrers)
        {
            Auto car = aktuell.getAuto();
            List<Fahrer>cardriver = car.getFahrers();
            Fahrer temp = null;
            for (Fahrer driver: cardriver)
            {
                if (driver.getId()==abfrage.getId())
                {
                    tobedeletet.add(aktuell);
                    temp = driver;

                }
            }
            cardriver.remove(temp);
            session.update(car);
        }


        for (Fahrer aktuell : tobedeletet)
        {
            session.remove(aktuell);
        }


        System.out.println(abfrage.getVorname()+ " "+abfrage.getNachname());


        session.getTransaction().commit();
        session.close();
        sf.close();

    }

    private Wohnung createWohnung(int i)
    {
        Wohnung wohnung = new Wohnung(); 
        wohnung.setOrt("bla"+i);
        wohnung.setStraße("blub"+i);
        return wohnung;
    }

}

终于有了配置文件

<?xml version='1.0' encoding='utf-8'?>
<hibernate-configuration>
<session-factory>
    <!-- Database connection settings -->
    <property 
     name="connection.driver_class">org.postgresql.Driver</property>
    <property name="connection.url">jdbc:postgresql://192.168.2.252:5432/test</property>
    <property name="connection.username">postgres</property>
    <property name="connection.password">postgres</property>

    <!-- JDBC connection pool (use the built-in) -->
    <property name="connection.pool_size">1</property>

    <!-- SQL dialect -->
    <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>

    <!-- Enable Hibernate's automatic session context management -->
    <property name="current_session_context_class">thread</property>

    <!-- Disable the second-level cache  -->
    <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>

    <!-- Echo all executed SQL to stdout -->
    <property name="show_sql">true</property>

    <!-- Drop and re-create the database schema on startup -->
    <property name="hbm2ddl.auto">create</property>
    <mapping class="mycode.Auto"/>
    <mapping class="mycode.Fahrer"/>
    <mapping class="mycode.Wohnung"/>
    <mapping class="mycode.Fahrgast"/>
</session-factory>

谁能告诉我,如何删除我的一个驱动程序?

错误信息: 错误:HHH000346:托管刷新期间出错[删除的对象将由级联重新保存(从关联中删除已删除的对象):[mycode.Fahrgast#3]] 线程“主”javax.persistence.EntityNotFoundException 中的异常:已删除的对象将由级联重新保存(从关联中删除已删除的对象):[mycode.Fahrgast#3] 在 org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:126) 在 org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155) 在 org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:162) 在 org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1441) 在 org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:491) 在 org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3201) 在 org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2411) 在 org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:467) 在 org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:146) 在 org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access $100(JdbcResourceLocalTransactionCoordinatorImpl.java:38) 在 org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:220) 在 org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:68) 在 mycode.Worker.work(Worker.java:133) 在 mycode.Worker.main(Worker.java:19)

【问题讨论】:

  • 你能发布错误信息吗?
  • 添加了错误信息

标签: java hibernate


【解决方案1】:

您的例外是:从关联中删除已删除的对象

只需从 Auto#fahrers 集合中删除 fahrer 并更新 auto 就足够了:

auto.getFahrers().remove(fahrer);
// remove other fahrers
session.update(auto);

因为您在 Auto 类中的 auto-to-fahrers 关系上有一个 cascade=CascadeType.ALL 属性,所以在更新 Auto 后,Fahrer 应该会被自动删除。

更多信息:https://stackoverflow.com/a/11649941/6521788

还有几件事需要注意:

  • ,在您的代码中使用一种语言 :)。 Auto car = aktuell.getAuto();。你得到了汽车,但变量被称为汽车......

  • PostgreSQLDialect 已弃用,请在您的休眠配置中选择 PostgreSQL9Dialect 或其他;

  • auto 是保留名称,最好使用其他名称。

【讨论】:

    【解决方案2】:

    感谢奥莱斯, 我将代码更新为

    List<Auto>autos = session.createCriteria(Auto.class).list();
            List<Auto>toBeUpdated = new ArrayList<Auto>();
            for (Auto fahzeug : autos)
            {
                List<Fahrer>fahrers2 = fahzeug.getFahrers();
                for (Fahrer aktuell : fahrers2)
                {
                    if (aktuell.getId()==abfrage.getId())
                    {
                        toBeUpdated.add(fahzeug);
                    }
                }
    
            }
            for (Auto fahrzeug : toBeUpdated)
            {
                fahrzeug.getFahrers().remove(abfrage);
                System.out.println("removed");
                session.update(fahrzeug);
            }
    

    不幸的是,仍然有些事情没有按预期工作。我不能在 fahrerloop 中执行删除操作,因为它以并发修改异常结束。使用此处发布的代码,没有进一步的例外。调试视图向我显示,在最后一个循环之后,其中一辆车没有司机了。尤其是 ID 为 2 的驱动程序会从驱动程序列表中删除。不幸的是,驱动程序仍保留在数据库中。如果我正确理解了最后一个答案,那不应该是这种情况。

    【讨论】:

      【解决方案3】:

      首先,希望你知道alter是保留字alter table &lt;table_name&gt;;,所以你必须在Fahrer类中改变你的列名:

      @Column(name = "_alter") // choose any name you want
      private int alter;
      

      在那之后,为什么需要这么多双向关系?看,你有:

      class Fahrer {
          // ...
          @ManyToOne(cascade = CascadeType.ALL)
          private Auto auto;
      

      这意味着,当您删除一个 fahrer 时,该 auto 将被删除。这真的是你想要的吗?

      现在看看你的代码:

      // at first you check if the ID is equal to abfrage and add it to list
      if (driver.getId() == abfrage.getId()) {
          tobedeletet.add(aktuell);
          temp = driver;
      }
      
      // at the end you formed a list tobedeleted witch contains elements with the same ID.
      
      for (Fahrer aktuell : tobedeletet) {
          session.remove(aktuell);
      }
      

      说实话,我是一个java初学者,所以我可能会错过一些东西。但是多次删除具有相同 ID 值的实体可能是没有必要的。

      【讨论】:

      • 解决了这个问题。 fahrer 和 auto 之间的 CascadeType 是问题所在。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-22
      • 1970-01-01
      • 2012-12-29
      • 2016-04-11
      • 2012-09-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多