Hibernate筆記

簡單使用

三、Hibernate的簡單使用:

    -- 拷貝jar(lib\required、lib\jpa、lib\optional\c3p0、mysql驅動).

    -- 寫全局配置文件hibernate.cfg.xml放在src目錄下.

       cfg: Configuration.

    -- 編程:

       a. 寫持久化類

          持久類 = pojo + annotation註解(@Entity)

      持久類 = pojo + Xxx.hbm.xml文件

        hbm: Hibernate Mapper (配置pojo與表的轉換關素).

          pojo : Plain Old Java Object 最簡單最傳統的java對象.

          寫pojo類注意的四點:

      -- 必須有一個無參的構造器.

      -- 所有的屬性都要有setter與getter方法.

      -- 屬性不能爲final修飾.

      -- 要提供一個唯一的標識符.(主鍵列) @Id

      注意: 持久類名就是表名, 類的屬性名就表中的列名.(默認)

拷貝了jar包後,不要忘記add to buildPath

在類上加註解@Entity 主鍵列加@Id,就是持久化類

測試類

Configuration configuration = new Configuration()//加載src目錄的hibernate.properties

.configure();//加載src目錄下的hibernate.cfg.xml文件

//第二步:創建SessionFactory

//創建服務註冊對象

ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();

SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);

//第三步:獲取session

Session session = sessionFactory.openSession();

//第四步:獲取事務

Transaction transaction = session.beginTransaction();

//第五步:利用Session完成所有的持久化操作

User u = new User();

u.setId(1);

u.setName("李小華");

u.setAge(18);

//第六步:事務提交或回滾

transaction.commit();

//關閉Session

session.close();

sessionFactory.close();

對象三種狀態

@GeneratedValue(strategy=GenerationType.IDENTITY)mysql的自增長策略(oracle用GenerationType.SEQUENCE)

判斷是不是持久化狀態 session.contains(u)//true持久化狀態

a.添加

1.Serializable id = session.save(持久化對象);

    立即 插入數據

2.session.saveOrUpdate(持久化對象);

3.void session.persist(持久化對象);

   -- 延遲往數據庫插數據

4.Object obj持久化 = session.merge(脫管);//集成添加與修改

b.根據主鍵id獲取持久化對象

User u = (User)session.get(User.class,1);

//立即查詢

User u = (User)session.load(User.class,1);

//延遲查詢,返回一個代理對象,如果關session再用會出異常

c.修改

User u = (User)session.get(User.class,1);

u.setxxx()//不用update,commit的時候才執行update語句

--脫管

session.saveOrUpdate(u);

User user = (User)session.merge(u);

session.update(u);

d.刪除

User u = session.get(User.class,1);

session.delete(u);

操作一級緩存:

1.判斷:session.contains(u);

2.踢出:session.evict(u);

3.清空:session.clear();

4.同步:session.flush();

5.session.close();

JPA註解:

@Table(name="USER",//表名

       schema="",//指定數據庫

       indexes={@Index(columnList="name",name="IDX_NAME"),

                @Index(columnList="age",name="IDX_AGE")},//數組使用花括號,指定索引

       uniqueConstraints={@UniqueConstraint(columnNames={"name","phone"},name="UC_NAME_PHONE")}//聯合唯一約束

       )

class User

寫在類上面的hibernate註解:

@DynamicInsert(true)//動態插入

@DynamicUpdate(true)//動態修改

@SelectBeforeUpdate(true)//修改前先查詢,沒發生改變就不生成update語句

二、主鍵映射

a.主鍵自增長策略:

-- @GeneratedValue(strategy=GenerationType.IDENTITY)

-- @GeneratedValue(strategy=GenerationType.SEQUENCE)

-- @GeneratedValue(strategy=GenerationType.AUTO)推薦

-- @GeneratedValue(strategy=GenerationType.TABLE)//單獨生成一張表來維護主鍵

b.單個屬性做主鍵

--直接在屬性上加@Id

c.多個屬性做主鍵

--多個屬性上加@Id

@Entity @Table(name="EMP_INFO")

public class Employee implements Serializable{//聯合主鍵必須實行序列化接口

    @Id

    private String lastName;

    @Id

    private String firstName;

    private int age;

}

d.複合屬性

持久化類裏@EmbeddedId//複合屬性做主鍵,此對象也要實現序列化接口

三、基本屬性映射

@Column

-- columnDefinition

-- length:長度

-- name:列名

-- nullable:非空約束

-- precision:總位數

-- scale:小數點後面的位數(跟上一個結合使用,java類型是BigDecemal)

-- unique:唯一約束

-- insertable:是否允許插入

-- updatable:是否允許修改

要弄默認值,需要動態插入,以及用包裝類

@Temporal:修飾日期屬性

-- TemporalType.DATE      yyyy-MM-dd

-- TemporalType.TIME      HH:mm:ss

-- TemporalType.TIMESTAMP 

@Lob//大的二進制或文本

@Basic(fetch=FetchType.LAZY)//延遲加載

