gpt4 book ai didi

java - 如何在 hibernate 状态下规范化数据库? (重复值不会一次又一次保存)

转载 作者:行者123 更新时间:2023-12-02 07:02:55 24 4
gpt4 key购买 nike

假设我有一个名为 Photo 的表和一个名为 Tag 的表。

一张照片可以有任意数量的标签。就像柏林勃兰登堡门的照片有标签“柏林”、“门”...

现在有第二张与柏林国会大厦的照片,并且标签之一也是“柏林”。

目前,这将被冗余地保存在我的数据库中,这意味着在我的标签表中“Berlin”出现两次,并且在我的由 hibernate 创建的连接表中,每个元组都指向其自己的“Berlin”标签。

我不喜欢这种情况,因为这意味着我在数据库中保存了冗余数据。我更希望标签“Berlin”在我的标签表中仅保存一次,并且具有此标签的每张照片都会获得此标签对象的引用。

总结一下:

之前(我希望现在当我发送此问题时可以正确显示)

照片

ID |照片名称
1 |勃兰登堡门
2 |德国国会大厦...| ...

标签

ID |标签名1 |柏林2 |仓鼠3 |柏林4 |柏林5 |鸟...| ...

PHOTO_TAG(连接表格)

照片ID |标签ID1 | 12 | 33 | 4... | ...

希望之后:

照片

ID |照片名称
1 |勃兰登堡门
2 |德国国会大厦...| ...

标签

ID |标签名1 |柏林2 |仓鼠3 |鸟...| ...

PHOTO_TAG(连接表格)照片ID |标签ID1 | 12 | 13 | 1... | ...

正如您所看到的,Berlin 只需要在 Tag 表中保存一次,而仍然没有信息丢失,因为连接表在元组上引用是正确的。

我尝试在 postgresql 数据库上使用 hibernate(我不是专业人士)来实现这一点。我的照片类有一个属性 photoTags,我给了它一个 ManyToMany 关系(我认为这可能意味着每张照片可以有任意数量的标签,而每个标签可以有它们引用的任意数量的照片)

@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<Tag> photoTags;

但简单地说,这不起作用。我的标签表中有很多冗余数据。A现在我的问题是:你知道有什么足够的方法让我实现这一点吗?感谢您的每一个回答和评论(如果您需要任何进一步的信息,例如我的 hibernate.cfg.xml,请告诉我)。

(这里的这个问题正在处理类似的问题,但答案并不令我满意: Normalize repeating values in Hibernate - Java )

编辑:我现在附加我的 hibernate 类:

User.java

import java.util.Date;
import java.util.Set;

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

@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue
private Long id;

@Column(unique = true)
private String userID;
private String userName;
private String userRealName;
private int userPhotoCount;
private Date userPhotoF;
private Date userPhot_1;
private String userLocation;
private String userThumbnailURL;
private int userIsPro;
private int userIsAdmin;
private int userContact;
private int userPhotoS;

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<Photo> photos;

public User(String userID, String userName, String userRealName, int userPhotoCount,
Date userPhotoF, Date userPhot_1, String userLocation,
String userThumbnailURL, int userIsPro, int userIsAdmin,
int userContact, int userPhotoS, Set<Photo> photos) {
this.userID = userID;
this.userName = userName;
this.userRealName = userRealName;
this.userPhotoCount = userPhotoCount;
this.userPhotoF = userPhotoF;
this.userPhot_1 = userPhot_1;
this.userLocation = userLocation;
this.userThumbnailURL = userThumbnailURL;
this.userIsPro = userIsPro;
this.userIsAdmin = userIsAdmin;
this.userContact = userContact;
this.userPhotoS = userPhotoS;
this.photos = photos;

}

// Hibernate requirement
public User() {
}

public Long getId() {
return id;
}

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

public String getUserID() {
return userID;
}

public void setUserID(String userID) {
this.userID = userID;
}

public String getUserRealName() {
return userRealName;
}

public void setUserRealName(String userRealName) {
this.userRealName = userRealName;
}

public int getUserPhotoCount() {
return userPhotoCount;
}

public void setUserPhotoCount(int userPhotoCount) {
this.userPhotoCount = userPhotoCount;
}

