Java Hibernate合并

时间:2017-07-05 08:11:04

标签: java mysql spring hibernate jpa

我将Java 8Spring 4.3.1.RELEASEHibernate 5.2.1.Final以及JPAMySQL一起使用。

我在数据库中有一行:

PERSON TABLE

# ID, UID, JOINING_DATE, LASTACCESS_DATE, DISPLAY_NAME, EMAIL_ADDRESS, AVATAR, PROVIDER, AVATAR_FIREBASE, MILES_KM, NOTIFICATIONS, CONTACTABLE, DEVICE_TOKEN
'384', 'h6qQg5YfQveTaCyBEXwDMSJPqwk1', '1499148701258', '1499240111170', 'Richard', 'richardmarais@gmail.com', ?, '3', 'https://scontent.xx.fbcdn.net/v/t1.0-1/p100x100/14484731_10155363658503146_8505143722410369457_n.jpg?oh=3b6fbb0facc9457f7e8387e4853278a8&oe=59D6034D', '0', '1', NULL, 'e_6U3WAVHu0:APA91bFibmAaVTLO13vG1Aww0yLK2UzRNopLK1UalurfYRXcCbUDrTJQKOm0hiKkyxV1auEWTL9od5ek62FfJIzo1li6vrgA6CfxE6Cu2HnPkSPGaeFispI2c16UBZcLZfYGRe1i9nmf'

当我尝试将Hibernate用于merge具有现有行的对象时,它会抛出一个错误,表明它是重复的。我想因为我正在做merge,它会更新现有的行。

我有以下代码:

PersonServiceImpl.java

@Transactional
public class PersonServiceImpl implements PersonService {