private byte[] picture;

FileInputStream fis = new FileInputStream("C:\\User\\Administrator\\Picture\\SamplePicture\\Koala.jpg");

byte[] data = new byte[fis.available()];

fis.read(data);

fis.close();

u.setPicture(data);

可能數據庫有大小限制,要改my.ini文件

private transient String tel;//@Transient或者transient關鍵字指定不是持久化的屬性

@Basic:延遲加載屬性

  - fetch

    FetchType.LAZY//延遲加載

    FetchType.EAGER//立即加載

1對多,1的一端做主表,多的一端做從表。

複合屬性映射

@Embedded //複合屬性(內含的)

說明:意思是屬性是 非基本類型

@AttributeOverrides:屬性重新命名(少用)

@AttributeOverrides({

    @AttributeOverride( name="firstName",column=@Column(name="FIRST_NAME") ),//複合屬性更改列名

    @AttributeOverride( name="lastName",column=@Column(name="LAST_NAME") )

})

代替方法:在那個類裏的屬性上寫 @Column(name="F_NAME")

集合映射

會單獨生成一張表。要面向接口編程並且集合屬性要程序員自己初始化。

private List<String> lists = new ArrayList<String>();

1.List集合2.Map集合3.Set集合

公共的註解:

@ElementCollection(fetch=FetchType.LAZY,targetClass=String.class) 元素是集合

                    指定延遲加載 集合映射出來的表

@CollectionTable(name="ADD_INFO",foreignKey = @ForeignKey(name="FK_ADD_USER")) 集合映射出來的表

                  表名 外鍵約束名

1.List集合(有序): 要在屬性上加 @OrderColumn() 排序列

    -- List<String>

    -- List<Address>

    Address複合屬性這個類上面需要加 @Embeddable

public class User{

    @Id @GeneratedValue(strategy=GenerationType.AUTO)

    @Column(name="U_ID")

    private int id;

    @Column(name="U_NAME", length=30,nullable=false)

    private String name;

    @Column(name="U_AGE",nullable=false)

    private int age;

    @ElementCollection(fetch=FetchType.LAZY,targetClass=String.class)//targetClass指的是集合的元素類型

    @CollectionTable(name="ADD_INFO",

                    foreignKey = @ForeignKey(name="FK_ADD_USER"),//更改外鍵約束名

                    joinColumns=@joinColumn(name="USER_ID",REFERENCEDcOLUMNnAME="U_ID"))//改外鍵列名

    @OrderColumn(name="O_ID")//排序列

    private List<String> addresses = new ArrayList<>();

}

    java代碼:

    //利用Session完成所有的持久化操作

    User u = new User();

    u.setAge(18);

    u.setName("李小一");

    u.getAddresses().add("天河區");

    u.getAddresses().add("海珠區");

    session.save(u);

執行完後,生成了USER_INFO表和ADD_INFO表

USER_INFO表

U_ID  U_AGE  U_NAME

1     18     李天一

ADD_INFO表結構是

外鍵列  addresses  O_ID

1        天河區    0

1        海珠區    1

ADD_INFO表的主鍵列:【外鍵列 + 排序列】做聯合主鍵

同樣地,集合是對象類型的,要在這個類的上面加@Embeddable

2.Map集合 @MapKeyColumn() key生成的列

    -- Map<String, String>

    -- Map<String, Address>

    Address複合屬性需要加 @Embeddable

 public class User{

    @Id @GeneratedValue(strategy=GenerationType.AUTO)

    @Column(name="U_ID")

    private int id;

    @Column(name="U_NAME", length=30,nullable=false)

    private String name;

    @Column(name="U_AGE",nullable=false)

    private int age;

    @ElementCollection(fetch=FetchType.LAZY,targetClass=String.class)//targetClass指的是集合的元素類型

    @CollectionTable(name="ADD_INFO",

                    foreignKey = @ForeignKey(name="FK_ADD_USER"),//更改外鍵約束名

                    joinColumns=@joinColumn(name="USER_ID",REFERENCEDcOLUMNnAME="U_ID"))//改外鍵列名

    //map的key

    @MapKeyColumn(name="MAP_KEY")

    private Map<String, String> addresses = new HashMap<>();

}

    java代碼:

    //利用Session完成所有的持久化操作

    User u = new User();

    u.setAge(18);

    u.setName("李小一");

    u.getAddresses().put("100000","天河區");

    u.getAddresses().put("200000","海珠區");

    session.save(u);

      用戶表(user_info):

      U_ID  U_AGE U_NAME

      1      18   李小一

      集合映射出來的表(add_info):

      USER_ID  addresses  MAP_KEY

      1        天河區     100000

      1        海珠區     200000

      說明:USER_ID是外鍵,主鍵列:【外鍵列 + Map的key對應的列】

