.Net转Java自学之路—Hibernate框架篇二(实体类、API、映射关系)
实体类编写规则:
1、实体类中属性私有化。
2、私有属性使用公开的set()和get()。
3、要求实体类中有属性作为唯一值。
4、实体类中属性建议不使用基本数据类型,而使用基本数据类型对应的包装类。
》八个基本数据类型对应的包装类:
int>>Integer、char>>Character、其他的都是首字符大写。
Hibernate主键生成策略:
1、hibernate要求实体类中有属性作为唯一值,对应表主键,主键可以不同生成策略。
2、hibernate主键生成策略有很多的值:<generator class="native"></tenerator>
》native:生成表id值就是主键自动增长。根据使用的数据库选择那个值。
》uuid:生成长度为32位的十六进制字符串。使用uuid时,实体类对应的uid必须是字符串类型。
》increment:每次增量为1依次增长。
》identity:条件是数据库支持自动增长数据类型。
》sequence:序列。条件是数据库支持序列。如:Oracle
//查询操作 SessionFactory factory=HibernateUtils.getSessionFactory(); Session session=factory.openSession(); Transaction tx=session.beginTransaction(); //get()方法:根据id查询 //第一个参数:实体类的class。第二个参数:id值 User user = session.get(User.class,1);\ tx.commit(); session.close(); factory.close(); //修改操作 SessionFactory factory=HibernateUtils.getSessionFactory(); Session session=factory.openSession(); Transaction tx=session.beginTransaction(); User user=session.get(User.class,1); user.setUsername("李四");//设置修改的值 session.update(user);或session.save(user); tx.commit(); session.close(); factory.close(); //删除操作 SessionFactory factory=HibernateUtils.getSessionFactory(); Session session=factory.openSession(); Transaction tx=session.beginTransaction(); //第一种方式: User user=session.get(User.class,1); session.delete(user); //第二种方式: User user=new User(); user.setUid(1); Session.delete(user); tx.commit(); session.close(); factory.close();
实体类的三种状态:
1、瞬时态:对象中没有id值,对象与Session没有关联。
2、持久态:对象中有id值,对象与Session关联。
3、托管态:对象中有id值,对象与Session没有关联。
saveOrUpdate():添加或修改操作。
当实体类对象状态是瞬时态时,做添加操作。
当实体类对象状态是托管态时,做修改操作。
当实体类对象状态是持久态时,做修改操作。
Hibernate缓存:
1、Hibernate框架中提供了很多优化的方式。Hibernate的缓存就是一个优化的方式。
2、Hibernate缓存特点:
》hibernate的一级缓存:
> hibernate的一级缓存默认时打开的。
> hibernate的一级缓存使用范围,是Session的范围。从Session创建到Session关闭的范围。
> hibernate的一级缓存中,存储数据必须是持久态数据。
》hibernate的二级缓存:
> 目前已经不使用了,替代技术redis。
> 二级缓存默认没有打开,需要配置开启。
> 二级缓存使用范围,是SessionFactory的范围。
一级缓存特性:持久态会自动更新数据库。
Hibernate绑定Session:
多人开发项目时,为了保证Session的单线程对象的特性。将Session与本地线程绑定即可。
1、Session类似于jdbc的Connection连接。
2、与本地线程绑定Session。其实底层就是与ThreadLocal绑定。
3、获取与本地线程Session:
》在Hibernate核心配置文件中配置。在第二部分配置<property name="hibernate.current_session_context_class">thread</property>
》调用SessionFactory中的方法得到。SessionFactory.getCurrentSession();
4、获取与本地线程绑定Session时,关闭Session会报错,所以不需要手动来关闭Session。
public class HibernateUtils{ private static final Configuration cfg=null; private static final SessionFactory factory=null; static{ cfg=new Configuration(); cfg.configure(); factory=cfg.buildSessionFactory(); } //提供方法返回SessionFactory publc static SessionFactory getSessionFactory(){ return factory; } //提供返回与本地线程绑定的Session的方法 public static Session getSessionThread(){ return factory.getCurrentSession(); } }
Hibernate查询的API使用:
Query:
1、使用Query对象,不需要写sql语句,但要写hql语句。
》hql:hibernate query language。Hibernate提供的查询语言。hql语句与普通sql语句很相似。
》hql和sql语句区别:使用sql操作表和表字段。使用hql操作实体类和属性。
2、查询所有hql语句。from 实体类名称
3、Query对象使用:
》创建Query对象:Query query = session.createQuery("from User");
》调用Query对象中的方法得到结果:List<User> list = query.list();
Criteria:
1、使用该对象查询操作,但hi使用该对象时,不需要写语句,直接调用方法即可。
2、实现过程:
》创建Criteria对象:Criteria criteria = session.createCriteria(User.class);
》调用对象中的方法得到结果:List<User> list=criteria.list();
SQLQuery:
1、使用hibernate时,调用底层SQL实现。
2、实现过程:
》创建对象:SQLQuery query = session.createSQLQuery("sql语句");
》调用对象的方法得到结果:
> List<Object[]> list = query.list();返回list集合,默认里面的每部分是数组结构。
> query.addEntity(User.class);设置将数据放到实体类中。
List<User> list=query.list();返回list集合,每部分是对象的形式。
Hibernate的一对多映射:
一对多映射配置:
1、创建一和多的实体类。(暂用OnlyClass和MoreClass表示)
2、让俩个实体类之间相互表示。
》在Hibernate中要求使用set集合表示多的数据。
》在OnlyClass中定义自身属性后,还需要定义一个set集合来表示MoreClass的属性。
》在MoreClass中定义自身属性后,还需要定义一个表示OnlyClass的属性。
3、配置映射关系:
》一般一个实体类对应一个映射文件。
》完成映射最基本的配置。
》在映射文件中,配置一对多关系。配置OnlyClass.hbm.xml的一对多关系使用set标签表示。
set标签中的name属性:属性值写在OnlyClass实体类中表示MoreClass的set集合名称。
<class> <set name="setMoreClass"> <!--一对多的建表,需要使用外键来建立关系 Hibernate机制:双向维护外键, 在一和多的双方都配置外键 column的属性值:外键名称--> <key column="mcid"></key> <!--在一的一方需要使用one-to-many标签: class属性值:MoreClass实体类全路径--> <one-to-many class="cn.test.xx.MoreClass"/> </set> </class>
配置MoreClass.hbm.cml 表示所属的OnlyClass。name属性:在MoreClass实体类中的OnlyClass名称。class属性:OnlyClass全路路径。column属性:外键名称(和OnlyClass中配置的外键名称保持一致)。
<class> <many-to-one name="onlyClass" class="cn.test.xx.OnlyClass" column="mcid"></many-to-one> </class>
4、创建核心配置文件,把映射文件引入到核心配置文件中。
SessionFactory factory = HibernateUtils.getSessionFactory(); Session session=factory.openSession(); Transaction tx=session.beginTransaction(); //创建对象。 OnlyClass onlyClass=new OnlyClass(); onlyClass.setXXX("xxx"); onlyClass.setXXX("xxx"); ...... MoreClass moreClass=new MoreClass(); moreClass.setXXX("xxx"); moreClass.setXXX("xxx"); ...... //建立OnlyClass与MoreClass关系。 //把MoreClass对象放到OnlyClass对象的set集合中。 onlyClass.getSetMoreClass().add(moreClass); //把OnlyClass对象放到MoreClass对象的set集合中。 moreClass.setOnlyClass(onlyClass); //保存到数据库 session.save(onlyClass); session.save(moreClass); tx.commit(); session.close(); factory.close();
简化写法:
1、在一OnlyClass的映射文件OnlyClass.hbm.xml中进行配置。在set标签中添加属性cascade="save-update"
<set name="setMoreClass" cascade="save-update">
2、常见一和多的对象,只需要把多的对象放到一中。最终只需要保存一即可。
SessionFactory factory = HibernateUtils.getSessionFactory(); Session session=factory.openSession(); Transaction tx=session.beginTransaction(); //创建对象。 OnlyClass onlyClass=new OnlyClass(); onlyClass.setXXX("xxx"); onlyClass.setXXX("xxx"); ...... MoreClass moreClass=new MoreClass(); moreClass.setXXX("xxx"); moreClass.setXXX("xxx"); ...... //把MoreClass对象放到OnlyClass对象中。 onlyClass.getSetMoreClass().add(moreClass); //保存到数据库 session.save(onlyClass); tx.commit(); session.close(); factory.close();
级联删除:
在删除一中的数据时,需要先删除多里面的数据。
1、先在OnlyClass映射文件set标签,进行配置。使用属性cascade="delete"
<set name="setMoreClass" cascade="save-update,delete">
2、执行过程:根据id查询OnlyClass的内容;再根据外键查询MoreClass的内容;将MoreClass的外键设置为null值;删除MoreClass的数据;删除OnlyClass的数据。
3、代码实现:
SessionFactory factory = HibernateUtils.getSessionFactory();
Session session=factory.openSession();
Transaction tx=session.beginTransaction();
OnlyClass only=session.get(OnlyClass.class,11);
session.delete(only);
tx.commit();
session.close();
factory.close();
SessionFactory factory = HibernateUtils.getSessionFactory(); Session session=factory.openSession(); Transaction tx=session.beginTransaction(); //根据id查询MoreClass的一条数据 MoreClass more=session.get(MoreClass.class,2) //根据id查询OnlyClass的一条数据 OnlyClass only=session.get(OnlyClass.class,5); //设置持久态对象值:把MoreClass放到OnlyClass中 only.getSetMoreClass().add(more); //把OnlyClass放到MoreClass中。即可完成修改 more.setOnlyClass(only); tx.commit(); session.close(); factory.close();
inverse属性:因为Hibernate是双向维护外键,所以会修改俩次外键,从而性能不是很高,造成了效率问题。
解决方式:让其中的一方不维护外键。一对多中,让一OnlyClass放弃。
实现:在放弃关系维护的映射文件中,进行配置,在set标签上使用inverse属性。inverse的默认值为false(不放弃关系维护)。而true表示放弃关系维护。
<set name="setMoreClass" cascade="save-update,delete" inverse="true">
Hibernate多对多映射:
多对多映射配置:以用户(User)和角色(Role)为例。
1、创建实体类。
2、让俩个实体相互表示。
一个用户中表示所有角色,使用set集合。
private Set<Role> role=new HashSet<Role>(); public Set<Role> getRole() { return role; } public void setRole(Set<Role> role) { this.role = role; }
一个角色有多个用户,使用set集合。
private Set<User> user=new HashSet<User>(); public Set<User> getUser() { return user; } public void setUser(Set<User> user) { this.user = user; }
3、配置映射关系:基本配置和配置多对多关系<set>标签。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="cn.test.entity.User" table="t_user"> <id name="u_id" column="u_id"> <generator class="native"></generator> </id> <property name="u_uname" column="u_uname"></property> <property name="u_pwd" column="u_pwd"></property> <property name="u_email" column="u_email"></property> <property name="u_address" column="u_address"></property> <!--t_user_role是t_user和t_role的关系表--> <set name="role" table="t_user_role" cascade="save-update,delete"> <!--key标签中配置当前映射文件第三张表外键名称--> <key column="uid"></key> <!--class:实体类全路径。column:角色在第三张表外键名称--> <many-to-many class="cn.test.entity.Role" column="rid"></many-to-many> </set> </class> </hibernate-mapping>
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="cn.test.entity.Role" table="t_role"> <id name="r_id" column="r_id"> <generator class="native"></generator> </id> <property name="r_rname" column="r_rname"></property> <property name="r_memo" column="r_memo"></property> <!--t_user_role是t_user和t_role的关系表--> <set name="user" table="t_user_role"> <!--key标签中配置当前映射文件第三张表外键名称--> <key column="rid"></key> <!--class:实体类全路径。column:角色在第三张表外键名称--> <many-to-many class="cn.test.entity.User" column="uid"></many-to-many> </set> </class> </hibernate-mapping>
4、在核心配置文件中引入映射文件。
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="connection.url">jdbc:mysql://localhost:3306/Test</property> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.username">root</property> <property name="connection.password">root123456</property> <property name="hibernate.show_sql">true</property> <property name="hibernate.format_sql">true</property> <property name="hibernate.hbm2ddl.auto">update</property> <!-- <property name="hbm2ddl.auto">update</property> --> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <mapping resource="cn/test/entity/User.hbm.xml"/> <mapping resource="cn/test/entity/Role.hbm.xml"/> </session-factory> </hibernate-configuration>
级联保存:
1、再User配置文件中set标签进行配置,cascade值save-update
2、实现:创建User、Role对象,把角色放到用户中,最终保存用户即可。
SessionFactory factory=HibernateUtils.getSessionFactory(); Session session=factory.openSession(); Transaction tx=session.beginTransaction(); User user1=new User(); user1.setUsername("zhangsan"); ..... User user2=new User(); user3.setUsername("lisi"); ..... Role role1=new Role(); role1.setR_rname("管理员"); ..... Role role2=new Role(); role2.setR_rname("普通用户"); ..... User1.getRole().add(role1); User1.getRole().add(role2); User2.getRole().add(role2); session.save(user1); session.save(user2); tx.commit;
级联删除:
User user=session.get(User.class,1); session.delete(user);
维护第三张表:
1、通过第三张表t_user_role来维护用户和角色多对多的关系。
2、让某用户有某角色:
》根据id查询用户和角色
User user=session.get(User.class,2); Role role=session.get(Role.class,1);
》把角色放到用户的set集合中:
user.getRole().add(role);
3、让某用户没有某角色:
User user=session.get(User.class,2); Role role=session.get(Role.class,1); user.getRole().remove(role);