学生, 课程,分数的设计.
a)使用联合主键@EmbeddedId
使用Serializable接口
b)不适用联合主键
联合主键:
3张表,
student: id, name
course: id , name
score:studentid, courseid, score. (两个id就是联合ID)
不使用联合主键的话:
student:id, name
course: id, name
score: id,name, student, course
score--> student: many to one
course-->student: many to one
student->course: many to many
设计:
1. 实体类(表)
2. 导航 (为了编程方便)
3. 确定编程方式
Student.java:
package com.bjsxt.hibernate; import java.util.HashSet; import java.util.Set; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; @Entity public class Student { private int id; private String name; private Set<Course> courses = new HashSet<Course>(); @ManyToMany @JoinTable(name="score", joinColumns=@JoinColumn(name="student_id", referencedColumnName="id"), inverseJoinColumns=@JoinColumn(name="course_id", referencedColumnName="id") ) public Set<Course> getCourses() { return courses; } public void setCourses(Set<Course> courses) { this.courses = courses; } @Id @GeneratedValue public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
Course.java:
package com.bjsxt.hibernate; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @Entity public class Course { private int id; private String name; @Id @GeneratedValue public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
Score.java:
package com.bjsxt.hibernate; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; @Entity @Table(name="score") public class Score { private int id; private int score; private Student student; private Course course; @Id @GeneratedValue public int getId() { return id; } public void setId(int id) { this.id = id; } public int getScore() { return score; } public void setScore(int score) { this.score = score; } @ManyToOne @JoinColumn(name="student_id") public Student getStudent() { return student; } public void setStudent(Student student) { this.student = student; } @ManyToOne @JoinColumn(name="course_id") public Course getCourse() { return course; } public void setCourse(Course course) { this.course = course; } }
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="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://localhost/hibernate</property> <property name="connection.username">root</property> <property name="connection.password">linda0213</property> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <!-- <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property> <property name="connection.url">jdbc:oracle:thin:@localhost:1521:SXT</property> <property name="connection.username">scott</property> <property name="connection.password">tiger</property> <property name="dialect">org.hibernate.dialect.OracleDialect</property> --> <!-- JDBC connection pool (use the built-in) --> <property name="connection.pool_size">1</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.NoCacheProvider</property> <!-- Echo all executed SQL to stdout --> <property name="show_sql">true</property> <property name="format_sql">true</property> <!-- Drop and re-create the database schema on startup <property name="hbm2ddl.auto">update</property> --> <!-- <mapping resource="com/bjsxt/hibernate/Group.hbm.xml"/> <mapping resource="com/bjsxt/hibernate/User.hbm.xml"/> --> <mapping class="com.bjsxt.hibernate.Student"/> <mapping class="com.bjsxt.hibernate.Course"/> <mapping class="com.bjsxt.hibernate.Score"/> </session-factory> </hibernate-configuration>
test文件:
package com.bjsxt.hibernate; import java.util.Map; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; import org.hibernate.tool.hbm2ddl.SchemaExport; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; public class HibernateTreeTest { private static SessionFactory sessionFactory; @BeforeClass public static void beforeClass() { //new SchemaExport(new AnnotationConfiguration().configure()).create(false, true); sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory(); } @AfterClass public static void afterClass() { sessionFactory.close(); } @Test public void testSave() { Student s = new Student(); s.setName("zhangsan"); Course c = new Course(); c.setName("java"); Score score = new Score(); score.setCourse(c); score.setStudent(s); Session session = sessionFactory.openSession(); session.beginTransaction(); session.save(s); session.save(c); session.save(score); session.getTransaction().commit(); session.close(); } @Test public void testLoad() { testSave(); Session session = sessionFactory.openSession(); session.beginTransaction(); Student s = (Student)session.load(Student.class, 1); for(Course c : s.getCourses()) { System.out.println(c.getName()); } session.getTransaction().commit(); session.close(); } @Test public void testSchemaExport() { new SchemaExport(new AnnotationConfiguration().configure()).create(false, true); } public static void main(String[] args) { beforeClass(); } }
最后生成的score有问题, 变成了联合主键, 所以删除掉score表, 自己建一个:
use hibernate; create table score(id int primary key auto_increment,student_id int references student(id),course_id int references course(id), score int)
然后注释掉beforeclass里的创建表语句再次执行就没问题了.