public Date getUserPhotoF() {
return userPhotoF;
}

public void setUserPhotoF(Date userPhotoF) {
this.userPhotoF = userPhotoF;
}

public Date getUserPhot_1() {
return userPhot_1;
}

public void setUserPhot_1(Date userPhot_1) {
this.userPhot_1 = userPhot_1;
}

public String getUserLocation() {
return userLocation;
}

public void setUserLocation(String userLocation) {
this.userLocation = userLocation;
}

public String getUserThumbnailURL() {
return userThumbnailURL;
}

public void setUserThumbnailURL(String userThumbnailURL) {
this.userThumbnailURL = userThumbnailURL;
}

public int getUserIsPro() {
return userIsPro;
}

public void setUserIsPro(int userIsPro) {
this.userIsPro = userIsPro;
}

public int getUserIsAdmin() {
return userIsAdmin;
}

public void setUserIsAdmin(int userIsAdmin) {
this.userIsAdmin = userIsAdmin;
}

public int getUserContact() {
return userContact;
}

public void setUserContact(int userContact) {
this.userContact = userContact;
}

public int getUserPhotoS() {
return userPhotoS;
}

public void setUserPhotoS(int userPhotoS) {
this.userPhotoS = userPhotoS;
}

public Set<Photo> getUserPhotos() {
return photos;
}

public void setUserPhotos(Set<Photo> userPhotos) {
this.photos = userPhotos;
}

public void addPhoto(Photo photo){
this.photos.add(photo);
}

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}

}

Photo.java

import java.util.Date;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;

@Entity
public class Photo {

@Id
@GeneratedValue
private Long id;

private Long photoID;
private String photoTitle;
private String photoUrl;
private int photoAccur;

@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<Tag> photoTags;

private int photoTagsCount;
// ist das korrekt?
private int photoCommentCount;
// date objekte
private Date photoDateP;
private Date photoDateT;
private String photoDescription;
// korrekter Name?
private String photoNotes;
private int photoNot_1;
private String photoMedia;
private String photoMed_1;
private int photoLicense;
private int photoIsFam;
private int photoIsFri;
private int photoIsPri;
// x-Achse
private float photoLongitude;
// y-Achse
private float photoLatitude;

public Photo(Long photoID, String photoTitle, String photoURL,
int photoAccur, Set<Tag> photoTags, int photoTagsCount,
int photoCommentCount, Date photoDateP, Date photoDateT,
String photoDescription, String photoNotesCount, int photoNot_1,
String photoMedia, String photoMed_1, int photoLicense,
int photoIsFam, int photoIsFri, int photoIsPri, float photoLongi,
float photoLatit) {
this.photoID = photoID;
this.photoTitle = photoTitle;
this.photoUrl = photoURL;
this.photoAccur = photoAccur;
this.photoTags = photoTags;
this.photoTagsCount = photoTagsCount;
this.photoCommentCount = photoCommentCount;
this.photoDateP = photoDateP;
this.photoDateT = photoDateT;
this.photoDescription = photoDescription;
this.photoNotes = photoNotesCount;
this.photoNot_1 = photoNot_1;
this.photoMedia = photoMedia;
this.photoMed_1 = photoMed_1;
this.photoLicense = photoLicense;
this.photoIsFam = photoIsFam;
this.photoIsFri = photoIsFri;
this.photoIsPri = photoIsPri;
this.photoLongitude = photoLongi;
this.photoLatitude = photoLatit;
}

// hibernate
public Photo() {
}

public Long getId() {
return id;
}

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

public Long getPhotoID() {
return photoID;
}

public void setPhotoID(Long photoID) {
this.photoID = photoID;
}

public String getPhotoTitle() {
return photoTitle;
}

public void setPhotoTitle(String photoTitle) {
this.photoTitle = photoTitle;
}

public String getPhotoUrl() {
return photoUrl;
}

public void setPhotoUrl(String photoUrl) {
this.photoUrl = photoUrl;
}

public int getPhotoAccur() {
return photoAccur;
}

public void setPhotoAccur(int photoAccur) {
this.photoAccur = photoAccur;
}

public Set<Tag> getPhotoTags() {
return photoTags;
}

public void setPhotoTags(Set<Tag> photoTags) {
this.photoTags = photoTags;
}

public int getPhotoTagsCount() {
return photoTagsCount;
}

public void setPhotoTagsCount(int photoTagsCount) {
this.photoTagsCount = photoTagsCount;
}

public int getPhotoCommentCount() {
return photoCommentCount;
}

public void setPhotoCommentCount(int photoCommentCount) {
this.photoCommentCount = photoCommentCount;
}

public Date getPhotoDateP() {
return photoDateP;
}

public void setPhotoDateP(Date photoDateP) {
this.photoDateP = photoDateP;
}

public Date getPhotoDateT() {
return photoDateT;
}

public void setPhotoDateT(Date photoDateT) {
this.photoDateT = photoDateT;
}

public String getPhotoDescription() {
return photoDescription;
}

public void setPhotoDescription(String photoDescription) {
this.photoDescription = photoDescription;
}

public String getPhotoNotesCount() {
return photoNotes;
}

public void setPhotoNotesCount(String photoNotesCount) {
this.photoNotes = photoNotesCount;
}

public int getPhotoNot_1() {
return photoNot_1;
}

public void setPhotoNot_1(int photoNot_1) {
this.photoNot_1 = photoNot_1;
}

public String getPhotoMedia() {
return photoMedia;
}

public void setPhotoMedia(String photoMedia) {
this.photoMedia = photoMedia;
}

public String getPhotoMed_1() {
return photoMed_1;
}

public void setPhotoMed_1(String photoMed_1) {
this.photoMed_1 = photoMed_1;
}

public int getPhotoLicense() {
return photoLicense;
}

public void setPhotoLicense(int photoLicense) {
this.photoLicense = photoLicense;
}

public int getPhotoIsFam() {
return photoIsFam;
}

public void setPhotoIsFam(int photoIsFam) {
this.photoIsFam = photoIsFam;
}

public int getPhotoIsFri() {
return photoIsFri;
}

public void setPhotoIsFri(int photoIsFri) {
this.photoIsFri = photoIsFri;
}

public int getPhotoIsPri() {
return photoIsPri;
}

public void setPhotoIsPri(int photoIsPri) {
this.photoIsPri = photoIsPri;
}

public float getPhotoLongi() {
return photoLongitude;
}

public void setPhotoLongi(float photoLongi) {
this.photoLongitude = photoLongi;
}

public float getPhotoLatit() {
return photoLatitude;
}

public void setPhotoLatit(float photoLatit) {
this.photoLatitude = photoLatit;
}
}

