Hibernate关系映射和HQL

 

1.单表映射:a.public class User { private Integer id;   
private String name; get/set}



b.xml: <class name="User" table="user">
 <id name="id" column="id" type="integer">// 配置主键的生成方式
<generator class="identity"></generator>    </id>
        <property name="name" column="name" type="string"></property> </class>


c. hibernate.cfg.xml
配置相应数据库和映射, show_sql=true;使console的sql语句可见

 

d.
采取junit进行测试:一般通过junit的setUp方法初始化,通过tearDown释放资源,自动加载

public class Client extends TestCase { protected Session session;
    public Client(String name) {        super(name);    }
    protected void setUp() throws Exception {
Configuration config=new Configuration().configure();// 创建Hibernate配置管理类,默认加载cfg.xml,若改名则用configure(new File(“src/hib.cfg.xml”));加上路径
SessionFactory sessionFactory =config.buildSessionFactory();
session = sessionFactory.openSession(); } // 是application和Hibernate交互接口
   


protected void tearDown() throws Exception {if(session!=null) session.close();}
    public void testCreate(){User user=new User();user.setName("hello");// 自动加载
    Transaction tr=null;// 改变数据库数据的操作都要开启一个事物
    try{    tr=session.beginTransaction(); session.save(user); tr.commit();    }
catch(HibernateException e) {       // 将自由状态变成持久状态
e.printStackTrace();   }    if(tr!=null) tr.rollback(); }
    public void testRetrieve(){
        User user=(User)session.get(User.class, 122);// 得到xml中的主键对应的对象
        assertEquals("hello", user.getName());}// 使用断言精确判断,防止空格等因素


public static Test suite(){ //junit
的静态测试方法
        TestSuite ts=new TestSuite();     Client cl=new Client("testCreate");
        ts.addTest(cl);     return ts; } }
e.session 的load和get方法的区别:1.对象存在时,load返回实体代理类类型,get返回实体类
                                2 .对象不存在时:load抛出异常,get返回null(用于判断)

 


f.
实体对象的生命周期
 1 .Transient自由状态:与Hibernate和数据库没有任何关系
 2 .Persistent持久状态:纳入了Hibernate的Session实体对象管理的容器,session会复制实体对象的引用 进行脏数据检查, 实体对象任何状态的改变最终都会同步到数据库。例如:Transaction trx=null;
    trx=session.beginTransaction(); User user=(User)session.load(User.class, 1);
    user.setName("nihao");      trx.commit();
// session.update(user); 就不需要了
 3 .Detached游离状态:(session.close()),与Hibernate和数据库没有任何关系,但是实体对象对应数据库的一条纪录。如: trx=session.beginTransaction();
User user= new User();   user.setId(61); 只要一个主键与数据库唯一标识
     session.delete(user);// 进行脏数据检查 trx.commit(); // 真正执行


2
.Generator的主键产生方式:
   a. <generator class="assigned"></generator> 由应用逻辑产生:***.setId(number);
   b.hilo: 通过hi/lo(hign/low)算法产生
   c.seqhilo: 适合oracle没有自动增长只有序列,主键历史状态保存在sequence中
   d.increment: 按照数值顺序增长,由Hibernate维护,效率很高
   e.identity: 采用数据库提供的主键生成机制,并发性不好
   f.sequence: 支持oracle这种数据库
   g.native: 根据数据库适配器自动采用identity,hilo,sequence中的一种
   h.uuid: 由Hibernate基于128位唯一算法生成32位字符串作为主键,适合所有数据库,并发好
   i:foreign: 使用外部表的字段作为主键




3.
一对一通过主键关联(one to one)(数据库中将两个表id为主键并建立外联,只一表自动增长)
 a. public class User1 {   private Integer id; private String name;
     private Passport passport; ...getter/setter} // 将passport最为成员属性
 b. public class Passport { private Integer id; private String serial;
    private User1 user; ...getter/setter}   // 将user作为成员属性
 c. <hibernate-mapping package="OneToOne"> <class name="User1" table="user1">
    <id name="id" column="id" type="integer"> <generator class="identity"/></id>
     <property name="name" column="name"></property>   // type 可以省略,由Hib匹配
     <one-to-one name="passport" cascade="all" fetch="join"></one-to-one> </class>
</hibernate-mapping>//cascade 主控方 设置级联同步更新,delete,sava-update,none
 d. <hibernate-mapping package="OneToOne"> <class name="Passport" table="passport">
    <id name="id" column="id"> <generator class="foreign"> // 主键有外表产生
      <param name="property">user</param> </generator> </id>  // 值来自user成员属性
 <property name="serial" column="serial"></property>
 <one-to-one name="user" class=” 更好” > </one-to-one></class> </hibernate-mapping>
 e. 要想实现级联操作,要让级联双发都知道对方的存在:
passport.setUser(user);    user.setPassport(passport);
tr=session.beginTransaction();session.save(user); tr.commit();// 才会起作用

 


4.
通过外键关联:many to one(环境:很多个人在一个组中且fk:user.group_id- à group.id)
 a. public class Group {  private Integer id; private String name; }
b. public class User2 { private Integer id;   private String name;
private Group group; ...getter/setter;}
 c. <hibernate-mapping package="ManyToOne">
   <class name="Group" table="group">   <id name="id" column="id">
    <generator class="identity"></generator>   </id>
   <property name="name" column="name"></property> </class> </hibernate-mapping>
