Hibernate5:Hibernate框架下的基於註解配置的多表關聯的入門級例子(完整版)

環境說明
※Windows10 OS ver:1703
※IDEA 2017 2.3
※Hibernate 5.2.11
※JDK 1.8
※MySQL 5.7

話不多說,直接上代碼.本人初學框架,在網上搜了下,可能我不會搜索,沒找到好的基於註解的多表關聯的完整例子,導致我學起來很喫力.所以上傳上來我的代碼,希望能幫到和我一樣的初學者.
本人菜鳥,如有bug,請評論指出.以便及時改正,謝謝.

User.class

package com.cs.qsx.domain;

import javax.persistence.*;
import java.util.Set;

//聲明是一個映射實體類
@Entity
//指定實體類映射的表  name=表名(數據庫中的表名)
@Table(name = "tb_user")
public class User {
    /**
    * 包名: com.cs.qsx.domain
    * 類名: User
    * 類描述: 註解測試---------用戶類
    * 作者: Lucifer
    * 創建日期: 2017/9/22
    * 創建時間: 19:51
    *
    **/

    // @Id指定該屬性爲數據庫中表的主鍵
    @Id
    // @GeneratedValue指定主鍵的生成策略
    /*
    常用參數:
    1.GenerationType.AUTO 根據底層數據庫自動選擇(默認),若數據庫支持自動增長類型,則爲自動增長。
    2.GenerationType.INDENTITY`根據數據庫的Identity字段生成,支持DB2、MySQL、MS、SQL Server、SyBase與HyperanoicSQL數據庫的Identity類型主鍵。
    3.GenerationType.SEQUENCE 註解聲明瞭一個數據庫序列、支持Oracle DB2.
    4.GenerationType.TABLE 使用一張單表管理主鍵值 結合@TableGenerator使用.
     */
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    // @Column指定該屬性映射到表中的字段
    /*
    常用參數:
    1.name 映射到表中的字段名,默認是屬性名
    2.length 指定該字段的長度,String類型默認255
    3.unique  該字段是否添加唯一性約束
    4.nullable 該字段是否添加非空約束
     */
    @Column(length = 16)
    private String username;
    @Column(length = 50)
    private String password;
    //@Transient 指定映射實體類到數據庫時忽略該字段
    private int roll;

    //mappedBy:表明當前類在指定類中的屬性名
    //一對一雙向關聯
    @OneToOne(mappedBy = "user")
    private UserInfo userInfo;

    /*
    一個用戶有多個訂單,所以用set集合
     */

    @OneToMany(mappedBy = "user",targetEntity = Order.class)
    private Set<Order> orders;


    public User(String username, String password, int roll) {
        this.username = username;
        this.password = password;
        this.roll = roll;
    }

    public User() {
    }

    public Set<Order> getOrders() {
        return orders;
    }

    public void setOrders(Set<Order> orders) {
        this.orders = orders;
    }

    public UserInfo getUserInfo() {
        return userInfo;
    }

    public void setUserInfo(UserInfo userInfo) {
        this.userInfo = userInfo;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getRoll() {
        return roll;
    }

    public void setRoll(int roll) {
        this.roll = roll;
    }

}

UserInfo.class

package com.cs.qsx.domain;

import javax.persistence.*;

@Entity
@Table(name = "tb_userinfo")
public class UserInfo {
    /**
    * 包名: com.cs.qsx.domain
    * 類名: UserInfo
    * 類描述: 註解測試--------用戶詳情類
    * 作者: Lucifer
    * 創建日期: 2017/9/22
    * 創建時間: 19:52
    *
    **/
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    @Column(length = 10)
    private String realName;
    @Column(length = 50)
    private String job;
    @Column(length = 2)
    private String sex;

    /*
    UserInfo和User是一對一關係,採用外鍵關聯
    UserInfo擁有user的外鍵
    外鍵關係在hibernate中體現爲擁有類的對象
     */

    /*
    @OneToOne:體現一對一關係映射 配合@JoinColumn一起使用
    @JoinColumn:多表關係中的外鍵字段
    常用參數:
        name:外鍵字段名稱
        fetch:加載策略
                FetchType.EAGER:勤加載
                FetchType.LAZY:懶加載,如果是集合那麼就是懶加載
        cascade:級聯設置,新增、修改、刪除
        targetEnity:目標類的class
     */