Tag.java

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Tag {

@Id
@GeneratedValue
private Long id;

private String tag;

public Tag(String tag) {
this.tag = tag;
}

public Tag() {
}

public String getTag() {
return tag;
}

public void setTag(String tag) {
this.tag = tag;
}

public Long getId() {
return id;
}

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

}

我的 Hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
<property name="hibernate.connection.url">jdbc:postgresql://localhost:5432/GIS</property>
<property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<property name="hibernate.connection.username">postgres</property>
<property name="hibernate.connection.password">mysql15</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.hbm2ddl.auto">create</property>
<property name="hibernate.show_sql">false</property>

<mapping class="database.User" />
<mapping class="database.Photo" />
<mapping class="database.Tag" />
</session-factory>
</hibernate-configuration>

**现在一些类正在使用 hibernate 处理我的 session 管理。它们可能没那么重要,但以防万一。 **

DAO.java

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.stat.Statistics;

/**
* DAO provides general access methods on the database related to session
* management (opening and closing)
*
*
*
*/
public abstract class DAO {

/**
* Logs about correct behaviour of the hibernate session management
*/
public static Statistics stats = statistics();

/**
* Ensures that every client gets his correct session
*/
private static final ThreadLocal<Session> sessions = new ThreadLocal<>();

/**
* Returns the current hibernate session. Also takes care that there's
* always an open hibernate transaction when needed.
*
* @return Current hibernate session
*/
public static Session getSession() {
Session result = sessions.get();
if (result == null) {
result = HibernateUtil.getSessionFactory().openSession();
sessions.set(result);
result.beginTransaction();
}

return result;
}

/**
* Closes the current hibernate session, if there is one.
*/
public static void closeSession() {
Session sess = sessions.get();
if (sess == null || !sess.isOpen())
return;
sessions.remove();

try {
Throwable error = null;
try {
if (sess.getTransaction().isActive() == true) {
sess.getTransaction().commit();
}
} catch (Throwable e) {
sess.getTransaction().rollback();
error = e;
} finally {
try {
System.out.println("Sessions geöffnet bisher: "
+ stats.getSessionOpenCount());
sess.close();
System.out.println("Sessions geschlossen bisher: "
+ stats.getSessionCloseCount());
} catch (Throwable th) {
if (error != null) {
error.addSuppressed(th);
} else {
throw th;
}
}
}
} catch (HibernateException ex) {
ex.printStackTrace();
}
}

public static Statistics statistics() {
Statistics stats = HibernateUtil.getSessionFactory().getStatistics();
stats.setStatisticsEnabled(true);
return stats;
}

}

