hibernate之helloworld

hibernate之helloworld

一、helloworld

  添加hibernate的依赖和数据库连接的依赖

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>4.2.4.Final</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.44</version>
</dependency>

  在 resource 目录下创建 hibernate.cfg.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="connection.username">root</property>
        <property name="connection.password">root</property>
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql:///hibernate</property>

        <!-- hibernate 所使用的数据库方言 -->
        <property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>

        <!-- 执行操作时是否在控制台打印 SQL -->
        <property name="show_sql">true</property>

        <!-- 表生成策略 -->
        <property name="hbm2ddl.auto">update</property>

        <!-- 指定关联的 .hbm.xml 文件 -->
        <mapping resource="News.hbm.xml" />

    </session-factory>
</hibernate-configuration>

  数据库方言:

数据库类型        	        Hibernate sql方言
DB2                	        org.hibernate.dialect.DB2Dialect
DB2 AS/400        	        org.hibernate.dialect.DB2400Dialect
DB2 OS390	                org.hibernate.dialect.DB2390Dialect
PostgreSQL 8.1	                org.hibernate.dialect.PostgreSQL81Dialect
PostgreSQL 8.2 and later	org.hibernate.dialect.PostgreSQL82Dialect
MySQL5	                        org.hibernate.dialect.MySQL5Dialect
MySQL5 with InnoDB	        org.hibernate.dialect.MySQL5InnoDBDialect
MySQL with MyISAM	        org.hibernate.dialect.MySQLMyISAMDialect
Oracle (any version)	        org.hibernate.dialect.OracleDialect
Oracle 9i	                org.hibernate.dialect.Oracle9iDialect
Oracle 10g	                org.hibernate.dialect.Oracle10gDialect
Oracle 11g	                org.hibernate.dialect.Oracle10gDialect
Sybase ASE 15.5	                org.hibernate.dialect.SybaseASE15Dialect
Sybase ASE 15.7	                org.hibernate.dialect.SybaseASE157Dialect
Sybase Anywhere	                org.hibernate.dialect.SybaseAnywhereDialect
Microsoft SQL Server 2000	org.hibernate.dialect.SQLServerDialect
Microsoft SQL Server 2005	org.hibernate.dialect.SQLServer2005Dialect
Microsoft SQL Server 2008	org.hibernate.dialect.SQLServer2008Dialect
SAP DB	                        org.hibernate.dialect.SAPDBDialect
Informix	                org.hibernate.dialect.InformixDialect
HypersonicSQL	                org.hibernate.dialect.HSQLDialect
H2 Database	                org.hibernate.dialect.H2Dialect
Ingres	                        org.hibernate.dialect.IngresDialect
Progress	                org.hibernate.dialect.ProgressDialect
Mckoi SQL	                org.hibernate.dialect.MckoiDialect
Interbase	                org.hibernate.dialect.InterbaseDialect
Pointbase	                org.hibernate.dialect.PointbaseDialect
FrontBase	                org.hibernate.dialect.FrontbaseDialect
Firebird	                org.hibernate.dialect.FirebirdDialect

  实体

public class News {	
	private Integer id;
	private String title;
	private String content;
......
}

  创建 News.hbm.xml 该文件将实体的属性映射到数据表,从而完成数据库创表和和保存对象的操作

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.hw.entity">
    <class name="News" table="NEWS" dynamic-insert="true">
        <!--dynamic-insert="true" 时表示插入对象时空的字段不插入 -->
        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="native" />
            <!-- 指定主键的生成策略, native: 使用数据库本地方式 -->
        </id>
        <property name="title" not-null="true"
            length="50" type="java.lang.String" column="TITLE">
        </property>        
        <property name="content">
            <column name="CONTENT" sql-type="text"></column>
          <!--数据库改字段的名字和类型-->
        </property>
    </class>
</hibernate-mapping>

  执行会自动创表,插入数据

// 1.创建SessionFactory
Configuration configuration=new Configuration().configure();
SessionFactory sessionFactory=configuration.buildSessionFactory();
// 2. 获得一个 Session 对象
Session session = sessionFactory.openSession();
// 3. 开启事务
Transaction transaction = session.beginTransaction();
// 4. 执行保存操作
News news = new News("标题","正文");
session.save(news);		
// 5. 提交事务
transaction.commit();
// 6. 关闭 Session
session.close();		
// 7. 关闭 SessionFactory 对象
sessionFactory.close();
System.out.println(news);

  主键生成策略
  increment:代理主键,适合于所有数据库,由hibernate维护主键自增,和底层数据库无关,但是不适合于2个或以上hibernate进程。

