JPA重复数据问题:
两个实体类:
package com.itzhai.musicsystem.bean;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name=“t_user”)
public class User {
@Id
@Column(name = “user_id”)
private String username;
@Column(name = “user_nikename”, length=100)
private String nikename;
@Column(name = “user_password”, length=20)
private String password;
@Column(name = “user_email”, length=40)
private String email;
//@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, mappedBy = “creater”, fetch = FetchType.EAGER)
//单向一对多
@OneToMany(cascade = { CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.MERGE, CascadeType.REMOVE }, fetch = FetchType.EAGER, mappedBy = “creater”)
private Set
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getNikename() {
return nikename;
}
public void setNikename(String nikename) {
this.nikename = nikename;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Set<Album> getAlbums() {
return albums;
}
public void setAlbums(Set<Album> albums) {
this.albums = albums;
}
}
package com.itzhai.musicsystem.bean;
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.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name=“t_album”)
public class Album {
@Id
@Column(name = "album_id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int albumId=0;
@Column(name = "album_name", length=100)
private String albumName;
@Column(name = "album_createtime", length=20)
private Date createTime;
@ManyToOne(cascade = { CascadeType.REFRESH, CascadeType.MERGE }, optional = false)
@JoinColumn(name = "user_id")
private User creater;
//@Column(name = "album_musics")
//@OneToMany(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
@ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
@JoinTable(name = "t_album_t_music",
joinColumns = { @JoinColumn(name = "t_album_id", referencedColumnName = "album_id") },
inverseJoinColumns = { @JoinColumn(name = "t_music_id", referencedColumnName = "music_id") })
private Set<Music> musics;
public int getAlbumId() {
return albumId;
}
public void setAlbumId(int albumId) {
this.albumId = albumId;
}
public String getAlbumName() {
return albumName;
}
public void setAlbumName(String albumName) {
this.albumName = albumName;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public User getCreater() {
return creater;
}
public void setCreater(User creater) {
this.creater = creater;
}
public Set<Music> getMusics() {
return musics;
}
public void setMusics(Set<Music> musics) {
this.musics = musics;
}
}
使用Jackson框架转换:
ObjectMapper objectMapper = new ObjectMapper();
JsonGenerator jsonGenerator = null;
String result;
try {
jsonGenerator = objectMapper.getJsonFactory().createJsonGenerator(System.out, JsonEncoding.UTF8);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
QueryResult<Album> albumList = new QueryResult<Album>();
albumList = ManagerHelper.getAlbumManager().getScrollData(Album.class);
try {
jsonGenerator.writeObject(albumList.getResultlist());
} catch (JsonProcessingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
发现得出如下的数据:
[{“albumId”:1,“musics”:[{“id3v1”:“TAG”,“songName”:“红日\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000”,“artist”:“李克勤\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000”,“album”:“留住这一刻-李克勤1\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000”,“genre”:0,“musicUrl”:“http://localhost/music/李克勤-红日.mp3",“id”:7,“size”:4643195,“comment”:"\\u0000\\u0001\\f “,“year”:”\u0000\u0000\u0000\u0000”}],“albumName”:“abcdefg”,“createTime”:1335692164000,“creater”:{“username":“arthinking”,“nikename”:“abc”,“email”:"arthinking@qq.com”,“albums”:[{“albumId”:2,“musics”:[{“id3v1”:“TAG”,“songName”:“千千厥歌\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000”,“artist”:“陳慧嫻\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000”,“album”:“柔情金曲精装集\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000”,“genre”:0,“musicUrl”:“http://localhost/music/陈慧娴 - 千千厥歌.mp3”,“id”:15,“size”:8436425,“comment”:“\u0000\u0000?\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000”,“year”:“\u0000\u0000\u0000\u0000”}],“albumName”:“gggggsfeffs”,“createTime”:1335693885000,“creater”:{“username":“arthinking”,“nikename”:“abc”,“email”:"arthinking@qq.com”,“albums”:[{“albumId”:2,“musics”:[{“id3v1”:“TAG”,“songName”:“千千厥歌\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000”,“artist”:“陳慧嫻\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000”,“album”:“柔情金曲精装集\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000”,“genre”:0,“musicUrl”:“http://localhost/music/陈慧娴 - 千千厥歌.mp3”,“id”:15,“size”:8436425,“comment”:“\u0000\u0000?\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000”,“year”:“\u0000\u0000\u0000\u0000”}],“albumName”:“gggggsfeffs”,“createTime”:1335693885000,“creater”:{“username":“arthinking”,“nikename”:“abc”,“email”:"arthinking@qq.com”,“albums”:[{“albumId”:2,“musics”:[{“id3v1”:“TAG”,“songName”:“千千厥歌\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000”,“artist”:“陳慧嫻\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000”,“album”:“柔情金曲精装集\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000”,“genre”:0,“musicUrl”:“http://localhost/music/陈慧娴 - 千千厥歌.mp3”,“id”:15,“size”:8436425,“comment”:“\u0000\u0000?\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000”,“year”:“\u0000\u0000\u0000\u0000”}],“albumName”:“gggggsfeffs”,“createTime”:1335693885000,“creater”:{“username":“arthinking”,“nikename”:“abc”,“email”:"arthinking@qq.com”,此处省略n个字
之后便是一直报错:
at org.codehaus.jackson.map.ser.BeanSerializer.serializeFields(BeanSerializer.java:175)
从输出的结果可以看出是查处了不断重复的数据。
经过进一步分析发现上面的数据中Album中的creater里面又有Album,这样不断的重复获取数据,就形成了无限循环。
为了解决这个问题,就是让use成为维护端,这样从user这边查出的所有Album就不会重复了。
或者改成由Album到user的多对一关系,而不是由create到Album的一对多关系,既是把user中的album集合删除,Album成为维护端:
保留Album中的配置即可,这样就可以从Album端查出数据了。生成的表只是在t_album加了个user_id外键。
根据表的模型进行配置,不要为了ORM而ORM。根据自己的需要选择合理的配置和查询方法,这样才能写出高效的查询代码。根据自己的表的设计,查阅到到相关的配置方法进行配置,这样才能从本质上提高自己的数据库设计能力。