3.Set集合 (無序列)

    -- Set<String>

    -- Set<Address> -->在屬性上加 @Column(name="A_NAME",nullable=false) 外鍵和這幾個聯合作主鍵

    Address複合屬性需要加 @Embeddable

      //加非空約束,纔有主鍵列(默認沒主鍵列)

      @Column(nullable=false)

      private Set<String> addresses = new HashSet<>();

      java代碼:

        //利用Session完成所有的持久化操作

        User u = new User();

        u.setAge(18);

        u.setName("李小一");

        u.getAddresses().add("天河區");

        u.getAddresses().add("海珠區");

        session.save(u);

      用戶表(user_info):

      U_ID   U_AGE  U_NAME

      1      18     李小一

      集合映射出來的表(add_info):

      USER_ID addresses

      1       天河區

      1       海珠區

      說明:主鍵列:【外鍵列 + set集合元素列】

-------------------------------------------------------------

關聯映射(重點)

   -- 雙向關聯(1-N):(兩邊都加註解)

   1的一端(主表)

   N的一端(從表)

@Entity @Table(name="TEA_INFO")

public class Teacher{

    private int id;

    private String name;

    private String job;

    @OneToMany(fetch=FetchType.LAZY,//延遲加載

               targetEntity=Student.class,//關聯持久化類

           cascade=CascadeType.REMOVE, //級聯刪除(級聯到關聯的實體),一般在主表配置,在從表也可(老師沒數據時會被刪)

           orphanRemoval=true,//刪除孤兒記錄(主表從表斷絕關係)

           mappedBy="teacher") //代表哪邊維護關聯關係,寫關聯的實體中哪個引用了它自己的那個屬性

    private Set<Student> students = new HashSet<>();//1的一端

}

@Entity @Table(name="STU_INFO")

public class Student{

    private int id;

    private String name;

    private int age;

    @ManyToOne(fetch=FetchType.LAZY, //延遲加載

               targetEntity=Teacher.class // 關聯的實體

           )

    @JoinColumn(name="T_ID",referencedColumnName="TEA_ID") //指定外鍵列

    private Teacher teacher;

}

說明:1的一端屬性寫另外的集合,多的一端寫指向1的端的屬性.

(表裏面生成有外鍵列,外鍵列那端就是多的一端——李小華語)。1的一端(加了mappedBy一端)不維護關聯關係

測試代碼:

Teacher t1 = new Teacher();//主表

t1.setName("唐僧");

t1.setJob("長老");

session.save(t1);

Student s1 = new Student(); //從表

s1.setAge(500);

s1.setName("孫悟空");

s1.setTeacher(t1);

Student s2 = new Student(); //從表

s2.setAge(500);

s2.setName("豬八戒");

s2.setTeacher(t1);

說明:先保存主表,再保存從表

tea_info

TEA_ID  TEA_JOB  TEA_NAME

1       長老     唐僧

stu_info是多的一端

STU_ID  STU_AGE  STU_NAME  T_ID

1       500      孫悟空    1

2       500      豬八戒    1

查詢(測試延遲加載):

Teacher t1 = (Teacher)session.get(Teacher.class,1);

Set<Student> students = t1.getStudents();

Iterator<Student> iter = students.iterator();

while(iter.hasNext()){

    Student s = iter.next();

    System.out.println(s.getName());

}

刪除:

session.delete(t1);

說明:配置級聯刪除,只刪老師,也會刪學生。級聯刪除在主表裏面配置。如果在從表配置是不科學(把某老師的學生刪掉同時就刪了那老師,不科學)

t1.getStudents().clear();//把從表關聯的記錄全部刪除

說明:要在主表 @OneToMany註解裏配orphanRemoval=true,//刪除孤兒記錄(主表從表斷絕關係)

------------N-N(多對多)-------------

@ManyToMany()

@Entity @Table(name="TEA_INFO")

public class Teacher{

    private int id;

    private String name;

    private String job;

    @ManyToMany(fetch=FetchType.LAZY,//延遲加載

               targetEntity=Student.class,//關聯持久化類

           cascade=CascadeType.REMOVE, //級聯刪除(級聯到關聯的實體)

           mappedBy="teachers") //代表哪邊維護關聯關係,寫關聯的實體中哪個引用了它自己的那個屬性

    private Set<Student> students = new HashSet<>();//1的一端

}

@Entity @Table(name="STU_INFO")

public class Student{

    private int id;

    private String name;

    private int age;

    @ManyToMany(fetch=FetchType.LAZY, //延遲加載

               targetEntity=Teacher.class // 關聯的實體

           )

    // 生成中間表

    @JoinTable(name="STU_2_TEA",

              joinColumns= @JoinColumn(name="S_ID",referencedColumnName="STU_ID"),//沒有加mappedBy屬性的一端

              inverseJoinColumns= @JoinColumn(name="T_ID",referencedColumnName="TEA_ID")) //加了mappedBy屬性的一端

    private Set<Teacher> teachers = new HashSet<>();

}

(STU_2_TEA)表

S_ID  T_ID

1     1

2     1

-----------------1-1 -----------------

雙向關聯

1-1