identity:代理主键,适合于Mysql或ms sql server等支持自增的dbms,主键值不由hibernate维护。
sequence:代理主键,适合于oracle等支持序列的dbms,主键值不由hibernate维护,由序列产生。
native:代理主键,根据底层数据库的具体特性选择适合的主键生成策略,如果是mysql或sqlserver,选择identity,如果是oracle,选择sequence。
hilo:代理主键,hibernate把特定表的字段作为hign值,生成主键值
uuid.hex:代理主键,hibernate采用uuid 128位算法生成基于字符串的主键值
assigned:适合于由java指定主键,一般使用uuid,保存对象时如果主键为空会抛异常。

  表生成策略
–create : 会根据 .hbm.xml 文件来生成数据表,但是每次运行都会删除上一次的表,重新生成表,哪怕二次没有任何改变

–create-drop : 会根据.hbm.xml文件生成表,但是SessionFactory一关闭,表就自动删除

–update : 最常用的属性值,也会根据.hbm.xml文件生成表,但若.hbm.xml 文件和数据库中对应的数据表的表结构不同,Hiberante 将更新数据表结构,但不会删除已有的行和列

–validate : 会和数据库中的表进行比较,若.hbm.xml文件中的列在数据表中不存在,则抛出异常

数据库字段类型

hibernate的映射关系如下:

Hibernate 映射类型           java 类型                                标准 sql 类型
integer                      int or Integer                           INTEGER 
long                         long or java.lang.Long                   BIGINT  
short                        short or java.lang.Short                 SMALLINT  
float                        float or java.lang.Float                 FLOAT              
double                       double or java.lang.Double               DOUBLE  
big_decimal                  java.math.BigDecimal                     NUMERIC  
character                    java.lang.String                         CHAR(1)  
string                       java.lang.String                         VARCHAR 
byte                         byte or java.lang.Byte                   TINYINT 
boolean                      boolean or java.lang.Boolean             BIT  
yes_no                       boolean or java.lang.Boolean             CHAR(1)('Y' or 'N')  
true_false                   boolean or java.lang.Boolean             CHAR(1)('Y' or 'N') 
date                         java.util.Date or java.sql.Date          DATE  
time                         java.util.Date or java.sql.Time          TIME  
timestamp                    java.util.Date or java.sql.TimeStamp     TIMESTAMP  
calendar                     java.util.Calendar                       TIMESTAMP  
calendar_date                java.util.Calendar                       DATE  
binary                       byte[]                                   VARBINARY( or BLOB)  
text                         java.lang.String                         CLOB  
serializable                 java.io.Serializable                     VARBINARY (or BLOB)
clob                         java.sql.Clob                            CLOB  
blob                         java.sql.Blob                            BLOB  
class                        java.lang.Class                          VARCHAR  
locale                       java.util.Locale                         VARCHAR  
timezone                     java.util.TimeZone                       VARCHAR  
currency                     java.util.Currency                       VARCHAR

二、Session 概述

  为了方便我们使用junit的测试前后注解

private SessionFactory sessionFactory;
private Session session;
private Transaction transaction;

@Before
public void init() {
    Configuration configuration=new Configuration().configure();
    sessionFactory=configuration.buildSessionFactory();
    session = sessionFactory.openSession();
    transaction = session.beginTransaction();
}

@After
public void destroy() {
    transaction.commit();
    session.close();
    sessionFactory.close();
}

Session 接口是Hibernate向应用程序提供的操纵数据库的最主要的接口,它提供了基本的保存,更新,删除和加载Java 对象的方法.

Session 具有一个缓存(一级缓存), 位于缓存中的对象称为持久化对象, 它和数据库中的相关记录对应. Session 能够在某些时间点, 按照缓存中对象的变化来执行相关的 SQL 语句, 来同步更新数据库, 这一过程被称为刷新缓存(flush)

站在持久化的角度, Hibernate 把对象分为 4 种状态:
  1.持久化状态
  2.临时状态
  3.游离状态
  4.删除状态
Session 的特定方法能使对象从一个状态转换到另一个状态.

一级缓存(基于session的缓存)

一级缓存hibernate默认开启

一级缓存表示session不关闭的情况下,该session保存的对象多次查询从缓存中获取

News news = (News) session.get(News.class, 1);
System.out.println(news);

News news2 = (News) session.get(News.class, 1);
System.out.println(news2);

如上:当第二次查询时不在去数据库里面查询,而是从session里面获取,共发一次sql

除非中间刷新缓存session.flush();关闭session 和session.clear();

session.refresh(news);与session.flush();的区别

refresh 强制从数据库查询该对象 ,获取数据库最新纪录后设置对象的属性