    @OneToOne(targetEntity = User.class,cascade = CascadeType.PERSIST,fetch = FetchType.EAGER)
    @JoinColumn(name = "uid")
    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public UserInfo(String realName, String job, String sex) {
        this.realName = realName;
        this.job = job;
        this.sex = sex;
    }

    public UserInfo() {
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getRealName() {
        return realName;
    }

    public void setRealName(String realName) {
        this.realName = realName;
    }

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "UserInfo{" +
                "id=" + id +
                ", realName='" + realName + '\'' +
                ", job='" + job + '\'' +
                ", sex='" + sex + '\'' +
                ", user=" + user +
                '}';
    }
}

Order.class

package com.cs.qsx.domain;

import javax.persistence.*;
import java.util.Set;

@Entity
@Table(name = "tb_order")
public class Order {
    /**
    * 包名: com.cs.qsx.domain
    * 類名: Order
    * 類描述: 註解測試-------訂單類
    * 作者: Lucifer
    * 創建日期: 2017/9/22
    * 創建時間: 19:52
    *
    **/

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    private double money;
    @Column(length = 10)
    private String rname;
    @Column(length = 11)
    private String phone;
    @Column(length = 100)
    private String raddress;

    /*
    用戶和訂單是一對多的關係
     */

    @ManyToOne(targetEntity = User.class)
    @JoinColumn(name = "uid")
    private User user;

    /*
    訂單和商品是多對多關係
     */

    @ManyToMany
    @JoinTable(name = "tb_orderitem",joinColumns = {@JoinColumn(name = "oid")},inverseJoinColumns = {@JoinColumn(name = "gid")})
    private Set<Goods> goodsSet;



    public Order(double money, String rname, String phone, String raddress) {
        this.money = money;
        this.rname = rname;
        this.phone = phone;
        this.raddress = raddress;
    }

    public Order() {
    }

    public Set<Goods> getGoodsSet() {
        return goodsSet;
    }