說明:1.兩邊都用 @OneToOne

      2.兩邊屬性都用關聯的實體定義

@Entity @Table(name="TEA_INFO")

public class Teacher{

    private int id;

    private String name;

    private String job;

    @OneToOne(fetch=FetchType.LAZY,//延遲加載

               targetEntity=Student.class,//關聯持久化類

           cascade=CascadeType.REMOVE, //級聯刪除(級聯到關聯的實體)

           orphanRemoval=true,//刪除孤兒記錄(主表從表斷絕關係)

           mappedBy="teacher") //代表哪邊維護關聯關係,寫關聯的實體中哪個引用了它自己的那個屬性

    private Student student;

}

@Entity @Table(name="STU_INFO")

public class Student{

    private int id;

    private String name;

    private int age;

    @OneToOne(fetch=FetchType.LAZY, //延遲加載

               targetEntity=Teacher.class // 關聯的實體

           )

    @JoinColumn(name="T_ID",referencedColumnName="TEA_ID") //指定外鍵列

    private Teacher teacher;

}

單向關聯(只需要一邊能查詢)

1-1

1-N(?)

N-1(保留學生這邊的註解,刪掉老師這端的)

N-N

繼承映射

@Entity

@Inheritance(strategy=InheritanceType.SINGLE_TABLE)//生成在一張表中

@DiscriminatorColumn(name="DC",discriminatorType=DiscriminatorType.INTEGER)//辨別者列

@DiscriminatorValue("0")//辨別者列的值

public class Person{

    @Id @Generator()

    private int id;

    private String name;

}

@DiscriminatorValue("1")//辨別者列的值

public class Employee extends Person{

    private double salary;

}

@DiscriminatorValue("2")//辨別者列的值

public class Manager extends Employee{

    private String job;

}

hibernate.cfg.xml配置持久化類

代碼:

Manager m = new Manager();

m.setJob("經理");

m.setName("李大華");

m.setSalary(2909.98);

session.save(m);

Employee m = new Employee();

m.setJob("經理");

m.setName("李大華");

m.setSalary(2909.98);

session.save(m);

DC  ID  NAME  SALARY  JOB

2   1   達宏  299     經理

1   2   大華  1       null

都繼承在同個表裏

第二種方式:

頂級父類:

@Entity

@Inheritance(strategy=InheritanceType.JOINE)//每個類單獨生成一張表

第三種方式:

頂級父類:

@Entity

@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)//每個類單獨生成一張表

一、HQL查詢

Query query = session.createQuery(hql);

分頁

第一個?號 query.setFirstResult((pageIndex-1)*pageSize);

第二個?號 query.setMaxResults(pageSize);

實例:

List<Student> students = session.createQuery("from Student as s").list();//from 持久化類名

List<Student> students = session.createQuery("select s from Student as s").list();

List<Object[]> list = session.createQuery("select name,age from Student").list();//查詢多列

List<String> list = session.createQuery("select name from Student").list();

List<List<Object>> list = session.createQuery("select new list(name,age) from Student").list();//默認是obj數組,new了就變成list

List<Map<String,Object>> lists = session.createQuery("select new map(name,age) from Student").list();//key默認第一列0,第二列是1

List<Map<String,Object>> lists = session.createQuery("select new map(name as n,age as a) from Student").list();//改key

List<Person> lists = session.createQuery("select new org.fkjava.domain.Person(name,age) from Student").list();//

關聯查詢實例:

//老師id爲1的所有學生(隱式關聯,意思是關聯的屬性是個持久化類)

session.createQuery("select s from Student s where s.teacher.id=?").setInteger(0,1).list();

//關聯的屬性是集合,要用顯式關聯

//查學生id爲1的老師

Teacher t = session.createQuery("select t from Teacher t inner join t.students as s where s.id = ?").setParameter(0,1).list();

//抓取連接join fetch

List<Student> stus = session.createQuery("select s from Student s join fetch s.teacher").list();

//order by

List<Student> stus = session.createQuery("select s from Student s order by s.age asc")

                            .setFirstResult((pageIndex-1)*pageSize)

                            .setMaxResults(pageSize)

                            .list();

//統計函數,跟sql一樣,注意ave(),sum()返回出來接收用Double

//根據老師分組,統計學生的數量

List<Object[]> list = session.createQuery("select count(s),s.teacher.name from Student as s group by s.teacher.id")

//過濾出老師id爲2的

Object[] obj = session.createQuery("select count(s),s.teacher.name from Student as s group by s.teacher.id having s.teacher.id=?")

                                .setParameter(0,2).uniqueResult();

session.createQuery("select s from Student s where s.name like ?11")

       .setParameter("11","%小%").list();

二、Criteria查詢:完全面向對象(不需要寫查詢語句)

1.session 2.Criteria criteria = session.createCriteria(持久化類.class)

Criteria 類的方法:

- add(Criterion criterion):添加查詢條件

    Criterion:查詢對象

    a.Restrictions 生成查詢對象的工具類,把where中的運算符,表達式,函數全部改成了靜態的方法。

    萬能的:sqlRestriction(String sql); // 如果沒找到where部分的運算符,表達式,函數,就直接用sqlRestriction(String sql)

    b.Property工具類(生成查詢條件)

- addOrder(Order order):排序

- createAlias(String associationPath):關聯查詢

     創建關聯查詢後(如果不加別名)添加的查詢條件,永遠都是爲目標持久化類添加的

- createCriteria(String associationPath):關聯查詢

     創建關聯查詢後(如果不加別名)添加的查詢條件,永遠都是爲關聯持久化類添加的

- setFetchMode(String associationPath):抓取延遲的屬性

     FetchMode.JOIN:立即加載

     FetchMode.SELECT:延遲加載

- setProjection(Projection projection):查詢哪些列

- 子查詢(離線查詢)

   相當於定義了一條查詢語句

//離線查詢

DetachedCriteria dc = DetachedCriteria.forClass(Student.class);

//與session關聯起來

Criteria ci = dc.getExecutableCriteria(session);

List<Student> lists = ci.list();

//子查詢

List<Student> lists = session.createCriteria(Student.class)

                             .add(Restrictions.in("age",new Object[]{19,20,21})).list();

//子查詢和離線查詢結合

DetachedCriteria dc = DetachedCriteria.forClass(Teacher.class)

                                      .setProjection(Projections.property("id"));

List<Student> lists = session.createCriteria(Student.class)

                             .add(Property.forName("id").in(dc)).list();

例子1://查詢所有學生

List<Student> students = session.createCriteria(Student.class).list();

//添加查詢條件

List<Student> students = session.createCriteria(Student.class)

                                .add(Restrictions.like("name","%小%"))

                .add(Restrictions.between("age",20,22))

                .add(Restrictions.sqlRestriction("length(stu_name) = ?",6,StandardBasicTypes.INTEGER))

                                .list();

//排序

List<Student> students = session.createCriteria(Student.class)

                                .addOrder(Order.asc("age")).list();

//查詢多列

ProjectionList pl = Projections.projectionList();

pl.add(Projections.property("name"))

  .add(Projections.property("age"));

List<Object[]> lists = session.createCriteria(Student.class)

       .setProjection(pl)

       .list();

//查詢指定的列(一列,後面覆蓋前面)

List<Object> lists = session.createCriteria(Student.class)

       .setProjection(Projections.property("name"))

       .setProjection(Projections.property("age"))

       .list();

//聚集函數count、max、min、avg

Object count = session.createCriteria(Student.class)

                      .setProjection(Projections.count("id"))

              .uniqueResult();

//分組

session.createCriteria(Student.class)

       .setProjection(Projections.groupProperty("teacher.id")).list();

//創建關聯

List<Student> lists = session.createCriteria(Student.class)

                             .createAlias("teacher","t")//創建關聯查詢

                 .add(Restrictions.eq("t.id",1)).list();

說明:如果下邊查詢條件不取別名,默認是目標持久化類(Student.class)的條件

//createCriteria :創建關聯

List<Student> lists = session.createCriteria(Student.class)

                             .createCriteria("teacher")創建關聯查詢

                 .add(Restrictions.e q("id",1)).list();//添加查詢條件是Teacher的

//兩個對象都添加查詢條件createAlias

List<Student> lists = session.createCriteria(Student.class)

                             .createAlias("teacher","t")//創建關聯查詢

                 .add(Restrictions.between("age",10,20))//學生

                 .add(Restrictions.eq("t.id",1)).list();//添加查詢條件是Teacher的

//兩個對象都添加查詢條件createCriteria

List<Student> lists = session.createCriteria(Student.class,"s")

                             .createCriteria("teacher")//創建關聯查詢

                 .add(Restrictions.between("s.age",10,20))//學生

                 .add(Restrictions.eq("id",1)).list();//添加查詢條件是Teacher的

//抓取延遲加載

List<Student> lists = session.createCriteria(Student.class)

                 .setFetchMode("teacher",FetchMode.JOIN).list();

三、原生的SQL查詢:寫sql進行查詢

a.session

b.寫sql

c.SQLQuery sqlQuery = session.createSQLQuery(sql);