flush 强制将修改过后的对象刷新到数据库,并清除一级缓存

对象的四个状态

临时状态(Transient): 在使用代理主键的情况下, OID 通常为 null 不处于 Session 的缓存中 在数据库中没有对应的记录

持久化状态 (也叫”托管”)(Persist): OID 不为 null 位于 Session 缓存中 若在数据库中已经有和其对应的记录, 持久化对象和数据库中的相关记录对应 Session 在 flush 缓存时, 会根据持久化对象的属性变化, 来同步更新数据库 在同一个 Session 实例的缓存中, 数据库表中的每条记录只对应唯一的持久化对象

删除状态(Removed) 在数据库中没有和其 OID 对应的记录 不再处于 Session 缓存中 一般情况下, 应用程序不该再使用被删除的对象

游离状态(也叫”脱管”) (Detached): OID 不为 null 不再处于 Session 缓存中 一般情况需下, 游离对象是由持久化对象转变过来的, 因此在数据库中可能还存在与它对应的记录

三、对象的基本操作

  持久化(保存)

News news = new News("Java", "SUN", new Date());
session.save(news);

Session 的 save() 方法使一个临时对象转变为持久化对象

把对象加入到 Session 缓存中, 使它进入持久化状态 选用映射文件指定的标识符生成器, 为持久化对象分配唯一的 OID. 计划执行一条 insert 语句

在 flush 缓存的时候 Hibernate 通过持久化对象的 OID 来维持它和数据库相关记录的对应关系.

当 News 对象处于持久化状态时, 不允许程序随意修改它的 ID

persist() 和 save() 区别:

当对一个 OID 不为 Null 的对象执行 save() 方法时, 会把该对象以一个新的 OID 保存到数据库中; 但执行 persist() 方法时会抛出一个异常.

对象查询(单个)

News news = (News) session.get(News.class, 1);
News news = (News) session.load(News.class, 1);

get 与 load:

  1. 执行 get 方法: 会立即加载对象. 执行 load 方法, 若不适用该对象, 则不会立即执行查询操作, 而返回一个代理对象,get 是 立即检索, load 是延迟检索.

  2. load 方法可能会抛出 LazyInitializationException 异常: 在需要初始化 代理对象之前已经关闭了 Session

  3. 若数据表中没有对应的记录, Session 也没有被关闭. get 返回 null load 若不使用该对象的任何属性, 没问题; 若需要初始化了,抛出异常.

延迟加载指的就是,当完成load操作之后,并不会马上发出sql语句,只有在使用到该对象时才会发出sql 当完成load之后,u其实是一个代理对象,这个代理对象中仅仅只有一个id的值

修改单个对象

News news = (News) session.get(News.class, 1);
news.setAuthor("SUN");
session.update(news);

update:

  1. 若更新一个持久化对象, 不需要显示的调用 update 方法. 因为在调用 Transaction 的 commit() 方法时, 会先执行 session 的 flush 方法. (如上面的第三句没有必要)

  2. 更新一个游离对象, 需要显式的调用 session 的 update 方法. 可以把一个游离对象 变为持久化对象 需要注意的:

  3. 无论要更新的游离对象和数据表的记录是否一致, 都会发送 UPDATE 语句. 如何能让 updat 方法不再盲目的出发 update 语句呢 ? 在 .hbm.xml 文件的 class 节点设置 select-before-update=true (默认为 false). 但通常不需要设置该属性.

  4. 若数据表中没有对应的记录, 但还调用了 update 方法, 会抛出异常

  5. 当 update() 方法关联一个游离对象时, 如果在 Session 的缓存中已经存在相同 OID 的持久化对象, 会抛出异常. 因为在 Session 缓存中 不能有两个 OID 相同的对象!

Session 的saveOrUpdate()方法同时包含了 save() 与 update() 方法的功能。id为空时save ,不为空时update

删除对象

News news = (News) session.get(News.class, 163840);
session.delete(news);

delete: 执行删除操作.

只要 OID 和数据表中一条记录对应, 就会准备执行 delete 操作 若 OID 在数据表中没有对应的记录, 则抛出异常

可以通过设置 hibernate 配置文件 hibernate.use_identifier_rollback 为 true, 使删除对象后, 把其 OID 置为 null

舍弃修改

News news1 = (News) session.get(News.class, 1);
News news2 = (News) session.get(News.class, 2);
news1.setTitle("AA");
news2.setTitle("BB");
session.evict(news1);

evict: 从 session 缓存中把指定的持久化对象移除 * 使news1的修改不影响数据库

上一篇:linux系统中vi命令操作大全


下一篇:Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: subnet is not mapped