    public void setGoodsSet(Set<Goods> goodsSet) {
        this.goodsSet = goodsSet;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    public String getRname() {
        return rname;
    }

    public void setRname(String rname) {
        this.rname = rname;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getRaddress() {
        return raddress;
    }

    public void setRaddress(String raddress) {
        this.raddress = raddress;
    }

}

Goods.class

package com.cs.qsx.domain;

import javax.persistence.*;
import java.util.Set;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

//@Cache:開啓二級緩存的註解
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
@Entity
@Table(name = "tb_goods")
public class Goods {
    /**
    * 包名: com.cs.qsx.domain
    * 類名: Goods
    * 類描述: 註解測試-----商品類
    * 作者: Lucifer
    * 創建日期: 2017/9/22
    * 創建時間: 19:52
    *
    **/

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    @Column(length = 30)
    private String name;
    @Column(length = 30)
    private String type;
    private double price;

    /*
    商品和訂單是多對多
     */

    /*
    @ManyToMany:多對多映射
    @JoinTable:隱式關係表,這張表沒有對應的實體類
     */
    @ManyToMany
    @JoinTable(name = "tb_orderitem",joinColumns = {@JoinColumn(name = "gid")},inverseJoinColumns = {@JoinColumn(name = "oid")})
    private Set<Order> orders;

    public Goods(String name, String type, double price) {
        this.name = name;
        this.type = type;
        this.price = price;
    }

    public Goods() {
    }

    public Set<Order> getOrders() {
        return orders;
    }

    public void setOrders(Set<Order> orders) {
        this.orders = orders;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

}

hibernate.cfg.xml

<?xml version="1.0" encoding="utf-8" ?>
<!--
  ~ Hibernate, Relational Persistence for Idiomatic Java
  ~
  ~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
  ~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
  -->

<!-- 約束文件-->
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<!-- 全局配置-->
<hibernate-configuration>
    <!-- session工廠設置,也就是連接設置-->
    <session-factory>
        <!--1.配置數據庫驅動 -->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <!--2.配置數據庫的url -->
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate_cache?charset=UTF-8</property>
        <!--3.配置用戶名和密碼 -->
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">123456</property>
        <!--4.配置數據庫方言 -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL57Dialect</property>
       <!--5.設置鍵表語句的執行:create or update -->
        <property name="hibernate.hbm2ddl.auto">update</property>
        <!--6.設置顯示自動生成的sql語句 -->
        <property name="hibernate.show_sql">true</property>
        <!--7.設置格式化顯示的sql語句 -->
        <property name="hibernate.format_sql">true</property>
        <!--開啓current_session支持 -->
        <property name="hibernate.current_session_context_class">thread</property>
        <!--開啓查詢緩存 -->
        <property name="hibernate.cache.use_query_cache">true</property>
        <!--開啓二級緩存 -->
        <property name="hibernate.cache.use_second_level_cache">true</property>
        <!--使用的是哪個類管理二級緩存 -->
        <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>

        <!--8.引入映射配置文件 -->
        <mapping class="com.cs.qsx.domain.User" />
        <mapping class="com.cs.qsx.domain.UserInfo" />
        <mapping class="com.cs.qsx.domain.Order" />
        <mapping class="com.cs.qsx.domain.Goods" />
    </session-factory>
</hibernate-configuration>

測試類:AnnoTest.class

package com.cs.qsx.test;

import com.cs.qsx.domain.Goods;
import com.cs.qsx.domain.Order;
import com.cs.qsx.domain.User;
import com.cs.qsx.domain.UserInfo;
import com.cs.qsx.utils.HiberUtils;
import com.cs.qsx.utils.Log;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.HashSet;
import java.util.Set;


public class AnnoTest {
    /**
     * 包名: com.cs.qsx.test
     * 類名: AnnoTest
     * 類描述: 測試註解
     * 作者: Lucifer
     * 創建日期: 2017/9/22
     * 創建時間: 19:50
     **/

    private Session session;
    private Transaction transaction;

    //@Before:@Test運行之前執行
    @Before
    public void before() {
        session = HiberUtils.getCurrentSession();
        transaction = session.beginTransaction();
    }

    //@After:@Test運行之後執行
    @After
    public void after() {
        transaction.commit();
        session.close();
    }

    @Test
    public void test1() {
        //測試一對一--------新增

        User user = new User("mark", "111", 0);
        session.save(user);
        UserInfo userInfo = new UserInfo("張三", "IT", "男");
        userInfo.setUser(user);
        session.save(userInfo);
    }

    @Test
    public void test2() {
        //測試一對一-------查詢

        UserInfo userInfo = session.get(UserInfo.class, 1l);
        Log.info("用戶信息", userInfo);
        Log.info("用戶", userInfo.getUser());

    }

    @Test
    public void test3() {
        //測試多對多------商品添加

        for (int i = 0; i < 10; i++) {
            Goods goods = new Goods("信陽毛尖" + i, "茶葉", 78 * (i + 2) + 100);
            session.save(goods);
        }
    }

    @Test
    public void test4() {
        //測試多對多------訂單添加(需開啓事務)

        Order order = new Order(100, "李四", "10089389", "火星");
        Set<Goods> goods = new HashSet<>();
        goods.add(session.get(Goods.class, 11l));
        goods.add(session.get(Goods.class, 14l));
        User user = session.get(User.class, 1l);
        order.setGoodsSet(goods);
        order.setUser(user);
        Log.info("添加訂單", session.save(order));
    }

    @Test
    public void test5() {
        //測試多對多--------查詢

        Order order = session.get(Order.class, 1l);
        Log.info("訂單", order.getRname() + "---" + order.getGoodsSet().size());
    }

    @Test
    public void test6() {
        //測試一對多-------查詢

        User user = session.get(User.class, 1l);
        Log.info("用戶", user.getUserInfo());
        for (Order order : user.getOrders()) {
            Log.info("用戶訂單", order.getId());
        }
    }
}

工具類:HiberUtils.class

package com.cs.qsx.utils;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HiberUtils {

    private static SessionFactory factory = new Configuration().configure().buildSessionFactory();

    public static SessionFactory getFactory() {
        return factory;
    }

    public static Session getSession(){
        return factory.openSession();
    }

    public static Session getCurrentSession(){
        return factory.getCurrentSession();
    }
}

工具類:Log.class

package com.cs.qsx.utils;

public class Log {
    private static final boolean isDebug = true;

    public static void info(String info,Object msg){
        if(isDebug){
            System.out.println(info +": " + msg.toString());
        }
    }

    public static void err(String info,Object msg){
        if(isDebug){
            System.err.println(info + ": " + msg.toString());
        }
    }
}

2017/9/22
Lucife

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