SQLQuery中的方法:

  - addEntity(Class entityType) : 實體查詢

  - addJoin(String tableAlias, String path) : 關聯查詢

  - addScalar(String columnAlias) : 標量查詢

  - 命名查詢(sql命名查詢)

  第一種方式:使用步驟:

    a.給個配置文件,定義hql語句

      xxx.hbm.xml

      <sql-query name="起個名字">hql語句</sql-query>

    b.在hibernate.cfg.xml文件進行配置

      <mapping resource="org/fkjava/domain/Query.hbm.xml"/>

    c.使用:Query query = session.getNamedQuery("sql語句的名字");

    例子:

    Query.hbm.xml文件

    <hibernate-mapping>

        <!--定義sql語句-->

    <sql-query name="sql-query_1">

        select s.*,t.* from stu_info as s,tea_info as t where s.t_id = t.tea_id

        <!--實體查詢:addEntity-->

        <return alias="s" class="org.fkjava.domain.Student"></return>

        <return alias="t" class="org.fkjava.domain.Teacher"></return>

        <!--關聯查詢:addJoin-->

        <return-join alias="t" property="s.teacher"/>

        <!--標量查詢:addScalar-->

        <return-scalar column="s.stu_age"/>

    </sql-query>

    </hibernate-mapping>

    //命名查詢

    session.getNamedQuery("sql-query_1");

  第二種方式:(加註解)

    a.在持久化類上加註解

      @NamedNativeQuery(name="sql_query_2",resultSetMapping="rs", query="查詢語句")

      @SqlResultSetMapping(name="rs",entities={ @EntityResult(entityClass=Student.class), // 實體查詢

                                                @EntityResult(entityClass=Teacher.class)},

                                     columns={ @ColumnResult(name="s.stu_age")}) // 標量查詢

    說明:下面的註解是關於rs結果集映射的

    b.配置

      <mapping class="org.fkjava.domain.Teacher"/>

    c.使用:Query query = session.getNamedQuery("hql語句的名字");

    List<Object[]> lists = query.list();

    for(Object[] obj : lists){

    System.out.println(obj.length);

    System.out.println(obj[0] + "==" + obj[1] + "==" + obj[2]);

    }

  - 調用存儲過程

  <sql-query name="call_proc">

    {call proc_query(?)}

    <return class="org.fkjava.domain.Student"></return>

  </sql-query>

在數據庫創建存儲過程:

DELIMITER $

CREATE PROCEDURE proc_query(IN minAge INT)

BEGIN

   select * from stu_info where stu_age > minAge;

END

$

//調用存儲過程

List<Student> students = session.getNamedQuery("call_proc").setParameter(0,20).list();

for(Student stu : students){

    System.out.println(stu.getName() + "==" + stu.getAge());

}

//使用SQLQuery直接寫存儲過程sql

List<Student> students = session.createSQLQuery("{call proc_query(?)}")

                                .addEntity(Student.class).setParameter(0,20).list();

for(Student stu : students){

    System.out.println(stu.getName() + "==" + stu.getAge());

}

//addEntity() : 實體查詢

List<Student> students = session.createSQLQuery("select * from stu_info")

                                .addEntity(Student.class).list();

//關聯

List<Object[]> lists = session.createSQLQuery("select s.*, t.* from stu_info as s,tea_info as t where s.t_id = t.tea_id")

                              .addEntity("s",Student.class)

                  .addEntity("t",Teacher.class)

                  .list();

//查兩列

List<Object[]> lists = session.createSQLQuery("select stu_name, stu_age from stu_info").list();

//addScalar() : 標量查詢

List<Object[]> lists = session.createSQLQuery("select * from stu_info")

                              .addScalar("stu_name") // 標量查詢

                  .addScalar("stu_age").list();

//addJoin(String tableAlias, String path) : 關聯查詢

List<Object[]> lists = session.createSQLQuery("select s.*, t.* from stu_info as s,tea_info as t where s.t_id = t.tea_id")

                              .addEntity("s",Student.class) //實體查詢

                  .addEntity("t",Teacher.class)

                  .addJoin("t","s.teacher") // 關聯查詢

                  .addScalar("s.stu_age") // 標量查詢

                  .list();

說明:關聯查詢就是把t放到s.teacher這個屬性裏面去。Student裏面teacher屬性就有值了。

=========================================

########## HQL語句寫法 ##########

1.from 字句

from Student [as s]

2.select 字句

查詢對象:select s from Student as s 返回類型是List<Student>

查詢多列:select s.id,s.age from Student as s 返回類型是List<Object[]>

     select id,age from Student 返回類型是List<Object[]>

     select s,s.name,s.age from Student as s 返回類型是List<Object[]>

查詢一列:select name from Student 返回類型是List<String>

3.select new 字句(可以改變返回的List集合中元素存放的是什麼)

select new list():List<List<>>

select new map():List<Map<>>

select new User():List<User>

舉例:

select new list(name,age) from Student 返回類型是List<List<Object>>,已經不是List<object[]>

select new map(name,age) from Student 返回類型是List<Map<String,Object>>,默認第一個的key爲0,第二個爲1等等

select new map(name as n,age as a) from Student 這時key就變爲 n 和 a

select new org.fkjava.domain.Person(name,age) from Student 返回類型是List<Person>

4.關聯查詢(對象)

-- 隱式關聯: @ManyToOne 、 @OneToOne

   關聯的屬性是一個持久化類

-- 顯式關聯: @OneToMany 、 @ManyToMany

   關聯的屬性是一個集合

類之間的關係:學生類有一個老師的屬性,老師類有一個裝學生的集合

問題來了:現在有一個需求,查老師id爲1的學生,就是關聯查詢

select s from Student as s where s.teacher.id = ?

