hibernate
从上图中,我们可以看出Hibernate六大核心接口,两个主要配置文件,以及他们直接的关系。Hibernate的所有内容都在这了。那我们从上到下简单的认识一下,每个接口进行一句话总结。
1、Configuration接口:负责配置并启动Hibernate
2、SessionFactory接口:负责初始化Hibernate
3、Session接口:负责持久化对象的CRUD操作
4、Transaction接口:负责事务
5、Query接口和Criteria接口:负责执行各种数据库查询
注意:Configuration实例是一个启动期间的对象,一旦SessionFactory创建完成它就被丢弃了。
优点:
1、更加对象化
以对象化的思维操作数据库,我们只需要操作对象就可以了,开发更加对象化。
2、移植性
因为Hibernate做了持久层的封装,你就不知道数据库,你写的所有的代码都具有可复用性。
3、Hibernate是一个没有侵入性的框架,没有侵入性的框架我们称为轻量级框架。
对比Struts的Action和ActionForm,都需要继承,离不开Struts。Hibernate不需要继承任何类,不需要实现任何接口。这样的对象叫POJO对象。
4、Hibernate代码测试方便。
5、提高效率,提高生产力。
缺点:
1、使用数据库特性的语句,将很难调优
2、对大批量数据更新存在问题
3、系统中存在大量的攻击查询功能
步骤
1.在src目录下创建hibernate.cfg.xml配置文件
PS:文件的名字不能改!
<?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> <!-- configure the database setting --> <property name="connection.username">root</property> <property name="connection.password">1234</property> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://localhost:3306/test</property> <!-- configure the hibernate setting --> <!-- transaction is supported by org.hibernate.dialect.MySQL5InnoDBDialect --> <property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property> <!-- show sql in the console --> <property name="show_sql">true</property> <!-- create and update the database automaticlly --> <property name="hbm2ddl.auto">update</property> <!-- javax.persistence.validation.mode默认情况下是auto的,就是说如果不设置的话它是会自动去你的classpath下面找一个 bean-validation**包,但是找不到,所以beanvalitionFactory错误 --> <property name="javax.persistence.validation.mode">none</property> </session-factory> </hibernate-configuration>
2.编写实体类(与db对应的getset方法)
3.编写Person.hbm.xml实体类配置文件(类名.hbm.xml)
<?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"> <!-- Mapping file autogenerated by MyEclipse Persistence Tools --> <hibernate-mapping package="test.Hibernate.model"> <class name="Person" table="person"> <id column="id" name="id" type="int"> <generator class="native"></generator> </id> <property name="name" column="name" length="50" type="string"></property> <set name="address" table="address"> <key column="personId"></key> <element column="address" type="string" length="50"></element> </set> </class> </hibernate-mapping>
4.在hibernate.cfg.xml中加入映射信息
<mapping resource="test/Hibernate/model/Person.hbm.xml" />
5.主键生成策略
identity:使用数据库的自动增长策略,不是所有数据库都支持,比如oracle就不支持。
sequence:在 DB2,PostgreSQL,Oracle,SAP DB,McKoi 中使用序列(sequence)在使用Oracle数据库时可以使用这一个。
hilo:使用高低位算法生成主键值。只需要一张额外表,所有的数据都支持。
native:根据底层数据库的能力选择 identity、sequence 或者 hilo中的一个。
assigned:手工指定主键值。
uuid:由Hibernate自动生成UUID并指定为主键值。
映射关系
一、一对一
<?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"> <!-- Mapping file autogenerated by MyEclipse Persistence Tools --> <hibernate-mapping package="test.Hibernate.model"> <class name="User" table="user"> <id name="id" type="int" column="id"> <generator class="native"></generator> </id> <property name="name" type="string" column="name"/> <set name="address" table="address"> <key column="userId"></key> <element column="address" type="string"></element> </set> <one-to-one name="idCard" class="IdCard" cascade="all"></one-to-one> </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"> <!-- Mapping file autogenerated by MyEclipse Persistence Tools --> <hibernate-mapping package="test.Hibernate.model"> <class name="IdCard" table="idCard"> <id name="id" type="int" column="id"> <generator class="foreign"> <param name="property">user</param> </generator> </id> <property name="number" type="string" column="number"/> <one-to-one name="user" class="User" constrained="true"></one-to-one> </class> </hibernate-mapping>
2.一对多,多对一(以Father和Children为例)
<?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 package="test.Hibernate.model"> <class name="Father" table="father"> <id name="id" type="int" column="id" > <generator class="native"></generator> </id> <property name="name" type="string" column="name"/> <set name="children" cascade="all"> <key column="fatherId"></key> <one-to-many class="Children"/> </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 package="test.Hibernate.model"> <class name="Children" table="children"> <id name="id" type="int" column="id" > <generator class="native"></generator> </id> <property name="name" type="string" column="name"/> <many-to-one name="father" class="Father" column="fatherId"></many-to-one> </class> </hibernate-mapping>
3.多对多(以Student和Teacher为例)
<?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"> <!-- Mapping file autogenerated by MyEclipse Persistence Tools --> <hibernate-mapping package="test.Hibernate.model"> <class name="Student" table="student"> <id name="id" type="int" column="id"> <generator class="native"></generator> </id> <property name="name" type="string" column="name" length="20"/> <set name="teachers" table="student_teacher" inverse="false" > <key column="studentId"></key> <many-to-many class="Teacher" column="teacherId"></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"> <!-- Mapping file autogenerated by MyEclipse Persistence Tools --> <hibernate-mapping package="test.Hibernate.model"> <class name="Teacher" table="teacher"> <id name="id" type="int" column="id"> <generator class="native"></generator> </id> <property name="name" column="name" type="string" length="20"></property> <set name="students" table="student_teacher" inverse="true" cascade="all"> <key column="teacherId"></key> <many-to-many class="Student" column="studentId"></many-to-many> </set> </class> </hibernate-mapping>
1.inverse=false在一对多删除时是把孩子的外键设置为null,然后删除父亲,孩子不删除,而casecade=all在一对多删除时是把孩子的外键设置为null,然后删除父亲,然后再删除孩子
2.many to many的时候由一方维护,所以一方要设置inverse=false,但是inverse=true的另一方直接删除会出错,这个时候可以用casecade完成级联删除
3.inverse=false只用于set等集合属性,在one to one关系中可以用casecade完成级联删除
hibernate的对象状态
1.临时态:db没有,也没有被session管理;
2.游离态:db有,没有被session管理
3.持久态:db有,有被session管理(对象状态发生变化,hibernate会自动更新,与内存完全一致)
修改(session.saveorupdate()):
持久态----》直接set
游离态----》session.update()(如果在xml中设置update=false,将永远不能更新)
查询(get/load):
根据主键查询:seesion.get(class,id) session.load(类型,参数)
默认懒加载
get未找到数据后返回null,load未找到数据后报ObjectNotFound异常,所以一般情况下使用get
String hql=new StringBuffer.append("from Person").toString(); Query q=session.createQuery(hql); q.list()//得到所有的结果
Query query = session.createQuery(hql) // .setParameter(0, 1) // .setParameter(1, 3);
// query.setFirstResult(0); // query.setMaxResults(10);
@Test public void DML(){ Session session = SessionFactory.getSession(); Transaction tr = session.beginTransaction(); //----------------------------------------- User u = (User)session.get(User.class, 11); String sql = "update User set name=? where id>?"; int result = session.createQuery(sql) .setParameter(0, "updated") .setParameter(1, 10) .executeUpdate(); System.out.println("count of update:"+result); //the object's status in session was not updated when the object in database have been changed,so if you want //to get the updated object in session,you should use method "refresh". session.refresh(u); System.out.println(u); //----------------------------------------- tr.commit(); SessionFactory.closeSession(); }
query.list()返回一个list
query.uniqueResult()最多一条记录,直接返回一个
setFirstResult()从第几个开始(下表从0开始)
setMaxResult()最多几个
根据姓名查询:
hql = "from Person p where p.name =?或者p.anme=:name"
.setString(0,name)或setstring("name",name)
根据id修改姓名:
先根据id查,再改
取消懒加载:lazy="false" 还需要fetch="join"(使用join查询)