flea-frame-db使用之JPA接入

JPA接入

本節內容須要瞭解JPA封裝內容,請參見筆者 上篇博文java

準備工做

爲了演示JPA接入,須要先準備以下:mysql

  1. MySQL數據庫 (客戶端能夠使用 navicat for mysql)
  2. 新建測試數據庫 fleajpatest
    在這裏插入圖片描述
  3. 新建測試表 student
    在這裏插入圖片描述
    建表語句以下:git

    DROP TABLE IF EXISTS `student`;
    CREATE TABLE `student` (
      `stu_id` int(10) NOT NULL AUTO_INCREMENT COMMENT '學生編號',
      `stu_name` varchar(255) NOT NULL COMMENT '學生姓名',
      `stu_age` tinyint(2) NOT NULL COMMENT '學生年齡',
      `stu_sex` tinyint(1) NOT NULL COMMENT '學生性別(1:男 2:女)',
      `stu_state` tinyint(2) NOT NULL COMMENT '學生狀態(0:刪除 1:在用)',
      PRIMARY KEY (`stu_id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

    接入講解

    1. 實體類

    新建以下實體類Student,對應測試表studentgithub

/**
 * <p> 學生表對應的實體類 </p>
 *
 * @author huazie
 * @version 1.0.0
 * @since 1.0.0
 */
@Entity
@Table(name = "student")
public class Student implements FleaEntity {

    private static final long serialVersionUID = 1267943552214677159L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY, generator = "STUDENT_SEQ")
    @SequenceGenerator(name = "STUDENT_SEQ")
    @Column(name = "stu_id", unique = true, nullable = false)
    private Long stuId; // 學生編號

    @Column(name = "stu_name", nullable = false)
    private String stuName; // 學生姓名

    @Column(name = "stu_age", nullable = false)
    private Integer stuAge; // 學生年齡

    @Column(name = "stu_sex", nullable = false)
    private Integer stuSex; // 學生性別(1:男 2:女)

    @Column(name = "stu_state", nullable = false)
    private Integer stuState; // 學生狀態(0:刪除 1:在用)

    // ... 省略get和set方法
}

2. 持久化單元DAO層實現

上篇博文說到,增長一個持久化單元配置,便須要增長一個持久化單元DAO層實現。針對本次演示新增持久化單元 fleajpa,持久化配置文件 fleajpa-persistence.xml, Spring配置中新增數據庫事務管理者配置,相關內容可參考上一篇博文。下面貼出本次演示的持久化單元DAO層實現代碼:spring

/**
 * <p> FleaJpa數據源DAO層父類 </p>
 *
 * @author huazie
 * @version 1.0.0
 * @since 1.0.0
 */
public class FleaJpaDAOImpl<T> extends AbstractFleaJPADAOImpl<T> {
    // 持久化單元,持久化配置文件中定義,spring配置中持久化接口工廠初始化參數
    @PersistenceContext(unitName="fleajpa")
    protected EntityManager entityManager;

    @Override
    // 持久化事務管理者, spring配置文件中定義
    @Transactional("fleaJpaTransactionManager")
    public boolean remove(long entityId) throws Exception {
        return super.remove(entityId);
    }

    // ...其餘實現省略

    @Override
    protected EntityManager getEntityManager() {
        return entityManager;
    }

}

3. 配置介紹

詳細配置信息,能夠參考筆者上篇博文,這裏再也不贅述。
涉及文件 fleajpa-persistence.xmlapplicationContext.xmlsql

4. 學生DAO層接口

IStudentDAO 繼承了抽象Flea JPA DAO層接口,並定義了兩個方法,分別獲取學生信息列表(分頁)和學生總數。數據庫

/**
 * <p> 學生DAO層接口 </p>
 *
 * @author huazie
 * @version 1.0.0
 * @since 1.0.0
 */
public interface IStudentDAO extends IAbstractFleaJPADAO<Student> {

    /**
     * <p> 學生信息列表 (分頁) </p>
     *
     * @param name      學生姓名,能夠模糊查詢
     * @param sex       性別
     * @param minAge    最小年齡
     * @param maxAge    最大年齡
     * @param pageNum   查詢頁
     * @param pageCount 每頁總數
     * @return 學生信息列表
     * @throws DaoException 數據操做層異常
     * @since 1.0.0
     */
    List<Student> getStudentList(String name, Integer sex, Integer minAge, Integer maxAge, int pageNum, int pageCount) throws DaoException;

    /**
     * <p> 學生總數 </p>
     *
     * @param name   學生姓名,能夠模糊查詢
     * @param sex    性別
     * @param minAge 最小年齡
     * @param maxAge 最大年齡
     * @return 學生總數
     * @throws DaoException 數據操做層異常
     * @since 1.0.0
     */
    int getStudentCount(String name, Integer sex, Integer minAge, Integer maxAge) throws DaoException;

}

5. 學生DAO層實現

StudentDAOImpl 是學生信息的數據操做層實現,繼承持久化單元DAO層實現類,並實現了上述學生DAO層接口自定義的兩個方法。 具體如何使用 FleaJPAQuery 能夠參見下面代碼 :併發

/**
 * <p> 學生DAO層實現類 </p>
 *
 * @author huazie
 * @version 1.0.0
 * @since 1.0.0
 */
@Repository("studentDAO")
public class StudentDAOImpl extends FleaJpaDAOImpl<Student> implements IStudentDAO {

    @Override
    @SuppressWarnings(value = "unchecked")
    public List<Student> getStudentList(String name, Integer sex, Integer minAge, Integer maxAge, int pageNum, int pageCount) throws DaoException {
        FleaJPAQuery query = initQuery(name, sex, minAge, maxAge, null);
        List<Student> studentList;
        if (pageNum > 0 && pageCount > 0) {
            // 分頁查詢
            studentList = query.getResultList((pageNum - 1) * pageCount, pageCount);
        } else {
            // 全量查詢
            studentList = query.getResultList();
        }
        return studentList;
    }

    @Override
    @SuppressWarnings(value = "unchecked")
    public long getStudentCount(String name, Integer sex, Integer minAge, Integer maxAge) throws DaoException {
        FleaJPAQuery query = initQuery(name, sex, minAge, maxAge, Long.class);
        // 統計數目
        query.countDistinct();
        Object result = query.getSingleResult();
        return Long.parseLong(StringUtils.valueOf(result));
    }

    private FleaJPAQuery initQuery(String name, Integer sex, Integer minAge, Integer maxAge, Class<?> result) throws DaoException{
        FleaJPAQuery query = getQuery(result);
        // 拼接 查詢條件
        // 根據姓名 模糊查詢, attrName 爲 實體類 成員變量名,並不是表字段名
        if (StringUtils.isNotEmpty(name)) {
            query.like("stuName", name);
        }
        // 查詢性別
        if (ObjectUtils.isNotEmpty(sex)) {
            query.equal("stuSex", sex);
        }
        // 查詢年齡範圍
        if (ObjectUtils.isNotEmpty(minAge)) {
            // 大於等於
            query.ge("stuAge", minAge);
        }
        if (ObjectUtils.isNotEmpty(maxAge)) {
            // 小於等於
            query.le("stuAge", maxAge);
        }
        return query;
    }
}

6. 學生SV層接口

IStudentSV 繼承抽象Flea JPA SV層接口,並定義兩個方法,分別獲取學生信息列表(分頁)和學生總數。app

/**
 * <p> 學生SV層接口定義 </p>
 *
 * @author huazie
 * @version 1.0.0
 * @since 1.0.0
 */
public interface IStudentSV extends IAbstractFleaJPASV<Student> {

    /**
     * <p> 學生信息列表 (分頁) </p>
     *
     * @param name      學生姓名,能夠模糊查詢
     * @param sex       性別
     * @param minAge    最小年齡
     * @param maxAge    最大年齡
     * @param pageNum   查詢頁
     * @param pageCount 每頁總數
     * @return 學生信息列表
     * @throws DaoException 數據操做層異常
     * @since 1.0.0
     */
    List<Student> getStudentList(String name, Integer sex, Integer minAge, Integer maxAge, int pageNum, int pageCount) throws DaoException;

    /**
     * <p> 學生總數 </p>
     *
     * @param name   學生姓名,能夠模糊查詢
     * @param sex    性別
     * @param minAge 最小年齡
     * @param maxAge 最大年齡
     * @return 學生總數
     * @throws DaoException 數據操做層異常
     * @since 1.0.0
     */
    long getStudentCount(String name, Integer sex, Integer minAge, Integer maxAge) throws DaoException;

}

7. 學生SV層實現

StudentSVImpl 繼承抽象Flea JPA SV層實現類,並實現了上述學生SV層接口的兩個自定義方法。具體實現參見以下代碼:ide

/**
 * <p> 學生SV層實現類 </p>
 *  * @author huazie
 * @version 1.0.0
 * @since 1.0.0
 */
@Service("studentSV")
public class StudentSVImpl extends AbstractFleaJPASVImpl<Student> implements IStudentSV {
    // 注入學生DAO層實現類
    @Autowired
    @Qualifier("studentDAO") 
    private IStudentDAO studentDao; 

    @Override
    public List<Student> getStudentList(String name, Integer sex, Integer minAge, Integer maxAge, int pageNum, int pageCount) throws DaoException {
        return studentDao.getStudentList(name, sex, minAge, maxAge, pageNum, pageCount);
    }

    @Override
    public long getStudentCount(String name, Integer sex, Integer minAge, Integer maxAge) throws DaoException {
        return studentDao.getStudentCount(name, sex, minAge, maxAge);
    }
    // 可參見AbstractFleaJPASVImpl裏的實現
    @Override
    protected IAbstractFleaJPADAO<Student> getDAO() {
        return studentDao;
    }
}

8. JPA接入自測

  • 新增學生信息

    private ApplicationContext applicationContext;
    
    @Before
    public void init() {
        applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        LOGGER.debug("ApplicationContext={}", applicationContext);
    }
    
    @Test
    public void testInsertStudent() {
        try {
            IStudentSV studentSV = (IStudentSV) applicationContext.getBean("studentSV");
            Student student = new Student();
            student.setStuName("張三");
            student.setStuAge(18);
            student.setStuSex(1);
            student.setStuState(1);
            studentSV.save(student);
    
            student = new Student();
            student.setStuName("李四");
            student.setStuAge(19);
            student.setStuSex(1);
            student.setStuState(1);
            studentSV.save(student);
    
            student = new Student();
            student.setStuName("王二麻子");
            student.setStuAge(20);
            student.setStuSex(1);
            student.setStuState(1);
            studentSV.save(student);
    
        } catch (Exception e) {
            LOGGER.error("Exception : ", e);
        }
    }

    執行結果:
    在這裏插入圖片描述

  • 更新學生信息
@Test
    public void testStudentUpdate() {
        try {
            IStudentSV studentSV = (IStudentSV) applicationContext.getBean("studentSV");
            // 根據主鍵查詢學生信息
            Student student = studentSV.query(3L);
            LOGGER.debug("Before : {}", student);
            student.setStuName("王三麻子");
            student.setStuAge(19);
            // 更新學生信息
            studentSV.update(student);
            // 最後再根據主鍵查詢學生信息
            student = studentSV.query(3L);
            LOGGER.debug("After : {}", student);
        } catch (Exception e) {
            LOGGER.error("Exception : ", e);
        }
    }

運行結果:
在這裏插入圖片描述

  • 刪除學生信息
@Test
    public void testStudentDelete() {
        try {
            IStudentSV studentSV = (IStudentSV) applicationContext.getBean("studentSV");
            // 根據主鍵查詢學生信息
            Student student = studentSV.query(3L);
            LOGGER.debug("Before : {}", student);
            // 刪除學生信息(裏面會先去將學生實體信息查出來,而後再刪除)
            studentSV.remove(3L);
            // 最後再根據主鍵查詢學生信息
            student = studentSV.query(3L);
            LOGGER.debug("After : {}", student);
        } catch (Exception e) {
            LOGGER.error("Exception : ", e);
        }
    }

運行結果:
在這裏插入圖片描述

  • 查詢學生信息(按條件分頁查詢)
    表裏自行再插入些數據,用於測試查詢,查詢結果因各自表數據而異;
    目前我表中數據以下:
    在這裏插入圖片描述

    @Test
    public void testStudentQueryPage() {
        try {
    
            IStudentSV studentSV = (IStudentSV) applicationContext.getBean("studentSV");
            List<Student> studentList = studentSV.getStudentList("張三", 1, 18, 20, 1, 5);
            LOGGER.debug("Student List = {}", studentList);
        } catch (Exception e) {
            LOGGER.error("Exception : ", e);
        }
    }

    運行結果:
    在這裏插入圖片描述

  • 查詢學生總數(按條件查詢)
@Test
    public void testStudentQueryCount() {
        try {
            IStudentSV studentSV = (IStudentSV) applicationContext.getBean("studentSV");
            long count = studentSV.getStudentCount("張三", 1, 18, 20);
            LOGGER.debug("Student Count = {}", count);
        } catch (Exception e) {
            LOGGER.error("Exception : ", e);
        }
    }

運行結果:
在這裏插入圖片描述

看到這裏,咱們的JPA接入工做已經成功完成,本demo工程能夠移步到GitHub查看 flea-jpa-test。在JPA封裝介紹博文中,針對Flea JPA查詢對象還存在的一個併發問題,將在後續的博文中介紹。

相關文章
相關標籤/搜索