session.createQuery(hql).setInteger(0,1).list();//第一個0代表 第一個 ? ,參數值爲1

說明:你要查的持久化類關聯的屬性是實體,就用隱式關聯

需求是查學生id爲1的老師,要查老師,看裏面關聯的屬性是集合,就得用顯式關聯

select t from Teacher as t inner join t.students as s where s.id = ?

說明:s就相當於對象了

-- 抓取連接(延遲加載的屬性)

select s from Student as s join fetch s.teacher

排序order by

select s from Student as s order by s.age asc

分頁

List<Student> students = session.createQuery("select s from Student as s")

.setFirstResult((pageIndex - 1)*pageSize)

.setMaxResults(pageSize)

.list();

聚合函數(統計函數)

Long count = (Long)session.createQuery("select count(*) from Student").uniqueResult();

//可以根據具體數據的類型寫返回類型

Integer max = (Integer)session.createQuery("select max(age) from Student").uniqueResult();

Double avg = (Double)session.createQuery("select avg(score) from Student").uniqueResult();

Double sum = (Double)session.createQuery("select sum(score) from Student").uniqueResult();

分組

根據老師分組,統計學生的數量

select count(s),s.teacher.name from Student as s group by s.teacher.id

根據老師分組,統計學生的數量,把老師id爲2的過濾出來

select count(s),s.teacher.name from Student as s group by s.teacher.id having s.teacher.id = ?

where 字句

select s from Student as s where s.name like ?11

...setParameter("11","%小%").list();

小結:

from 字句的類後面不取別名,前面就直接寫屬性名

select new list()意思就是返回的List<List<Object>> 裏面泛型是List集合

select new map()裏的key默認從0開始,如果想改變key,查詢屬性取別名即可

select new 數據傳輸類(包名加類名),這個類要有對應帶參構造器

如果查學生,看裏面關聯屬性是什麼,是類就隱式,是集合就顯式

=======================李韓飛========================

持久化映射文件 *.hbm.xml

<hibernate-mapping>

    <!--name是類名,table是表-->

    <class name="Person" table="t_person">

         <id name="id" column="id">

          <generator class="native"/>

     </id>

     <property name="name" column="t_name"></property>

    </class>

</hibernate-mapping>

連接工廠是線程安全,session非線程安全

一級緩存:clear後就會清掉

批量操作建議的方式:在循環裏面

if(i % 10 == 0){

      session.flush();

      session.clear();

}

普通組件和動態組件(在對象的屬性是個對象)

<component name="phone">

    <property name="companyPhone" column="t_company_phone"/>

    <property name="homePhone"/>

</component>

即映射到類的對象屬性裏

動態組件

private Map attribute = new HashMap();

配置文件:

<dynamic-component name="attribute">

    <property name="key1" column="t_key1" type="string" />

    <property name="key2" column="t_key2" type="integer" />

</dynamic-component>

//高效操作map數據

Iterator<Map.Entry> it = p.getAttribute().entrySet().iterator();

for(;it.hasNext();){

     Map.Entry map = it.next();

     System.out.println(map.getKey()+"==="+map.getValue());

}

數組映射

<array name="arrays">

    <key column="id"/> 指person類的id

    <list-index column="indexs"/>

    <element column="values" type="string"></element>

</array>

<!-- Map的映射配置-->

<map name="myMap">

    <key column="id"/> 指person類的id

    <map-key column="map_key"/>

    <element column="values" type="string"></element>

</map>

<!-- set的映射配置-->

<set name="mySet">

    <key column="id"/> 指person類的id

    <element column="values"></element>

</set>

關聯映射

<one-to-one name="address"/>

<many-to-one name="" nuique="true" not-null="true"/>

保存數據,要先保存主表,再保存從表。

===============================

=====================項目運用======================

多條件分頁查詢的dao寫法:條件是不確定的,所以hql要拼出來。

public List<User> getUserByPage(User user, PageModel pageModel){

    StringBuilder hql = new StringBuilder();

    hql.append("select u from User as u where 1=1");

    List<Object> params = new ArrayList<>();

    if(user != null){

        if(StringUtils.hasText(user.getName())){

            hql.append(" and name like ? ");

            params.add("%"+user.getName()+"%");

        }

        if(StringUtils.hasText(user.getPhone())){

            hql.append(" and phone like ?");

            params.add("%"+user.getPhone()+"%");

        }

        if(user.getJob()!=null && StringUtils.hasText(user.getJob().getCode())){

            hql.append(" and job.code = ?");

            params.add(user.getJob().getCode());

        }

    }

    hql.append(" order by createDate asc");

    return this.findByPage(hql.toString(), pageModel, params);

}

使用第三種方式要在 userDao實現類里加deleteUser方法:

    public void deleteUser(String[] userIds){

        StringBuilder hql = new StringBuilder();

        hql.append("delete from User where userId in(");

        for(int i = 0;i<userIds.length;i++){

            hql.append( i == 0 ? "?" : ",?");

        }

        hql.append(")");

        this.bulkUpdate(hql.toString(), userIds);

    }

