今天我做了一些关于hibernate的实验。 首先,我的计划背后没有更深层次的意义。我只想尝试框架。 我计划了以下数据库表:
具有以下双向映射:
在准备单个课程后,我写了我的工作人员插入一些demodata。到目前为止,一切都按预期工作。 最后我想删除我的一个司机。但是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]] 线程“main”中的异常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) at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:146) at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access $ 100(JdbcResourceLocalTransactionCoordinatorImpl.java:38) at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl $ TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:220) 在org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:68) at mycode.Worker.work(Worker.java:133) 在mycode.Worker.main(Worker.java:19)
答案 0 :(得分:1)
首先,希望您知道alter
是保留字alter table <table_name>;
,因此您必须更改Fahrer类中的列名:
@Column(name = "_alter") // choose any name you want
private int alter;
之后,为什么需要这么多的双向关系?看,你有:
class Fahrer {
// ...
@ManyToOne(cascade = CascadeType.ALL)
private Auto auto;
这意味着,当您删除fahrer时,会删除自动。这真的是你想要的吗?
现在看看你的代码:
// 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值的实体几次是不合适的。
答案 1 :(得分:0)
您的例外说明:从关联中删除已删除的对象
仅仅从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();
。你得到自动,但变量叫做car ...
不推荐使用PostgreSQLDialect,在你的hibernate配置中选择PostgreSQL9Dialect或其他内容;
auto
是保留名称,最好使用其他名称。答案 2 :(得分:0)
感谢Oles, 我将代码更新为
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中删除,因为它以concurrentmodificationexception结束。使用此处发布的代码,没有其他例外。调试视图向我显示,在最后一个循环之后,其中一辆车没有剩下的驱动程序。特别是id为2的驱动程序将从驱动程序列表中删除。不幸的是,驱动程序仍然在数据库中如果我正确理解了最后一个答案,情况应该不是这样的。