Hibernate注解(一对一、一对多、多对多)
1、创建两个实体类。
一个实体类是商品类,另一个实体类是商品的分类类。
在一对多关系的两个实体中,在编写实体类时必须要遵循以下规则:
(1)在一的那一方的实体中,必须要有一个私有的多那一方的实体对象属性,并且提供公有的getter和setter方法。
private Integer gid; private String gname; private String gmessage; /** * 在一对多关系中,在一的这一方,必须要有一个多的对象的私有属性 * 别提供共有的getter和setter方法。 */ private Sort sort; public Sort getSort() { return sort; } public void setSort(Sort sort) { this.sort = sort; }
(2)在多的那一方的实体类中,必须要有一个私有的set集合属性来保存一的那一方的对象,并提供公有的getter和setter属性。
private Integer sid; private String gname; private String gmessage; /** * 在一对多关系中,在多的那一方,必须要有一个set集合属性来保存一个那个实体 * 并提供共有的getter和setter方法。 */ private Set<Good> getSet = new HashSet<Good>(); public Set<Good> getGetSet() { return getSet; } public void setGetSet(Set<Good> getSet) { this.getSet = getSet; }
2、编写两个实体类的映射文件。
(1)一的那一方的映射文件。
在一的这一方,需要使用<many-to-one>标签来配置对应关系。
<hibernate-mapping> <class name="com.jack.entity.Good" table="t_good"> <id name="gid" column="gid"> <generator class="native"></generator> </id> <property name="gname" column="gname"></property> <property name="gmessage" column="gmessage"></property> <!-- 表示商品所属的分类 name属性的值:因为在Good商品实体中,用sort表示Sort实体类,所有这里写sort class属性的值:sort类的全路径 column属性的值:外键的名称 --> <many-to-one name="sort" class="com.jack.entity.Sort" column="gsid"></many-to-one> </class> </hibernate-mapping>
(2)多的那一方的映射文件。
在多的这一方,需要使用<set>标签来配置对应关系。
<hibernate-mapping> <class name="com.jack.entity.Sort" table="t_sort"> <id name="sid" column="sid"> <generator class="native"></generator> </id> <property name="sname" column="sname"></property> <property name="smessage" column="smessage"></property> <!-- 在多的这一边使用set标签来设置对应关系 name属性的值:因为在Sort中使用getSet保存good属性。 column属性的值:外键的名称,由于在Hibernate使用双向维护主键 所有在这边的column的值必须要和另一边的值一致 class属性的值:Good实体类的全路径。 --> <set name="getSet"> <key column="gsid"></key> <one-to-many class="com.jack.entity.Good" /> </set> </class> </hibernate-mapping>
3、编写核心配置文件
<hibernate-configuration> <session-factory> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql:///hibernatetest</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">root</property> <property name="hibernate.show_sql">true</property> <property name="hibernate.format_sql">true</property> <property name="hibernate.hbm2ddl.auto">update</property> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name=" hibernate.current_session_context_class">thread</property> <mapping resource="com/jack/entity/Good.hbm.xml"/> <mapping resource="com/jack/entity/Sort.hbm.xml"/> </session-factory> </hibernate-configuration>
4、编写工具类
public class HibernateUtils { private static Configuration configuration = null; private static SessionFactory sessionFactory = null; static{ configuration = new Configuration().configure(); sessionFactory = configuration.buildSessionFactory(); } public static Session getSeeion() { return sessionFactory.getCurrentSession(); } }
5、编写级联保存代码
第一种代码(复杂):
@Test public void TestAdd(){ Session session = null; Transaction tx = null; try { session = HibernateUtils.getSeeion(); tx = session.beginTransaction(); /** * 创建两个商品 */ Good good1 = new Good(); good1.setGname("蛋糕"); good1.setGmessage("奶油蛋糕"); Good good2 =new Good(); good2.setGname("牙膏"); good2.setGmessage("冷酸灵牙膏"); /** * 创建两个类别 */ Sort sort1 =new Sort(); sort1.setSname("食品"); sort1.setSmessage("食品类"); Sort sort2 = new Sort(); sort2.setSname("生活用品"); sort2.setSmessage("生活用品类"); /** * 将商品放到类别中 */ sort1.getGetSet().add(good1); sort2.getGetSet().add(good2); /** * 将类别设置到商品中 */ good1.setSort(sort1); good2.setSort(sort2); /** * 保存类别 * 保存商品 */ session.save(sort1); session.save(sort2); session.save(good1); session.save(good2); tx.commit(); } catch (Exception e) { tx.rollback(); }finally{ } }
第二种代码(简单):
首先在多的那一方的配置文件的<set>标签内,写入cascade属性,其值为save-update。
<set name="getSet" cascade="save-update"> <key column="gsid"></key> <one-to-many class="com.jack.entity.Good" /> </set>
然后编写代码
@Test public void TestAdd2(){ Session session = null; Transaction tx = null; try { session = HibernateUtils.getSeeion(); tx = session.beginTransaction(); /** * 创建两个商品 */ Good good3 = new Good(); good3.setGname("面包"); good3.setGmessage("面包"); /** * 获得食品类 */ Sort sort1 = session.get(Sort.class, 1); /** * 将商品放到类别中 */ sort1.getGetSet().add(good3); /** * 保存类别 * 现在只需要保存类别,商品也会自动保存 */ session.save(sort1); tx.commit(); } catch (Exception e) { tx.rollback(); }finally{ } }
6、Hibernate默认双方都要维护主键,这样会降低效率,通过配置inverse属性可以让一方放弃维护主键,这样可以提高操作效率。一般让多的那一方放弃。
<!-- true:表示不维护 false:表示维护主键 默认为false,维护主键 --> <set name="getSet" cascade="save-update" inverse="true"> <key column="gsid"></key> <one-to-many class="com.jack.entity.Good" /> </set>
7、测试结果
8、级联删除
首先配置cascade属性,值为delete
<set name="getSet" cascade="save-update,delete" inverse="true"> <key column="gsid"></key> <one-to-many class="com.jack.entity.Good" /> </set>
编写代码实现删除(删除食品类)
@Test public void TestDelete(){ Session session = null; Transaction tx = null; try { session = HibernateUtils.getSeeion(); tx = session.beginTransaction(); /** * 找到食品类 */ Sort sort = session.get(Sort.class, 1); /** 删除食品类 */ session.delete(sort); tx.commit(); } catch (Exception e) { tx.rollback(); }finally{ } }
测试结果:
9、级联修改
修改前数据库
修改代码(把蛋糕放到生活用品中):
@Test public void TestUpdate(){ Session session = null; Transaction tx = null; try { session = HibernateUtils.getSeeion(); tx = session.beginTransaction(); /** * 找到生活用品 */ Sort sort = session.get(Sort.class, 2); /** * 找到蛋糕 */ Good good =session.get(Good.class, 4); /** * 把蛋糕放到生活用品中去 */ sort.getGetSet().add(good); /** * 把生活用品设置到蛋糕中去 */ good.setSort(sort); tx.commit(); } catch (Exception e) { tx.rollback(); }finally{ } }
修改之后结果:
https://www.cnblogs.com/jack1995/p/6942162.html
JPA(Java Persistence API)通过注解或XML描述对象与关系表的映射关系,并将运行期的实体对象持久化到数据库中。
JPA是一个规范,是一个标准,Hibernate是实现了这个标准的开源框架。
1、引入hibernate-jpa-2.0-api-1.0.0.Final.jar JPA规范对应的hibernate的jar包
2、修改配置文件hibernate.cfg.xml 的映射关系<Mapping class="">
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- thread:一个线程中使用一个。获取session会话时使用--> <property name="current_session_context_class">thread</property> <!-- 是否显示SQL语句,值为布尔型,默认false --> <property name="hibernate.show_sql">true</property> <!-- 是否格式化显示sql语句,让显示更美观,值为布尔型,默认false --> <property name="hibernate.format_sql">false </property> <!-- 自动建表 update:每次执行时,无表则建表,无列则建列,只增不减 create:每次启动的时候,删除原表,再次创建 create-drop:每次启动时创建新表,当显式关闭sessionFactory时,删除表 --> <property name="hibernate.hbm2ddl.auto">update</property> <!-- 连接数据库 --> <property name="hibernate.connection.url">jdbc:mysql://127.0.0.1:3306/zxd_db</property> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.username">zxd</property> <property name="hibernate.connection.password">123456</property> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <!-- 读取注解 --> <mapping class="demo.entity.Book" /> </session-factory> </hibernate-configuration>
3、实体配置
package demo.entity; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; import org.hibernate.annotations.GenericGenerator; /** * 注解实体配置 * JPA通过注解或XML描述对象与关系表的映射关系,并将运行期的实体对象持久化到数据库中。 * @author Don * @date:日期:2017年4月19日 时间:上午10:43:00* * @version 1.0 */ //标注实体 @Entity //实体对应的表名,自动建库(若不写name,则表名与实体名保持一致) @Table(name="tb_book") public class Book { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) //主键ID注解 private int id; @Id @GenericGenerator(name="pk_uuid",strategy="uuid") @GeneratedValue(generator="pk_uuid") //生成UUID的主键注解 private String uuid; @Column //列注解 private String name; @Column private double price; 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; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public String getUuid() { return uuid; } public void setUuid(String uuid) { this.uuid = uuid; } }
4、数据库实务session创建
package demo.util; import java.text.Annotation; import org.hibernate.SessionFactory; import org.hibernate.cfg.AnnotationConfiguration; import org.hibernate.cfg.Configuration; import org.hibernate.classic.Session; public class HibernateUtil { public static Session getCurrentSession() { /*注解调用使用AnnotationConfiguration 对象创建*/ // 加载Hibernate配置信息,默认读取src下的hibernate.cfg.xml Configuration cfg = new AnnotationConfiguration().configure(); // 也可以指定hibernate.cfg.xml 的路径加载 // Configuration cfg1 = new Configuration().configure(Path); /* * 应用程序从SessionFactory(会话工厂)里获得Session(会话)实例。它在多个应用线程间进行共享。 * 通常情况下,整个应用只有唯一的一个会话工厂,SessionFactory由Configuration对象创建, * 每个Hibernate配置文件,实际上是对SessionFactory的配置 */ // 试用配置信息构建sessionFactory SessionFactory factory = cfg.buildSessionFactory(); Session session =factory.getCurrentSession(); return session; } }
5、测试建表和增删改查和XML配置映射一致
(一)、 一对一映射(主键关联)
Card实体类
Person实体类
(二)、一对一映射(唯一外键)
Card实体类
Person实体类
(三)、一对多映射
Classes实体类(课程)
package demo.entity; import java.util.ArrayList; import java.util.List; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.Table; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CascadeType; @Entity @Table(name="ann_m2o_Classes") public class Classes { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private int id; @Column private String name; @OneToMany(mappedBy="cal") @Cascade(CascadeType.ALL) //一对多关系配置(配置Student实体中的Class实体映射对象,设计级联关系) private List<Student> list = new ArrayList<Student>(); 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; } public List<Student> getList() { return list; } public void setList(List<Student> list) { this.list = list; } }
Student实体类(学生)
package demo.entity; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CascadeType; @Entity @Table(name="ann_m2o_Student") public class Student { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private int id; @Column private String name; @ManyToOne @JoinColumn(name="cid") @Cascade(CascadeType.SAVE_UPDATE) private Classes cal; 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; } public Classes getCal() { return cal; } public void setCal(Classes cal) { this.cal = cal; } }
(四)、多对多映射(中间表)
Course实体类(选课)
package demo.entity; import java.util.HashSet; import java.util.Set; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import javax.persistence.Table; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CascadeType; import org.hibernate.annotations.GenericGenerator; /** * 课程实体 * @author Don * @date:日期:2017年4月11日 时间:下午2:25:45* * @version 1.0 */ @Entity @Table(name="ann_m2m_Course") public class Course { @Id @GenericGenerator(name="pk_key",strategy="uuid") @GeneratedValue(generator="pk_key") private String id; @Column private String name; @ManyToMany //级联关系 @Cascade(CascadeType.SAVE_UPDATE) //中间表 @JoinTable(name="ann_m2m_stu_course", //链接当前对象的Id joinColumns={@JoinColumn(name="cid",referencedColumnName="id")}, //链接对方的表的Id inverseJoinColumns={@JoinColumn(name="stuId",referencedColumnName="id")}) private Set<Student> stus = new HashSet<>(); public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<Student> getStus() { return stus; } public void setStus(Set<Student> stus) { this.stus = stus; } public Course(){} public Course(String name) { this.setName(name); } }
Student实体类(选课人员)
package demo.entity; import java.util.HashSet; import java.util.Set; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinColumns; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import javax.persistence.Table; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CascadeType; import org.hibernate.annotations.GenericGenerator; /** * 学生实体 * @author Don * @date:日期:2017年4月11日 时间:下午2:25:15* * @version 1.0 */ @Entity @Table(name="ann_m2m_Student") public class Student { @Id //生成UUID @GenericGenerator(name="pk_key",strategy="uuid") @GeneratedValue(generator="pk_key") private String id; @Column private String name; @ManyToMany //级联关系 @Cascade(CascadeType.SAVE_UPDATE) //中间表 @JoinTable(name="ann_m2m_stu_course", //链接当前对象的Id joinColumns={@JoinColumn(name="stuId",referencedColumnName="id")}, //链接对方的表的Id inverseJoinColumns={@JoinColumn(name="cid",referencedColumnName="id")}) private Set<Course> cous=new HashSet<>(); public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<Course> getCous() { return cous; } public void setCous(Set<Course> cous) { this.cous = cous; } public Student() { } public Student(String name) { this.setName(name); } }
https://www.cnblogs.com/zxd543/p/6734559.html