标签:date() cer 外键 word sql ppi text root nfa
@OneToMany注解可以用在一对多的数据结构来操作数据库,这里以班级<->学生为例来测试这个注解。
首先来看看项目结构:
xml文件配置,与前面一篇‘一对一‘的随笔差不多,有两个Java类:ClassRoom、Student。所以,应该将两个表写到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">com.mysql.jdbc.Driver</property> <!-- 设置数据库的连接 --> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate?useSSL=false&useUnicode=true&characterEncoding=UTF-8</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">123456</property> <!-- 数据库的方言:根据底层的数据库生成不同的SQL --> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <!-- 配置显示SQL --> <property name="hibernate.show_sql">true</property> <!-- 配置格式化SQL --> <property name="hibernate.format_sql">true</property> <property name="hibernate.hbm2ddl.auto">update</property> <property name="hibernate.current_session_context_class">thread</property> <mapping class="o2m.Student"/> <mapping class="o2m.ClassRoom"/> </session-factory> </hibernate-configuration>
ClassRoom类:
package o2m; import javax.persistence.*; import java.util.Set; @Entity public class ClassRoom { @Id @GeneratedValue(strategy= GenerationType.IDENTITY) @Column private Integer cid; @OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.LAZY) @JoinColumn(name = "cid") private Set<Student> stus; // 学生集合 @Column private Integer nums; // 一个班的总人数 public ClassRoom() { } public ClassRoom(Set<Student> stus, Integer nums) { this.stus = stus; this.nums = nums; } public Integer getCid() { return cid; } public void setCid(Integer cid) { this.cid = cid; } public Set<Student> getStus() { return stus; } public void setStus(Set<Student> stus) { this.stus = stus; } public Integer getNums() { return nums; } public void setNums(Integer nums) { this.nums = nums; } }
@OneToMany注解写在少的类中的对应多的头上。
Student类:
package o2m; import org.hibernate.annotations.GenericGenerator; import javax.persistence.*; import java.util.Date; @Entity public class Student { @Id @GeneratedValue(generator="sid") @GenericGenerator(name="sid", strategy = "assigned") @Column(length = 6) private String sid; // 学号 @Column private String name; // 姓名 @Column private String sex; // 性别 @Column private String school; // 学校 @Column private String address; // 地址 @Column private Date registertime; // 注册学籍时间 public Student() { } public Student(String sid, String name, String sex, String school, String address, Date registertime) { this.sid = sid; this.name = name; this.sex = sex; this.school = school; this.address = address; this.registertime = registertime; } public String getSid() { return sid; } public void setSid(String sid) { this.sid = sid; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getSchool() { return school; } public void setSchool(String school) { this.school = school; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public Date getRegistertime() { return registertime; } public void setRegistertime(Date registertime) { this.registertime = registertime; } }
还有一个@ManyToOne注解,@ManyToOne应加在多的类中的对应少的头上,但这里我没有用,因为目前需求只要单向外键关联的。
这样就有两张表了:
然后插入数据测试:
package main; import o2m.ClassRoom; import o2m.Student; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import controller.StudentController; import java.util.*; public class Main { public static void main(String[] args) { Configuration configuration = new Configuration().configure(); ServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build(); SessionFactory sessionFactory = configuration.buildSessionFactory(registry); Session session = sessionFactory.getCurrentSession(); Transaction transaction = session.beginTransaction(); List<String> name = new LinkedList<>(); List<String> sex = new LinkedList<>(); List<String> address = new LinkedList<>(); name.add("漩涡鸣人"); name.add("宇智波佐助"); name.add("春野樱"); name.add("旗木卡卡西"); name.add("自来也"); name.add("纲手"); name.add("大蛇丸"); name.add("宇智波鼬"); name.add("九尾"); name.add("八尾"); sex.add("男"); sex.add("男"); sex.add("女"); sex.add("男"); sex.add("男"); sex.add("女"); sex.add("男"); sex.add("男"); sex.add("男"); sex.add("男"); address.add("木叶村501号"); address.add("木叶村504号"); address.add("木叶村902号"); address.add("木叶村401号"); address.add("木叶村107号"); address.add("木叶村219号"); address.add("木叶村901号"); address.add("木叶村116号"); address.add("木叶村511号"); address.add("木叶村801号"); Set<Student> s1 = new HashSet<>(); for (int i = 0; i < name.size(); i++) { Student studenet = new Student( "S0000" + i, name.get(i), sex.get(i), "木叶村", address.get(i), new Date() ); s1.add(studenet); session.save(studenet); } ClassRoom c1 = new ClassRoom(s1, s1.size()); session.save(c1); transaction.commit(); session.close(); } }
这里注意session.close(),应该放在提交(commit)的后面,不然Student中cid就为null,如果不写也可以,但我想一般api都加上关闭更符合标准一点。
ps:请不用在意我使用List,我知道它的底层是链表,肯定效率不如数组,这里只是想用用它而已。。。
最后看一看插入数据后的效果:
ClassRoom表:
对应为:1班共10人。
Student表:
显然,cid是外键classroom的主键,即这些学生都是1班的。
实际上也有好多问题我不明白,比如,我将CRUD功能单独封装起来调用,就不能有这样的效果了。。。可能我的session会话没使用正确、@OneToMany的具体作用我也不清楚...感觉按理来说Student中没有ClassRoom对象成员,我的操作中也没有手动设置,那么外键cid不应该会有值(这样说也不对,因为本来cid就是外键,既然ClassRoom表创建并给cid赋值了,那它理应有值,与Student无关,但我就是遇到有情况,ClassRoom类中cid有值,但Student表中就为null,比如前面提到的session.close()放在了commit前面就会有这种情况),那么只有可能是@OneToMany做了这件事,正因为有这个注解,Student表中对应的外键就能自动关联...感觉应该是这样。
标签:date() cer 外键 word sql ppi text root nfa
原文地址:https://www.cnblogs.com/darkchii/p/8758960.html