hibernate基本步骤
一、导包
使用hibernate框架的第一步是先导jar包,在hibernate官网上下载文件,导入hibernate框架必须的jar包。
另外,如果使用的JDK小于等于8的话,有上述的jar包就够了,但如果使用JDK版本大于8的话,只有hibernate的jar包还不够,在运行程序时会抛出异常java.lang.ClassNotFoundException: javax.xml.bind.JAXBException,所以如果是JDK8以上的版本的话,还需要导入其他的包,参考
https://blog.youkuaiyun.com/hadues/article/details/79188793
二、配置hibernate.cfg.xml
在导入hibernate所需的jar包之后,下一步就是创建hibernate主配置文件进行添加所需的配置信息。
1. 创建hibernate主配置文件,命名格式一般为hibernate.cfg.xml,后面读取配置文件时默认是读取该文件名;配置文件一般放置在src目录下。
2. 添加xml头部信息;
3. 配置连接数据库的四个必须的属性:driver、url、username、password;
4. 配置两个可选的属性:show_sql、format_sql;这两个属性设置为true时分别表示在控制台显示执行的SQL语句、格式化显示的SQL语句。
5. 配置DDL:create-drop/create/update/validate;create-drop和create会在执行SQL之前,先删除表,再创建新表,执行SQL;update则是在执行SQL之前,若没有表,就创建表执行SQL,若有表就直接执行SQL,推荐使用update;validate没啥用,没有表的情况下会直接抛出异常。
6. 关联 ORM 映射:关联实体类的映射文件。
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 四个必须-->
<property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="hibernate.connection.url">
jdbc:mysql://localhost:3306/...
</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<!-- 两个可选-->
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<!-- 配置方言-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 配置ddl:
create-drop:右表先删表,再建表,再执行其他操作
create:与create-drop一样
update:若没有表则建表,再更新表,若右表则直接更新表
validate:没有表则直接报错
-->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 关联 ORM 映射-->
<mapping resource="com/gec/domain/..."/>
</session-factory>
</hibernate-configuration>
三、配置实体类的映射文件
配置实体类的映射文件,一个实体类对应一个映射文件。
1. 创建实体类映射文件,命名格式一般为“实体类名.hbm.xml”,配置文件一般放置与实体类同一个包下。
2. 添加配置文件的头部信息;
3. 配置实体类与数据库表的关联;将实体类与数据库的表、属性与列一一对应起来。
4. 最后检查一下hibernate主配置文件中是否有关联该实体类的配置文件。
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- package属性用于扫描包 -->
<hibernate-mapping package="com.gec.domain">
<!-- name属性对应实体类名;table属性对应表名-->
<class name="User" table="tb_user">
<!-- id标签用于配置主键 ; property标签用于配置非主键-->
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="username" column="username"></property>
<property name="password" column="password"></property>
</class>
</hibernate-mapping>
四 、使用hibernate的方法进行增删改查
配置完相应的配置文件后,就可以在测试方法中使用hibernate的方法进行增删改查了。
1. 读取主配置文件:new Configuration().configure().读取配置文件信息,并返回configuration对象,默认是读取src目录下的hibernate.cfg.xml文件。
2. 创建session工厂:configuration.buildSessionFactory().创建一个sessionFactory对象。
3. 获得session对象:sessionFactory.openSession().返回一个session对象。
4. 获得事务对象(事务对象一般用于提交事务,查询不需要提交事务,但增删改在执行完SQL后需要提交事务):session.beginTransaction().返回transaction对象。
5. 查:
session.get(Class, serializable),只能查询出一个;
使用HQL语言自定义查询条件:格式一般为 HQL = “from 实体类名 [where …]”;创建Query对象执行SQL,
Query query = session.createQuery(HQL);
query.list(),查询返回一个List集合;
query.uniqueResult(),查询返回一个结果。
6. 增:session.save(Object b);
7. 删:先查询,再删除 session.delete(Object b);
8. 改:先查询,再修改session.update(Object b),另外需要注意的是,在执行修改方法之前,对对象b设置的修改内容的代码一定要有,否则会抛出异常。
9. 最后检查增删改之后是否有提交事务:session.commit()。
@Test
public void fun1() {
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
//先查询,再修改
User user = session.get(User.class, 1);//查
user.setUsername("修改后的名字");
session.update(user);//修改
transaction.commit();
}
使用HQL语言虽然能自定义查询条件了,但仍然不够灵活,对于计数、求和、求平均等操作仍不能实现,解决的办法有两种,分别是使用criteria对象和原生SQL语言。
五、使用criteria对象的方法进行增删改查
特点在于不需要写一句SQL或HQL语句,但需要指定操作的实体类。
1. 获取session对象,与前面的步骤一样;
2. 创建criteria对象:session.createCriteria(Class c).
3. 设置查询列表项,也就是select部分,可以设置为count/avg/sum/…,或者为某几个属性列。
通过criteria.setProjection(Projections.XXX)方式设置。
4. 设置查询的限制条件,也就是where部分。
通过criteria.add(Restriction.XXX)方式设置一个或多个限制条件。
5. 使用criteria对象的list()/uniqueResult()方法执行查询。
@Test
public void fun1() {
//使用criteria进行查询
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Criteria criteria = session.createCriteria(User.class);
//设置查询列表,property设置查询显示的列,也就是select部分
criteria.setProjection(Projections.property("id"));
List<Integer> list = criteria.list();
for (Integer id : list) {
System.out.println(id);
}
//count返回的类型默认是long类型
// Long count = (Long) criteria.uniqueResult();
// System.out.println("记录数为:" + count);
Criteria criteria1 = session.createCriteria(User.class);
//设置查询的限制条件,也就是where部分
criteria1.add(Restrictions.eq("id", 2));
criteria1.add(Restrictions.eq("password", "1234"));
/*
若为分页查询,与HQL的方法一样
criteria1.setFirstResult(0);
criteria1.setMaxResults(3);
*/
// criteria1.list();
User user = (User) criteria1.uniqueResult();
System.out.println("条件查询:" + user);
}
六、使用原生SQL语言进行增删改查
1. 编写SQL语句;
2. 获取SQLQuery对象:通过session.createSQLQuery(sql)创建执行该SQL语句的SQLQuery对象。
3. 若SQL中存在占位符,则使用SQLQuery对象的setParameter(i, o)方法替换占位符。
4. 在执行查询之前,需要先设置返回类型,因为SQL语句中不像HQL那样说明了结果集返回后该由哪个实体类进行接收,所以默认是Object类型,这时候强转类型的话是会出现异常的;设置完接收的实体类之后,就可以正常的强转类型了。
5. 使用SQLQuery对象的list()/uniqueResult()方法执行查询。
@Test
public void fun2() {
//使用原生SQL进行查询
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
String sql = "select * from tb_user where id = ?";
SQLQuery sqlQuery = session.createSQLQuery(sql);
//设置查询结果的返回类型,不设置的话后面获得的结果集将不能转型
sqlQuery.addEntity(User.class);
// sqlQuery.addEntity("com.gec.domain.User");
sqlQuery.setParameter(0, 2);
// List<User> list = sqlQuery.list();
User user = (User) sqlQuery.uniqueResult();
// for (User user : list) {
// System.out.println(user);
// }
System.out.println(user);
}
七、hibernate设置表的关系
数据库表的关系分为 1:1,1:N ,N:N 三种
设置 1:N:
- 在关系为 1 的实体类中使用集合存放关系为 N 的实体类的数据;在关系为 N 的实体类中使用一个关系为 1 的实体类的对象存放实体类的数据。
- 在关系为 1 的实体类的配置文件中,使用相应的属性标签设置实体类中集合字段,以set集合为例。
<!-- name:属性名称; table:映射的表
cascade:级连操作
save-update:保存和更新时外键的记录也一起保存和更新;
delete:删除时外键的记录也一起删除;
all:上面两种方式的组合。
-->
<set name="cars" table="tb_car" cascade="all">
<!-- column:映射表的外键名-->
<key column="cid"></key>
<!-- class:存放实体类的全路径名-->
<one-to-many class="Car"></one-to-many>
</set>
- 在关系为 N 的实体类的配置文件中,使用标签 many-to-one 设置对应关系。
<!-- name:实体类属性名;column:外键名;class:对应实体类的全路径名-->
<many-to-one name="user" column="uid" class="User"></many-to-one>
- 设置完成,在执行增删改查时将遵循设置的方式执行。
设置 N:N :两张表之间的多对多关系通过一张中间表来体现。
- 在具有多对多关系的两个实体类中都创建一个集合保存数据。
- 两个实体类的配置文件中,都使用相应的集合标签设置实体类中集合字段,以set标签为例。
<!-- 多对多关系设置:
name:属性名称; table:中间表名; cascade:级连操作
inverse:true表示将当前自己的 外键维护权利 交给另一方维护
-->
<set name="roles" table="tb_user_role" cascade="save-update" inverse="true">
<!-- column:当前表在中间表中的外键名 -->
<key column="uid"></key>
<!-- column:另一张表在中间表中的外键名
class:另一张表对应实体类的全路径名 -->
<many-to-many column="rid" class="Role"></many-to-many>
</set>
- 可以选择级连操作。
- 在其中一个配置文件的集合标签中设置 inverse 属性为true,表示将自己的外键维护权利交给另一方维护,若不设置,会因为两张表同时维护中间表的主键而报错。