d. <hibernate-mapping package="ManyToOne"> <class name="User2" table="user2">
 <id name="id" column="id">     <generator class="identity"/>   </id>
   <property name="name" column="name"></property>
 <many-to-one name="group" column="group_id" fetch="join"></many-to-one>
 </class> </hibernate-mapping> // 关系由many端进行维护
 e. 关联双方:Group group=new Group();    group.setId(1); User2 user=new User2(); user.setName("hello");    user.setGroup(group);   //session.save()才行


5.ont to many:(
环境:一个人有多个地址,fk:address.user_id à user.id)
 a. public class MyUser { private Integer id; private String name;
  private Set<Address> addresses; } // 对应多个值采用集合形式
 b. public class Address { private Integer id;  private String address;
private MyUser user; }
 c. <hibernate-mapping package="ManyToOne"> <class name="MyUser" table="myuser">
    <id name="id" column="id"> <generator class="identity"/>    </id>
       <property name="name" column="name"></property>
   <set name="addresses" cascade="all" inverse="true" order-by="address asc" fetch="join">  <key column="user_id"></key> // 必须通过外表的外键建立的关联
      Inverse=”true” 进行反转,由many端来维护关联
<one-to-many class="Address"/> </set> </class> </hibernate-mapping>
 d. <hibernate-mapping package="ManyToOne"> <class name="Address" table="address">
      <id name="id" column="id">   <generator class="identity"/> </id>
     <property name="address" column="address"></property>
   <many-to-one name="user" column="user_id"></many-to-one> </class> </hibernate-mapping>
 e. 使用时要设置关联:MyUser user=new MyUser();user.setName(“hello”);
   Set<Address> addresses=new HashSet<Address>();
   Address add1=new Address();add1.setZipcode(“241000”);
   add1.setUser(user); addresses.add(add1); user.setAddresses(addresses);

 



.HQL: 特点:语法类似sql,使用面向对象的封装,直接返回对象或对象数组
1 .查询整个实体对象(不加select)
String hql="from com.mypack.User4"; Query query=session.createQuery(hql);
     List lists=query.list();   for(int i=0;i< lists.size();i++){
User4 user=(User4)lists.get(i);    System.out.println(user.getId());   }
或者: for(Iterator iter=users.iterator();iter.hasNext();){
    User4 user=(User4)iter.next(); }



2.
查询单个属性(返回单个属性类型): hql="select u.name from User4 u";
       query=session.createQuery(hql);   List names=query.list();// 执行查询
       for(int i=0;i<names.size();i++){   String name=(String)names.get(i);    }


3.1
查询多个属性返回对象数组的集合: hql="select u.name,u.age from User4 u";
       query=session.createQuery(hql);    List names=query.list();// 一步步转型
       for(int i=0;i<names.size();i++){   Object[ ] object=(Object[])names.get(i);
           String name=(String)object[0];        Integer age=(Integer)object[1];


3.2
也可以将多个属性用单个属性替代: hql="select new User4(u.name,u.age) from User4 u";
       query=session.createQuery(hql);   List names=query.list();
       for(int i=0;i<names.size();i++){   User4 user=(User4)names.get(i); }
   注:需要在User4中添加User4(name,age)构造函数,同时添加无参构造函数防止影响其他代码


4.
聚合函数也可以使用: hql="select count(*) from User4 u";
       query=session.createQuery(hql);   int count=(Integer)query.list().get(0);
       System.out.println(count);
  当确定只有唯一的一个结果: int count=(Integer)query.uniqueResult(); 代替


5.
更新(需要加上Transaction): Transaction tr=session.beginTransaction();
                             hql="update User4 u set u.name='liming'";
     query=session.createQuery(hql);    query.executeUpdate();  tr.commit();



6.
删除操作: Transaction tr2=session.beginTransaction();
            hql="delete from User4 u where u.id=81";
            query=session.createQuery(hql);   query.executeUpdate(); tr2.commit();


7.1.?
查询绑定: hql="from User4 u where u.name=?";
query=session.createQuery(hql); query.setString(0, "lm"); List user= query.list();



7.2.
引用占位符:查询绑定: hql="from User4 u where u.name=:name and u.id=:id";
     query=session.createQuery(hql);
     query.setInteger("id", 84);    query.setParameter("name", "lm"); 推荐使用
     List user1= query.list(); assertEquals(8, user1.size());


8.
分页查询功能: hql="from User4 u order by u.id"; query=session.createQuery(hql);
query.setFirstResult(2); 从零计数 query.setMaxResults(10);//十分方便数据库的移植
     List userlist=query.list();    for(int i=0;i<userlist.size();i++){
     User4 name=(User4)userlist.get(i); System.out.println(name.getId()); }


9.
同样支持原生SQL语句: String sql="select id ,name, age from t_user4";
     Query sqlQuery=session.createSQLQuery(sql);
     List result =sqlQuery.list(); for(Iterator it=result.iterator();it.hasNext();){
         Object[] obj=(Object[])it.next();  Integer id=(Integer)obj[0];
         String name=(String)obj[1];        Integer age=(Integer)obj[2]; }
  利用得到的数据: List<User4> users=new ArrayList();
                 User4 user4=new User4(); user4.setId(id); users.add(user4);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值