环境说明
※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