开发者

Update an entity (OneToMany relationship)

开发者 https://www.devze.com 2023-03-18 20:53 出处:网络
i got 2 entities, Student and Phone, and a relationship one-to-many between them. @Entity @Table(name = \"STUDENT\")

i got 2 entities, Student and Phone, and a relationship one-to-many between them.

@Entity 
@Table(name = "STUDENT") 
public class Student { 

    private long studentId; 
    private String studentName; 
    private Set<Phone> studentPhoneNumbers = new HashSet<Phone>(0); 

    public Student() { 
    } 

    public Student(String studentName, Set<Phone> studentPhoneNumbers) { 
        this.studentName = studentName; 
        this.studentPhoneNumbers = studentPhoneNumbers; 
    } 

    @Id 
    @GeneratedValue 
    @Column(name = "STUDENT_ID") 
    public long getStudentId() { 
        return this.studentId; 
    } 

    public void setStudentId(long studentId) { 
        this.studentId = studentId; 
    } 

    @Column(name = "STUDENT_NAME", nullable = false, length = 100) 
    public String getStudentName() { 
        return this.studentName; 
    } 

    public void setStudentName(String studentName) { 
        this.studentName = studentName; 
    } 

    @OneToMany (mappedBy="student", cascade = CascadeType.ALL)       

    public Set<Phone> getStudentPhoneNumbers() { 
        return this.studentPhoneNumbers; 
    } 

    public void setStudentPhoneNumbers(Set<Phone> studentPhoneNumbers) { 
        this.studentPhoneNumbers = studentPhoneNumbers; 
    } 

} 


@Entity 
@Table(name = "PHONE") 
public class Phone { 

    private long phoneId; 
    private String phoneType; 
    private String phon开发者_如何学PythoneNumber; 

    private Student student; 
    private Set<Student> students = new HashSet<Student>(0); 

    public Phone() { 
    } 

    public Phone(String phoneType, String phoneNumber) { 
        this.phoneType = phoneType; 
        this.phoneNumber = phoneNumber; 
    } 

    @Id 
    @GeneratedValue 
    @Column(name = "PHONE_ID") 
    public long getPhoneId() { 
        return this.phoneId; 
    } 

    public void setPhoneId(long phoneId) { 
        this.phoneId = phoneId; 
    } 

    @Column(name = "PHONE_TYPE", nullable = false, length=10) 
    public String getPhoneType() { 
        return this.phoneType; 
    } 

    public void setPhoneType(String phoneType) { 
        this.phoneType = phoneType; 
    } 

    @Column(name = "PHONE_NUMBER", nullable = false, length=15) 
    public String getPhoneNumber() { 
        return this.phoneNumber; 
    } 

    public void setPhoneNumber(String phoneNumber) { 
        this.phoneNumber = phoneNumber; 
    } 

    @ManyToOne(cascade = CascadeType.ALL) 
    @JoinColumn (name="STUDENT_ID") 
    public Student getStudent() { 
        return this.student; 
    } 

    public void setStudent(Student student) { 
        this.student = student; 
    }   

here is the code of applicationContext.xml:

  ... 
 <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">   
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>   
        <property name="url" value="jdbc:mysql://localhost/Project"/>   
        <property name="username" value="root"/>   
        <property name="password" value="root"/>   
    </bean>   

    <bean id="mySessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">   
        <property name="dataSource" ref="myDataSource" />   
        <property name="annotatedClasses">   
            <list>   
                <value>com.domain.Student</value>                         
                <value>com.domain.Phone</value>                           
            </list>   
        </property>   
        <property name="hibernateProperties">   
            <props>   
                <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>   
                <prop key="hibernate.show_sql">true</prop>   
                <prop key="hibernate.hbm2ddl.auto">create</prop>   
            </props>   
        </property>   
    </bean>   

 <bean id="myClassDAO" class="com.project.dao.ClassDAOImpl"> 
        <property name="sessionFactory" ref="mySessionFactory"/> 
 </bean>   

...  

And my ClassDAOImpl looks like:

    public class ClassDAOImpl{ 

    private HibernateTemplate hibernateTemplate; 
    private Session session; 
    public void setSessionFactory(SessionFactory sessionFactory) { 
            this.hibernateTemplate = new HibernateTemplate(sessionFactory); 
            this.session = sessionFactory.openSession(); 
    }     

    public void updateStudent(){ 

            Transaction transaction = session.beginTransaction();           
            Student s = (Student)session.get(Student.class, new Long(1));   
            Set<Phone> phoneNumbers =s.getStudentPhoneNumbers();   
            phoneNumbers.add(new Phone ("house","12342342"));   
            s.setStudentPhoneNumbers(phoneNumbers);   
            session.update(s);   
            transaction.commit(); 

    } 

}  

I just want to add a phone to the student with primary key "1". For this purpose, first I get the student and then I update the phone set by adding a new one. Finally I update the entity Student. I looked at my Phone table, and there was a new row with the new phone, but the foreign key (STUDENT_ID) appeared with "Null" value, therefore the relationship is not registered. How could i fix it?

Thanks in advance


Try this:

public void updateStudent(){ 

        Transaction transaction = session.beginTransaction();           
        Student s = (Student)session.get(Student.class, new Long(1));   
        Set<Phone> phoneNumbers =s.getStudentPhoneNumbers();   
        Phone phone = new Phone("house", "12342342");
        phone.setStudent(s);
        phoneNumbers.add(phone);   
        s.setStudentPhoneNumbers(phoneNumbers);   
        session.update(s);   
        transaction.commit(); 

    }

Or better yet, add a utility method to student like so:

public void addPhone(Phone phone) {
    if (phone == null) throw new IllegalArgumentException("Cannot add a null phone to a Student!");
    phone.setStudent(this);
    getStudents().add(phone);
}

And change your updateStudent method to be:

public void updateStudent(){ 

        Transaction transaction = session.beginTransaction();           
        Student s = (Student)session.get(Student.class, new Long(1));   
        Phone phone = new Phone("house", "12342342");
        s.addPhone(phone);
        session.update(s);   
        transaction.commit(); 

    } 

Also make sure you have set your cascade options to cascade to phone.


In bidirectional entity relationships, it is always advisable to wire both sides of the relationship. This is in spite of the fact that you do have an owning side of the relationship (the side not marked with "mappedBy").

So for example, when you are creating a new relationship, invoke the getStudentPhoneNumbers().addPhone(newPhone) on the student entity as well as the setStudent() on the phone entity.


In JPA/Hibernate, you always have to maintain both sides of a bidirectional association yourself. The owning side of an association, which is the side used by Hibernate to know if an association exists or has changed, is the side where these is no mappedBy attribute.

In your case, it's the Phone which is the owning side. So if you don't set the student property of the phone you create, Hibernate will consider that the phone is not linked to any user, even if user has the phone in its list of phones.

Side note: read the Spring documentation about declarative transaction management. You really don't do what should be done to get an open session and manage transactions.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号