首先配置好persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<persistence-unit name="myjpa" transaction-type="RESOURCE_LOCAL">
<properties>
<!-- 必须配置4个连接数据库属性 -->
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />
<property name="hibernate.connection.url" value="jdbc:mysql:///jpa" />
<property name="hibernate.connection.username" value="root" />
<property name="hibernate.connection.password" value="******" />
<!-- 必须配置1个方言属性 -->
<!-- 实现跨数据库关键类 :查询MySQLDialect的getLimitString方法 -->
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
<!-- 可选配置 -->
<!-- 是否自动生成表 自动创建表-->
<property name="hibernate.hbm2ddl.auto" value="create" />
<!-- 是否显示sql -->
<property name="hibernate.show_sql" value="true" />
<!-- 格式化sql -->
<!--<property name="hibernate.format_sql" value="true" />-->
</properties>
</persistence-unit>
我们再来简单创建两个类,完成多对一
/**
*多方
* 产品类
*
*
*/
//交给jpa管理,在mysql中创建对应的表
@Entity
@Table(name="t_product")
public class Product {
//设置主键,自增
@Id
@GeneratedValue
private Long id;
private String name;
//设置附键
@ManyToOne(fetch = FetchType.LAZY)//懒加载延迟加载,提高性能
@JoinColumn(name = "dir_id")
private ProductDir dir;
}
/**
*一方
* 产品类型类
*
*/
@Entity
@Table(name="t_productDir")
public class ProductDir {
@Id
@GeneratedValue
private Long id;
private String name;
}
接下来我们来完成多对一的CRUD
首先我们来抽取一个获取EntityManager实体管理对象的工具类
/**
*
* 抽取创建EntityManager的工具类
*/
public class Jpautil {
private static EntityManagerFactory factory;
//放入静态代码块中实现单例
static{
try {
//获取工厂类
factory = Persistence.createEntityManagerFactory("cn.itsource.jpa");
} catch (Exception e) {
e.printStackTrace();
}
}
//返回EntityManager的方法
public static EntityManager getEntityManager(){
return factory.createEntityManager();
}
}
接下来我们来完成Dao层代码的编写,由于CRUD的方法类似,我们来抽取代码,做一个代码的简化,注意这里放置的是共有的方法
public interface IBaseDao<T> {
//保存
void save(T t);
//修改
void update(T t);
//删除
void delete(Serializable id);
//查询一条数据
T queryOne(Serializable id);
//查询所有数据
List<T> queryAll();
}
我们让两个类的接口都去继承它
public interface IProductDao extends IBaseDao<Product> {
//这里现在写了其实没有实现任何功能,当时当我们后续这个类有自己独有的方法的时候,就可以在这里添加自己的方法
}
public interface IProductDirDao extends IBaseDao<ProductDir> {
}
再写一个共有的实现类去实现IBaseDao公共接口
public class BaseDaoImpl<T> implements IBaseDao<T> {
//在查询中要使用到的实体类
private Class entityClass;
//通过构造方法子类可以传入他的实体类
public BaseDaoImpl(Class entityClass) {
this.entityClass = entityClass;
}
//保存方法
@Override
public void save(T t) {
EntityManager entityManager = null;
try {
entityManager = Jpautil.getEntityManager();
//开启事务
entityManager.getTransaction().begin();
//保存
entityManager.persist(t);
//提交事务
entityManager.getTransaction().commit();
} catch (Exception e) {
//回滚事务
entityManager.getTransaction().rollback();
e.printStackTrace();
} finally {
//关闭
entityManager.close();
}
}
//修改方法
@Override
public void update(T t) {
EntityManager entityManager = null;
try {
entityManager = Jpautil.getEntityManager();
//开启事务
entityManager.getTransaction().begin();
//修改
entityManager.merge(t);
//提交事务
entityManager.getTransaction().commit();
} catch (Exception e) {
//回滚事务
entityManager.getTransaction().rollback();
e.printStackTrace();
} finally {
//关闭
entityManager.close();
}
}
//删除方法
@Override
public void delete(Serializable id) {
EntityManager entityManager = null;
try {
entityManager = Jpautil.getEntityManager();
//开启事务
entityManager.getTransaction().begin();
//先查询
T t = (T)entityManager.find(entityClass, id);
if (t != null){
//再删除
entityManager.remove(t);
}
//提交事务
entityManager.getTransaction().commit();
} catch (Exception e) {
//回滚事务
entityManager.getTransaction().rollback();
e.printStackTrace();
} finally {
//关闭
entityManager.close();
}
}
//查询一个数据
@Override
public T queryOne(Serializable id) {
EntityManager entityManager = null;
try {
entityManager = Jpautil.getEntityManager();
//查询方法
return (T)entityManager.find(entityClass, id);
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭
entityManager.close();
}
return null;
}
@Override
public List<T> queryAll() {
EntityManager entityManager = null;
try {
entityManager = Jpautil.getEntityManager();
//查询所有方法
return entityManager.createQuery("from "+entityClass.getName()).getResultList();
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭
entityManager.close();
}
return null;
}
}
写两个子类分别去实现他们自己的接口,同时去继承共用的实现类BaseDaoImpl,那么就能完成覆写自己接口的方法
public class ProductDaoImpl extends BaseDaoImpl<Product> implements IProductDao {
//创建一个构造方法,将自己的实体类传给父类
public ProductDaoImpl() {
super(Product.class);
}
}
public class ProductDirDaoImpl extends BaseDaoImpl<ProductDir> implements IProductDirDao {
public ProductDirDaoImpl() {
super(ProductDir.class);
}
}
到这里我们简单的多对一CRUD就完成了,同时提取简练了代码,这里我只是简单示范了两个类实现多对一,在面对更多类时,我们只需要去实现公共接口,同时继承公共实现类即可
附上简单的抽取代码思路:
简单的测试一下
private IProductDirDao productDirDao = new ProductDirDaoImpl();
private IProductDao productDao = new ProductDaoImpl();
@Test
public void saveTest() {
//产品类型
ProductDir productDir = new ProductDir();
productDir.setName("白色系列");
//产品1
Product product1 = new Product();
product1.setName("罗技530");
product1.setDir(productDir);
//产品2
Product product2 = new Product();
product2.setName("罗技820");
product2.setDir(productDir);
//注意这里要先保存一方,再保存多方
productDirDao.save(productDir);
productDao.save(product1);
productDao.save(product2);
}