    @Override
    public Person save(Person person) throws Exception {
        try {
            person = personDao.merge(person);

调用:

PersonDaoImpl.java

public class PersonDaoImpl extends JpaDao<Long, Person> implements PersonDao

    @Override
    public Person merge(Person person) throws InstantiationException, IllegalAccessException {
        Person foundPerson = null;
        if (!StringUtils.isEmpty(person.getUid())) {
            foundPerson = findByUid(person.getUid(), person.getProvider());
        }
        if (foundPerson == null && !StringUtils.isEmpty(person.getId())) {
            foundPerson = findById(person.getId());         
        }
        if ((foundPerson == null || foundPerson.getUid() == null) && person.getEmailAddress() != null) {
            foundPerson = findByEmail(person.getEmailAddress());
            if (foundPerson != null) {
                foundPerson.setUid(person.getUid());
            }
        }

        if (foundPerson != null && person.getUid().equals(foundPerson.getUid())) {
            if (person.getLocations().isEmpty() && foundPerson.getLocations() != null && !foundPerson.getLocations().isEmpty()) {
                person.setLocations(foundPerson.getLocations());
            }

            BeanUtils.copyProperties(person, foundPerson);

            if (foundPerson.getLocations().isEmpty() && person.getLocations() != null && !person.getLocations().isEmpty()) {
                foundPerson.setLocations(person.getLocations());
            }
            foundPerson.setLastAccessDate(System.currentTimeMillis());
            if (Objects.isNull(foundPerson.getJoiningDate()) || foundPerson.getJoiningDate() == 0) {
                foundPerson.setJoiningDate(System.currentTimeMillis());
            }           
            return super.merge(foundPerson);   // << line executed
        } else {
            return super.merge(person);
        }
    }

调用:

JpaDao.java

public class JpaDao<I, T extends AbstractDomain<I>> {

    protected Class<T> entityClass;

    protected T merge(T entity) throws InstantiationException, IllegalAccessException {
        T attached = null;
        if (entity.getId() != null) {
            attached = entityManager.find(entityClass, entity.getId());  // << line executed
        }
        if (attached == null) {
            attached = entityClass.newInstance();
        }

        BeanUtils.copyProperties(entity, attached);
        entityManager.setFlushMode(FlushModeType.COMMIT);
         attached = entityManager.merge(attached);

        return attached;
    }

但是,当我尝试merge Person对象时,我收到以下错误:

错误

  

09:53:10,775 WARN [org.hibernate.engine.jdbc.spi.SqlExceptionHelper]   (默认任务-33)SQL错误:1062,SQLState:23000 09:53:10,781错误   [org.hibernate.engine.jdbc.spi.SqlExceptionHelper](默认任务-33)   重复录入&#39; 384-8576&#39;关键&#39; PRIMARY&#39; 09:53:10,781 INFO   [org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl](默认   task-33)HHH000010:在批量发布时它仍然包含JDBC   陈述09:53:10,782错误   [org.hibernate.internal.ExceptionMapperStandardImpl](默认任务-33)   HHH000346:托管刷新期间出错   [org.hibernate.exception.ConstraintViolationException:不能   执行声明]

问题

如果行存在,我将如何实现代码以允许更新?

谢谢

更多信息

以下是Entity

Person.java

@Entity
@Table(name = "person")
@XmlRootElement(name = "person")
public class Person extends AbstractDomain<Long> {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Size(min = 1, max = 45)
    @Column(name = "UID")
    private String uid;

    @Column(name = "JOINING_DATE", nullable = false)
    private Long joiningDate;

    @Column(name = "LASTACCESS_DATE", nullable = false)
    private Long lastAccessDate;

    @Size(min = 1, max = 85)
    @Column(name = "DISPLAY_NAME", nullable = false)
    private String displayName;

    @Size(min = 5, max = 55)
    @Column(name = "EMAIL_ADDRESS", nullable = false, unique = true)
    private String emailAddress;

    @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinTable(name = "person_language", joinColumns = {
            @JoinColumn(name = "PER_ID", referencedColumnName = "ID") }, inverseJoinColumns = {
                    @JoinColumn(name = "LANG_ID", referencedColumnName = "LANGUAGE_CODE", unique = true) })
    private Set<Language> languages;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
    @JoinTable(name = "person_location", joinColumns = {
            @JoinColumn(name = "PER_ID", referencedColumnName = "ID") }, inverseJoinColumns = {
                    @JoinColumn(name = "LOC_ID", referencedColumnName = "ID", unique = true) })
    private Set<LocationPerson> locations = null;

    @Basic(fetch = FetchType.LAZY)
    @Lob
    @Column(name = "AVATAR", nullable = true)
    private byte[] avatar;

    @Column(name = "PROVIDER")
    private Integer provider;

    @Column(name = "AVATAR_FIREBASE")
    private String avatarFirebase;

    @Column(name = "MILES_KM")
    private Integer milesKm;

    @Column(name = "NOTIFICATIONS")
    private Integer notifications;

    @Size(max = 256)
    @Column(name = "DEVICE_TOKEN")
    private String deviceToken;

    @XmlElement
    public String getDeviceToken() {
        return deviceToken;
    }

    public void setDeviceToken(String deviceToken) {
        this.deviceToken = deviceToken;
    }

    @XmlElement
    public Integer getMilesKm() {
        return milesKm;
    }

    public void setMilesKm(Integer milesKm) {
        this.milesKm = milesKm;
    }

    @Column(name = "CONTACTABLE")
    private Long contactable;

    @Transient
    private Boolean contactableFree;

    @XmlElement
    public Boolean getContactableFree() {
        return contactableFree;
    }

    public void setContactableFree(Boolean contactableFree) {
        this.contactableFree = contactableFree;
    }

    @XmlElement
    public Long getContactable() {
        return contactable;
    }

    public void setContactable(Long contactable) {
        this.contactable = contactable;
    }

    @XmlElement
    public Integer getNotifications() {
        return notifications;
    }

    public void setNotifications(Integer notifications) {
        this.notifications = notifications;
    }

    @XmlElement
    public Long getId() {
        return id;
    }

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

    @XmlElement
    public Long getJoiningDate() {
        return joiningDate;
    }

    public void setJoiningDate(Long joiningDate) {
        this.joiningDate = joiningDate;
    }

    @XmlElement
    public Long getLastAccessDate() {
        return lastAccessDate;
    }

    public void setLastAccessDate(Long lastAccessDate) {
        this.lastAccessDate = lastAccessDate;
    }

    @XmlElement
    public String getUid() {
        return uid;
    }

    public void setUid(String uid) {
        this.uid = uid;
    }

    @XmlElement
    public String getDisplayName() {
        return displayName;
    }

    public void setDisplayName(String displayName) {
        this.displayName = displayName;
    }

    @XmlElement
    public String getEmailAddress() {
        return emailAddress;
    }

    public void setEmailAddress(String emailAddress) {
        this.emailAddress = emailAddress;
    }

    @XmlElement
    public Set<Language> getLanguages() {
        return languages;
    }

    public void setLanguages(Set<Language> languages) {
        this.languages = languages;
    }

    @XmlElement
    public Set<LocationPerson> getLocations() {
        return locations;
    }

    public void setLocations(Set<LocationPerson> locations) {
        if (this.locations == null) {
            this.locations = locations;
        } else {
            this.locations.retainAll(locations);
            this.locations.addAll(locations);
        }
    }

    public void putLocations(Set<LocationPerson> locations) {
        if (locations != null) {
            this.locations.clear();
            this.locations.addAll(locations);
        } else {
            this.locations = locations;
        }
    }

    @XmlElement
    public byte[] getAvatar() {
        return avatar;
    }

    public void setAvatar(byte[] avatar) {
        this.avatar = avatar;
    }

    @XmlElement
    public Integer getProvider() {
        return provider;
    }

    public void setProvider(Integer provider) {
        this.provider = provider;
    }

    @XmlElement
    public String getAvatarFirebase() {
        return avatarFirebase;
    }

    public void setAvatarFirebase(String avatarFirebase) {
        this.avatarFirebase = avatarFirebase;
    }
}

更新

在阅读the following后,我将Person对象locationsCascadeType.ALL更改为CascadeType.PERSIST

Person.java

@OneToMany(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER, orphanRemoval = true)
@JoinTable(name = "person_location", joinColumns = {
        @JoinColumn(name = "PER_ID", referencedColumnName = "ID") }, inverseJoinColumns = {
                @JoinColumn(name = "LOC_ID", referencedColumnName = "ID", unique = true) })
private Set<LocationPerson> locations = null;

更新已完成到数据库,但我现在得到以下内容:

  

10:41:20,657错误   [org.hibernate.internal.ExceptionMapperStandardImpl](默认任务-7)   HHH000346:托管刷新期间出错   [org.hibernate.TransientObjectException:object引用未保存的   瞬态实例 - 在查询刷新之前保存瞬态实例:   com.jobs.spring.domain.LocationPerson] 10:41:21,429 INFO   [org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl](默认   task-7)HHH000010:在批量发布时,它仍然包含JDBC   语句

0 个答案:

没有答案