Hibernate5:Hibernate框架下的基于注解配置的多表关联的入门级例子(完整版)

本文提供了一个基于Hibernate注解实现的多表关联示例,包括一对一、一对多及多对多关联的详细代码实现,适用于初学者快速掌握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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值