UserDAO.java

import java.util.List;

import org.hibernate.Session;

public class UserDAO extends DAO {

public void createUser(User user) {
if (user == null) {
throw new IllegalArgumentException("user must be not null");
}

Session session = getSession();

// speichern des test in der datenbank
session.save(user);

closeSession();

}

public void updateUser(User user) {
if (user == null) {
throw new IllegalArgumentException("User doesnt exist");
}
Session session = getSession();

// updaten des Users in der datenbank
session.saveOrUpdate(user);

closeSession();
}

public User getUser(Long userID) {
Session session = getSession();

@SuppressWarnings("unchecked")
List<User> oneUser = session.createQuery(
"FROM User WHERE id = " + userID).list();

closeSession();

return oneUser.get(0);
}

public User getUserByUserID(String userID) {
Session session = getSession();

@SuppressWarnings("unchecked")
List<User> oneUser = session.createQuery(
"FROM User WHERE userID = '" + userID + "'").list();

closeSession();
if (oneUser.size() > 0) {
return oneUser.get(0);
} else {
// user existiert nicht
return null;
}

}

public List<User> getAllUsers() {
Session session = getSession();

@SuppressWarnings("unchecked")
List<User> allUsers = session.createQuery("FROM users").list();

closeSession();

return allUsers;
}

}

HibernateUtil.java

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

/**
* HibernateUtil manages the access to the sessionFactory, which ensures that
* there's always an open database session
*
*
*
*/
@SuppressWarnings("deprecation")
public class HibernateUtil {

final private static SessionFactory sessionFactory;

static {
try {
// create the sessionfactory from standardconfig file
sessionFactory = new Configuration().configure("hibernate.cfg.xml")
.buildSessionFactory();

} catch (Throwable ex) {
// log the exception
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}

/**
* Returns the current SessionFactory
*
* @return Current SessionFactory
*/
public static SessionFactory getSessionFactory() {
return sessionFactory;
}

}

HibernateListener.java

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;


/**
* The HibernateListener takes care that hibernate for the database connection
* management gets initialised on the server start.
*/
public class HibernateListener implements ServletContextListener {

/**
* Calls the static initializer of the HibernateUtil class
*/
public void contextInitialized(ServletContextEvent event) {
HibernateUtil.getSessionFactory(); // Just call the static initializer
// of that class
}

/**
* Frees all ressources when the server is being restarted
*/
public void contextDestroyed(ServletContextEvent event) {
HibernateUtil.getSessionFactory().close(); // Free all resources
}
}

最佳答案

你期望它如何工作,它就应该如何工作。

我在您发布的 Hibernate 模型类中没有发现任何问题,因此我只能假设您正在为照片设置新的 Tag 实例,而不是加载它们并设置它们。

当你这样做时,hibernate 不知道这些对象是否相等,因为它们没有 ID 集(你只是创建它们,还记得吗?)。

加载标签对象并将它们分配给照片,或者如果您一心想要添加新实例,请删除级联所有选项并重写 equals 方法,以在未设置 id(空)的情况下考虑除 ID 之外的其他详细信息。

关于java - 如何在 hibernate 状态下规范化数据库? (重复值不会一次又一次保存),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16425652/

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