第一节 Hibernate配置文件详解
1.1 hibernate.cfg.xml详解
1. 配置数据库连接的4个参数
<!-- 1.配置数据库连接的4个参数 -->
<!-- mysql8以上的jar包要加上cj,com.msyql.cj.jdbc.Driver -->
<!-- 要是用的是5,8以下,无需添加 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- ///代表是本地的默认localhost:3306可以省略,如果是在别的服务器要写://ip:端口号/ -->
<property name="hibernate.connection.url">jdbc:mysql:///hibernate_day1</property>
<!-- 数据库用户名 -->
<property name="hibernate.connection.username">root</property>
<!-- 数据库密码 -->
<property name="hibernate.connection.password">root</property>
2. sql语句显示与sql格式化语句
<!-- 2.是否显示sql语句 -->
<property name="show_sql">true</property>
<!-- 3.是否格式化sql语句 -->
<property name="format_sql">true</property>
- 格式化sql简洁、美观、易于阅读,适合开发时使用
- 不显示sql或不格式化sql,可在后期开发完成后使用
3. 自动提交事务与session本地线程绑定
- day01中3.3 Session会话与3.4 Transaction事务已详解:https://blog.csdn.net/qq_43414199/article/details/108162894.
<!-- 4.是否自动提交事务:针对insert有效,针对delete无效 -->
<property name="hibernate.connection.autocommit">true</property>
<!-- 5.开启与当前线程绑定session的功能
ThreadLocal<Connection>
ThreadLocal<ActionContext>
ThreadLocal<Session>
-->
<property name="hibernate.current_session_context_class">thread</property>
4. 配置映射文件与数据库表的关系
<!-- 6.hibernate.hbm2ddl.auto
ddl数据库定义语言
配置映射文件与数据库表的关系
update:如果数据库有没表,自动帮你创表【常用】
如果hbm与数据表不一样,会更新【例如在User实体类中添加一个字段,程序执行,数据库会自动帮你更新表结构】
create:每次启动hibernate都帮你创建表【所以插入数据后再执行程序,会覆盖刷新】
create-drop,每次启动hibernate都帮你创建表,执行完后删除表【要你何用,用完就删,可以测试时使用,哈哈】
validate:检验hbm文件,如果与数据库的字段不一致,就抛出异常【不错不错】
-->
<property name="hibernate.hbm2ddl.auto">update</property>
- 这里就演示一下添加新字段,运行程序后,数据库表结构会自动刷新
- 在User.java中添加一个字段gender,表示性别,提供getter、setter
- 在User.hbm.xml中添加gender
- 程序运行前
- 随便执行一个Demo12.java,更新一下密码,它会顺便更新表结构
package com.it.hibernate.test;
import com.it.hibernate.domain.User;
import com.it.hibernate.uitls.HibernateUtils;
import org.hibernate.Session;
import org.junit.Test;
public class Demo12 {
@Test
public void test12(){
//获取session对象
Session session = HibernateUtils.openSession();
try {
//开启事务
session.getTransaction().begin();
//session操作
User user = (User) session.get(User.class, 24);
user.setPassword("456");
session.update(user);
//提交事务
session.getTransaction().commit();
} catch (Exception e){
//打印异常信息
e.printStackTrace();
//回滚
session.getTransaction().rollback();
}
//关闭会话
session.close();
}
}
5. hibernate.dialect 数据库方言
<!-- 7.hibernate.dialect:数据库方言
每个数据库都有自己的方言,MySQL有MySQL的方式,oracle有oracle的方式
因为一个意思有不同的表达方式,就如同不同地方有不同的方言
MySQL与oracle的分页语句不同:
mysql:分页使用limit
oracle:分页使用rownum
可以查看MySQLDialect和OracleDialect的getLimitString
-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<!--<property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>-->
- MySQLDialect的getLimitString源码:
- OracleDialect的getLimitString源码:
6. 配置JavaBean与表的映射文件【常用】
- 更多配置方法见day01
<!-- 8.配置JavaBean与表的映射文件【常用】 -->
<mapping resource="com/it/hibernate/domain/User.hbm.xml" />
附 hibernate.cfg.xml
<!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>
<!-- 1.配置数据库连接的4个参数 -->
<property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///hibernate_day1</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<!-- 2.是否显示sql语句 -->
<property name="show_sql">true</property>
<!-- 3.是否格式化sql语句 -->
<property name="format_sql">true</property>
<!-- 4.是否自动提交事务:针对insert有效,针对delete无效 -->
<property name="hibernate.connection.autocommit">true</property>
<!-- 5.开启与当前线程绑定session的功能
ThreadLocal<Connection>
ThreadLocal<ActionContext>
ThreadLocal<Session>
-->
<property name="hibernate.current_session_context_class">thread</property>
<!-- 6.hibernate.hbm2ddl.auto
ddl数据库定义语言
配置映射文件与数据库表的关系
update:如果数据库有没表,自动帮你创表【常用】
如果hbm与数据表不一样,会更新【例如在User实体类中添加一个字段,程序执行,数据库会自动帮你更新表结构】
create:每次启动hibernate都帮你创建表【所以插入数据后再执行程序,会覆盖刷新】
create-drop,每次启动hibernate都帮你创建表,执行完后删除表【要你何用,用完就删,可以测试时使用,哈哈】
validate:检验hbm文件,如果与数据库的字段不一致,就抛出异常【还好】
-->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 7.hibernate.dialect:数据库方言
每个数据库都有自己的方言,MySQL有MySQL的方式,oracle有oracle的方式
因为一个意思有不同的表达方式,就如同不同地方有不同的方言
MySQL与oracle的分页语句不同:
mysql:分页使用limit
oracle:分页使用rownum
可以查看MySQLDialect和OracleDialect的getLimitString
-->
<property name="hibernate.dialect">org.hibernate.dialect.OracleDialect</property>
<!--<property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>-->
<!-- 8.配置JavaBean与表的映射文件【常用】 -->
<mapping resource="com/it/hibernate/domain/User.hbm.xml" />
</session-factory>
</hibernate-configuration>
1.2 实体.hbm.xml 映射文件详解
- 昨天创建的是一个javaweb项目,今天直接使用idea创建一个hibernate项目
- 原来WEB-INF下lib里的jar,将放在这
1. 实体类entity(model)的编写规则
- 我们在使用Hibernate时,书写了一个User类,这个类我们称为JavaBean
- JavaBean可以简单的理解成提供私有属性,并提供私有属性的get/set方法
- POJO(Plain Ordinary Java Object)简单的Java对象,实际就是普通JavaBeans
- 我们也称为模型,在Hibernate中,又称这种类为实体,因为这个实体是与表相关联的
- 编写规则:
-
必须要提供一个无参数 public访问控制符的构造器
-
必须要提供一个标识属性,映射数据表主键字段,提供id
-
所有属性必须要提供public访问控制符的 set/get 方法(javaBean)
-
标识属性应尽量使用基本数据类型的包装类型
hibernate是面向对象的,它希望它的数据类型都是对象。可以new出来
- 不要用final修饰实体 (将无法生成代理对象进行优化)
-
2. 持久化对象的唯一标识 OID
- Java按地址区分同一个类的不同对象
- 关系型数据库用主键区分同一条记录
- Hibernate使用OID来建立内存中的对象和数据库中记录的对应关系结论: 对象的OID和数据库表的主键对应。
- 为保证OID的唯一性,应该让Hibernate来为OID赋值
3. 区分自然主键和代理主键
- 主键需要具备:不为空/不能重复/不能改变
- 自然主键:在业务中,某个属性符合主键的三个要求,那么该属性可以作为主键列。【例如:登录名可以是自然主键】
- 代理主键:在业务中,不存在符合以上3个条件的属性,那么就增加一个没有意义的列,作为主键。
例如:如果不把username当成主键(username可以重复),就增加一个没有意义的id列来当代理主键。
扫描二维码关注公众号,回复:
12014618 查看本文章
4. 基本数据与包装类型
- 基本数据类型和包装类型对应hibernate的映射类型相同
- 基本类型无法表达null,数字类型(int)的默认值为0。
- 包装类默认值是null,当对于默认值有业务意义的时候需要使用包装类。
5. SQL、Hibernate和对象类型对应
Java数据类型 | Hibernate数据类型 | 标准SQL数据类型(PS:对于不同的DB可能有所差异) |
byte、java.lang.Byte | byte | TINYINT |
short、java.lang.Short | short | SMALLINT |
int、java.lang.Integer | integer | INGEGER |
long、java.lang.Long | long | BIGINT |
float、java.lang.Float | float | FLOAT |
double、java.lang.Double | double | DOUBLE |
java.math.BigDecimal | big_decimal | NUMERIC |
char、java.lang.Character | character | CHAR(1) |
boolean、java.lang.Boolean | boolean | BIT |
java.lang.String | string | VARCHAR |
boolean、java.lang.Boolean | yes_no | CHAR(1)('Y'或'N') |
boolean、java.lang.Boolean | true_false | CHAR(1)('Y'或'N') |
java.util.Date、java.sql.Date | date | DATE |
java.util.Date、java.sql.Time | time | TIME |
java.util.Date、java.sql.Timestamp | timestamp | TIMESTAMP |
java.util.Calendar | calendar | TIMESTAMP |
java.util.Calendar | calendar_date | DATE |
byte[] | binary | VARBINARY、BLOB |
java.lang.String | text | CLOB |
java.io.Serializable | serializable | VARBINARY、BLOB |
java.sql.Clob | clob | CLOB |
java.sql.Blob B | blob | BLO |
java.lang.Class | class | VARCHAR |
java.util.Locale | locale | VARCHAR |
java.util.TimeZone | timezone | VARCHAR |
java.util.Currency | currency | VARCHAR |
6. 主键的生成策略【重要】
- User.hbm.xml
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<!-- name:模型的全名称-->
<class name="com.it.hibernate.domain.User" table="t_user">
<!-- name:模型属性名 -->
<id name="uid" column="id">
<!-- generator:id的生成策略
increment:也会自动增长id,但是它的这种增长是hibernate自己实现的
执行select max(id)查询,但是这种会有线程并发问题(如果2个数据同时插入,后面的数据插不进去)
sequence:一般在oracle数据库使用
hilo:hibernate:自己实现的id规则【一般不用,不学】
native:【经常常用】【这个自动增长的实现是mysql实现的,mysql它会记录上一条记录的id值然后加1】
如果是mysql数据库,id会自动增长
如果是oracle数据库,也会自动增长,一般是与sequence相关
uuid:【经常常用】一个长字符串,需要把模型的id改成字符串
保存的时候,不用自己设置id,hibernate会设置id
assigned:【经常常用】需要手动设置id属性
-->
<generator class="uuid"></generator>
</id>
<!-- 如果模型的属性和数据库的列名一样,就不用写column -->
<property name="username"></property>
<property name="password"></property>
<property name="gender"></property>
</class>
</hibernate-mapping>
- 这里测试一下uuid的效果
-
把uid设为String,重新写一下get/set
-
删除数据库中的t_user表,由于之前的id是integer类型,现在要插入string类型的数据会报错。
-
User.hbm.xml中设置uuid
- 随便写一个数据,保存一下
- Demo1.java
package com.it.hibernate.test;
import com.it.hibernate.domain.User;
import com.it.hibernate.uitls.HibernateUtils;
import org.hibernate.Session;
import org.junit.Test;
public class Demo1 {
@Test
public void test1(){
Session session = HibernateUtils.openSession();
session.getTransaction().begin();
User user = new User("shu","123");
session.save(user);
session.getTransaction().commit();
session.close();
}
}
- 发现hibernate会自己设置id
- 再测试一下assigned的效果
- 更改User.hbm.xml中的generator class为assigned
- 直接运行会报错,因为assigned要我们自己手动设置id
- 修改Demo1中的代码,自己设置id(随机一个id,再转换成字符串)
- 这样生成的id里面有-,可以使用replace去掉-
7. 普通属性(动态插入与动态更新)
动态插入
- class标签的dynamic-insert=“true” 是否动态生成插入语句
- 【如果属性字段为空,插入语句就不会显示这些字段】
- 设置前:我只修改了username和password,gender为null,却也跟着显示插入了
- 设置后运行:只针对要修改的字段进行插入显示
动态更新
- class标签的dynamic-update=“true” 与insert类似
- 设置前:我只设置了password,它却显示还设置了username和gender
- 设置后:只会显示我要设置的字段
没有改的字段没有必要显示和再设置,也没有必要在sql语句中出现。
8. type的使用
- 默认生成的数据库表的字段长度比较大,可以限制一下
注意:它将在创建表的时候改变字段默认的长度,设置成我们想要的长度,所以要删除原有的表。
- 设置后,运行一下:
- 添加一个日期字段
- 我们设置的是timestamp时间戳,它却帮我们转成了datetime…真好…
- 要使用时间戳,可以用long类型
- OK
- hibernate的long类型对应的是bigint
- 查阅上面5提供的表格也可以知道