--dao實現類增加方法

    public void checkUser(String[] userIds,Short status){

        StringBuilder hql = new StringBuilder();

        hql.append("update User set status = ?,checker = ?,checkDate = ? where userId in(");

        List<Object> params = new ArrayList<>();

        params.add(status);

        params.add(WebConstant.getSessionUser());

        params.add(new Date());

        for(int i = 0;i<userIds.length;i++){

            hql.append( i == 0 ? "?" : ",?");

            params.add(userIds[i]);

        }

        hql.append(")");

        this.bulkUpdate(hql.toString(), params.toArray());

    }

//批量刪除角色

    public void deleteRole(String[] ids){

        StringBuilder hql = new StringBuilder();

        hql.append("delete from Role where id in(");

        Long[] params = new Long[ids.length];//id是long類型要注意

        for(int i=0;i<ids.length;i++){

            hql.append(i==0? "?":",?");

            params[i] = Long.valueOf(ids[i]);

        }

        hql.append(")");

        this.bulkUpdate(hql.toString(),params);

    }

//異步加載樹的hql

public List<Object[]> getModuleByCodeAndName() {

    String hql = "select code,name from Module order by code asc";

    return find(hql);

}

---------------------------------

集合映射(對象有個集合)

T_USER

ID  NAME

T_USER_ADDRESS

USER_ID外鍵 ADDRESS

* 這種是1對多的處理方式

有集合就意味着有額外包含外鍵的一張表

無序,不重複

order-by屬性:order-by="address DESC"(默認ASC)

<set name="addressSet" table="user_addressSet" sort="natural">排序屬性,用TreeSet

    <key column="userId"></key>指定名字即可,會自動找主鍵

    <element type="string" column="address"></element>

</set>

List映射,有序,可重複

<list name="addressList" table="">

    <key column="userId"></key>

    <list-index column="idx"></list-index>

    <element type="string" column=""></element>

</list>

map映射,

<map name="addressMap" table="">

    <key column="userId"></key>

    <map-key type="string" column="key_"></map-key>

    <element type="string" column="address"></element>

</map>

Bag  無序,可重複,用List來引用

<bagname="addressMap" table="">

    <key column="userId"></key>

    <element type="string" column="address"></element>

</bag>

1對多(外鍵在多的一方)

public class Department{

    private Set<Employee> employees;

}

inverse屬性,默認false維護關聯關係,true就不維護關聯關係

--------------------------------------------------------

=====================項目運用======================

多條件分頁查詢的dao寫法:條件是不確定的,所以hql要拼出來。

public List<User> getUserByPage(User user, PageModel pageModel){

    StringBuilder hql = new StringBuilder();

    hql.append("select u from User as u where 1=1");

    List<Object> params = new ArrayList<>();

    if(user != null){

        if(StringUtils.hasText(user.getName())){

            hql.append(" and name like ? ");

            params.add("%"+user.getName()+"%");

        }

        if(StringUtils.hasText(user.getPhone())){

            hql.append(" and phone like ?");

            params.add("%"+user.getPhone()+"%");

        }

        if(user.getJob()!=null && StringUtils.hasText(user.getJob().getCode())){

            hql.append(" and job.code = ?");

            params.add(user.getJob().getCode());

        }

    }

    hql.append(" order by createDate asc");

    return this.findByPage(hql.toString(), pageModel, params);

}

使用第三種方式要在 userDao實現類里加deleteUser方法:

    public void deleteUser(String[] userIds){

        StringBuilder hql = new StringBuilder();

        hql.append("delete from User where userId in(");

        for(int i = 0;i<userIds.length;i++){

            hql.append( i == 0 ? "?" : ",?");

        }

        hql.append(")");

        this.bulkUpdate(hql.toString(), userIds);

    }

--dao實現類增加方法

    public void checkUser(String[] userIds,Short status){

        StringBuilder hql = new StringBuilder();

        hql.append("update User set status = ?,checker = ?,checkDate = ? where userId in(");

        List<Object> params = new ArrayList<>();

        params.add(status);

        params.add(WebConstant.getSessionUser());

        params.add(new Date());

        for(int i = 0;i<userIds.length;i++){

            hql.append( i == 0 ? "?" : ",?");

            params.add(userIds[i]);

        }

        hql.append(")");

        this.bulkUpdate(hql.toString(), params.toArray());

    }

//批量刪除角色

    public void deleteRole(String[] ids){

        StringBuilder hql = new StringBuilder();

        hql.append("delete from Role where id in(");

        Long[] params = new Long[ids.length];//id是long類型要注意

        for(int i=0;i<ids.length;i++){

            hql.append(i==0? "?":",?");

            params[i] = Long.valueOf(ids[i]);

        }

        hql.append(")");

        this.bulkUpdate(hql.toString(),params);

    }

//異步加載樹的hql

public List<Object[]> getModuleByCodeAndName() {

    String hql = "select code,name from Module order by code asc";

    return find(hql);

}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章