SpringBoot系列一(入門,ORM,Transaction,log4j2等)

今天寫篇springboot的博客,主要介紹一下springboot搭建以及一些整合。java

首先介紹springboot搭建,我今天選擇Maven,想用Gradle搭建的就本身百度一下吧,訪問「http://start.spring.io/」官網。mysql

填寫好Maven的GroupId以及ArtifactId而後Generate Project。web

我此次使用的是IntellIj IDEA,導入generate出來的project,選擇maven導入,一直選next就好了(記得選一下jdk版本,我用的是1.8),eclipse的話直接import project就好了。spring

初始的項目結構應該就是一個普通的maven項目,只有一個配置文件就是application.properties,也是springboot整合全部東西的配置文件。sql

maven pom文件的依賴只須要如下:數據庫

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
 
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

若是加入web模塊:api

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

 

我用的版本是1.5.4數組

 

能夠按照我上面的項目結構去創建resource文件夾以及package包,注意一點,test和main的根包名須要一致,不然會報錯(具體報錯能夠本身試試)。tomcat

首先來試試最基礎的helloworld。安全

 

 寫一個跟SpringMVC相似的controller就能夠試試helloworld了,在包的根路徑創建一個Application類做爲程序入口(springboot的規矩),也能夠直接運行main方法啓動springboot,至關於內嵌了tomcat。

運行起來以後就能夠在localhost:8080/hello看到映射結果了。

若是使用Test訪問:

Mock一下,而後引入

import static org.hamcrest.Matchers.equalTo;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

具體代碼不解釋了,看一看能猜出來。


而後來看一下普通restful風格的controller咋寫,通俗點說就是我咋用springboot實現springmvc同樣的東東
package com.zhengyu.web;

import com.zhengyu.model.User;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by niezy on 2017/7/26.
 */
@RestController
@RequestMapping(value = "/users") // 經過這裏配置使下面的映射都在/users下
public class UserController {

  // 建立線程安全的Map
  static Map<Long, User> users = Collections.synchronizedMap(new HashMap<Long, User>());

  @RequestMapping(value = "/", method = RequestMethod.GET)
  public List<User> getUserList() {
    // 處理"/users/"的GET請求,用來獲取用戶列表
    // 還能夠經過@RequestParam從頁面中傳遞參數來進行查詢條件或者翻頁信息的傳遞
    List<User> r = new ArrayList<User>(users.values());
    return r;
  }

  @RequestMapping(value = "/", method = RequestMethod.POST)
  public String postUser(@ModelAttribute User user) {
    // 處理"/users/"的POST請求,用來建立User
    // 除了@ModelAttribute綁定參數以外,還能夠經過@RequestParam從頁面中傳遞參數
    users.put(user.getId(), user);
    return "success";
  }

  @RequestMapping(value = "/{id}", method = RequestMethod.GET)
  public User getUser(@PathVariable Long id) {
    // 處理"/users/{id}"的GET請求,用來獲取url中id值的User信息
    // url中的id可經過@PathVariable綁定到函數的參數中
    return users.get(id);
  }

  @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
  public String putUser(@PathVariable Long id, @ModelAttribute User user) {
    // 處理"/users/{id}"的PUT請求,用來更新User信息
    User u = users.get(id);
    u.setName(user.getName());
    u.setAge(user.getAge());
    users.put(id, u);
    return "success";
  }

  @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
  public String deleteUser(@PathVariable Long id) {
    // 處理"/users/{id}"的DELETE請求,用來刪除User
    users.remove(id);
    return "success";
  }

}

同樣的controller如上圖,而後開始測試唄

package com.zhengyu;

import com.zhengyu.web.UserController;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.hamcrest.Matchers.equalTo;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
public class ApplicationTests {

  private MockMvc mvc;

  @Before
  public void setUp() throws Exception {
    mvc = MockMvcBuilders.standaloneSetup(new UserController()).build();
  }

  @Test
  public void testUserController() throws Exception {
    // 測試UserController
    RequestBuilder request = null;

    // 一、get查一下user列表,應該爲空
    request = MockMvcRequestBuilders.get("/users/");
    mvc.perform(request).andExpect(status().isOk()).andExpect(content().string(equalTo("[]")));

    // 二、post提交一個user
    request = post("/users/").param("id", "1").param("name", "測試大師").param("age", "20");
    mvc.perform(request).andExpect(content().string(equalTo("success")));

    // 三、get獲取user列表,應該有剛纔插入的數據
    request = MockMvcRequestBuilders.get("/users/");
    mvc.perform(request).andExpect(status().isOk())
        .andExpect(content().string(equalTo("[{\"id\":1,\"name\":\"測試大師\",\"age\":20}]")));

    // 四、put修改id爲1的user
    request = put("/users/1").param("name", "測試終極大師").param("age", "30");
    mvc.perform(request).andExpect(content().string(equalTo("success")));

    // 五、get一個id爲1的user
    request = MockMvcRequestBuilders.get("/users/1");
    mvc.perform(request).andExpect(content().string(equalTo("{\"id\":1,\"name\":\"測試終極大師\",\"age\":30}")));

    // 六、del刪除id爲1的user
    request = delete("/users/1");
    mvc.perform(request).andExpect(content().string(equalTo("success")));

    // 七、get查一下user列表,應該爲空
    request = MockMvcRequestBuilders.get("/users/");
    mvc.perform(request).andExpect(status().isOk()).andExpect(content().string(equalTo("[]")));

  }



}

好咯~






下面說一下log,spring1.5.4版本是不支持log4j老用法了,我查了一下而後選擇的是log4j2xml的方式,pom以下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

首先springboot自帶的是logback,咱們首先更改以前的pom,加上

 <exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
除去logback,而後引入log4j2.
而後在resource文件夾底下新建一個log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--日誌級別以及優先級排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration後面的status,這個用於設置log4j2自身內部的信息輸出,能夠不設置,當設置成trace時,你會看到log4j2內部各類詳細輸出-->
<!--monitorInterval:Log4j可以自動檢測修改配置 文件和從新配置自己,設置間隔秒數-->
<configuration status="WARN" monitorInterval="30">
    <!--先定義全部的appender-->
    <appenders>
        <!--這個輸出控制檯的配置-->
        <console name="Console" target="SYSTEM_OUT">
            <!--輸出日誌的格式-->
            <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
        </console>
        <!--文件會打印出全部信息,這個log每次運行程序會自動清空,由append屬性決定,這個也挺有用的,適合臨時測試用-->
        <File name="log" fileName="log/test.log" append="false">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
        </File>
        <!-- 這個會打印出全部的info及如下級別的信息,每次大小超過size,則這size大小的日誌會自動存入按年份-月份創建的文件夾下面並進行壓縮,做爲存檔-->
        <RollingFile name="RollingFileInfo" fileName="${sys:user.home}/logs/info.log"
                     filePattern="${sys:user.home}/logs/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log">
            <!--控制檯只輸出level及以上級別的信息(onMatch),其餘的直接拒絕(onMismatch)-->
            <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="100 MB"/>
            </Policies>
        </RollingFile>
        <RollingFile name="RollingFileWarn" fileName="${sys:user.home}/logs/warn.log"
                     filePattern="${sys:user.home}/logs/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log">
            <ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="100 MB"/>
            </Policies>
            <!-- DefaultRolloverStrategy屬性如不設置,則默認爲最多同一文件夾下7個文件,這裏設置了20 -->
            <DefaultRolloverStrategy max="20"/>
        </RollingFile>
        <RollingFile name="RollingFileError" fileName="${sys:user.home}/logs/error.log"
                     filePattern="${sys:user.home}/logs/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log">
            <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="100 MB"/>
            </Policies>
        </RollingFile>
    </appenders>
    <!--而後定義logger,只有定義了logger並引入的appender,appender纔會生效-->
    <loggers>
        <!--過濾掉spring和mybatis的一些無用的DEBUG信息-->
        <logger name="org.springframework" level="INFO"></logger>
        <logger name="org.mybatis" level="INFO"></logger>
        <root level="all">
            <appender-ref ref="Console"/>
            <appender-ref ref="RollingFileInfo"/>
            <appender-ref ref="RollingFileWarn"/>
            <appender-ref ref="RollingFileError"/>
        </root>
    </loggers>
</configuration>

  而後在application.properties配置文件里加上

logging.config=classpath:log4j2.xml 
其實不加也行,起碼我測試這個版本沒問題,隨便你啦,強迫症的加上吧。

下面說說spring jdbcTemplate

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<version>1.5.2.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.21</version>
</dependency>

加上這個依賴,而後咱們開始codeing

建個user類

application.properties加上:

spring.datasource.url=jdbc:mysql://localhost:3306/boot
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.properties.hibernate.hbm2ddl.auto=create-drop
log4j.logger.org.springframework.jdbc.core=DEBUG, file
log4j.logger.org.springframework.jdbc.core.StatementCreatorUtils=TRACE, file

而後建一個UserService,跟springmvc沒什麼兩樣
/**
 * Created by niezy on 2017/7/26.
 */
public interface UserService {
  /**
   * 新增一個用戶
   * 
   * @param name
   * @param age
   */
  void create(String name, Integer age);

  /**
   * 根據name刪除一個用戶高
   * 
   * @param name
   */
  void deleteByName(String name);

  /**
   * 獲取用戶總量
   */
  Integer getAllUsers();

  /**
   * 刪除全部用戶
   */
  void deleteAllUsers();

  /**
   * 根據姓名更新年齡
   * @param name
   * @param age
   */
  void update(String name,int age);


  /**
   * 根據姓名查對象
   * @param name
   * @return
   */
  User querySingleUser(String name);



}
/**
 * Created by niezy on 2017/7/26.
 */
@Service
public class UserServiceImpl implements UserService {
  @Autowired
  private JdbcTemplate jdbcTemplate;

  @Override
  public void create(String name, Integer age) {
    jdbcTemplate.update("insert into USER(NAME, AGE) values(?, ?)", name, age);
  }

  @Override
  public void deleteByName(String name) {
    jdbcTemplate.update("delete from USER where NAME = ?", name);
  }

  @Override
  public Integer getAllUsers() {
    return jdbcTemplate.queryForObject("select count(1) from USER", Integer.class);
  }

  @Override
  public void deleteAllUsers() {
    jdbcTemplate.update("delete from USER");
  }

  @Override
  public void update(String name, int age) {
    jdbcTemplate.update("update user set age = ? where name=? ", age, name);
  }

  @Override
  public User querySingleUser(String name) {
    User user = new User();
    user.setName(name);
    // 返回對象須要beanPropertyRowMapper映射,查詢條件放到Object數組
    return jdbcTemplate.queryForObject("select * from user where name=? ", new Object[] {name},
        new BeanPropertyRowMapper<User>(User.class));
  }
}

 

 

而後測試

package com.zhengyu;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import com.zhengyu.jdbcservice.UserService;

/**
 * Created by niezy on 2017/7/26.
 */


@RunWith(SpringRunner.class)
@SpringBootTest
public class JdbcApplicationTests {
  @Autowired
  private UserService userSerivce;

  @Before
  public void setUp() {
    // 準備,清空user表
    userSerivce.deleteAllUsers();
  }

  @Test
  public void test() throws Exception {
    // 插入5個用戶
    userSerivce.create("zhangsan", 18);
    userSerivce.create("lisi", 19);
    userSerivce.create("wangwu", 20);
    userSerivce.create("haozi", 25);
    userSerivce.create("zhengyu", 23);
    // 查數據庫,應該有5個用戶
    Assert.assertEquals(5, userSerivce.getAllUsers().intValue());
    // 刪除兩個用戶
    userSerivce.deleteByName("zhangsan");
    userSerivce.deleteByName("haozi");
    userSerivce.update("wangwu", 28);
    System.out.println(userSerivce.querySingleUser("zhengyu").toString());
    // 查數據庫,應該有3個用戶
    Assert.assertEquals(3, userSerivce.getAllUsers().intValue());
  }
}

本身跑一下試試  ~

jdbcTemplate只有一點注意的,返回對象稍微麻煩點,須要按他的BeanPropertyRowMapper規矩來,其實還有不少種玩法,ORM框架都有不少玩法,包括我進攜程之後用的攜程的dal框架,返回Object數組啦,集合啦,List<Map>等等,說到底都是封裝的jdbc,而後有的框架是全mapping,有的是半mapping,包括Hibernate實現的JPA標準,也能夠nativeSql支持數組[]選字段返回,也能夠直接mapping整個類,甚至級聯操做,下次專門寫個博客好好說說ORM

 

插一點事務的東東,springboot整合jpa jdbctempalte等ORM的depency已經自帶Transaction註解了,也是默認的

你能夠在@Test處加上

@Transactional(propagation = Propagation.REQUIRED)


 

 

 

而後咱們開始spring-data-jpa黑魔法,號稱業務操做幾乎不須要寫任何sql的ORM框架,也是spring進軍ORM的產品

pom:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>1.5.3.RELEASE</version>
</dependency>

<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0.2</version>
</dependency>

IDEA 1.5.4版本要選擇一下jpa的版本,不然會有引不到JPA註解的bug,我當時就被坑了十幾分鍾,換了不少persistence的depency

老規矩,model開始
package com.zhengyu.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import java.math.BigDecimal;

/**
 * Created by niezy on 2017/7/26.
 */
@Entity
@Table(name = "student")
public class Student {
  @Id
  @GeneratedValue
  private Long id;
  @Column(nullable = false,length = 5)
  private String name;
  @Column(nullable = false)
  private Integer age;

  @Column(nullable = false)
  private BigDecimal salary;

  @Column(nullable = false)
  private String address;

  public Student() {}

  public Student(String name, Integer age) {
    this.name = name;
    this.age = age;
  }

  public Student(Long id, String name, Integer age) {
    this.id = id;
    this.name = name;
    this.age = age;
  }

  public Student(String name, Integer age, BigDecimal salary, String address) {
    this.name = name;
    this.age = age;
    this.salary = salary;
    this.address = address;
  }

  public BigDecimal getSalary() {
    return salary;
  }

  public void setSalary(BigDecimal salary) {
    this.salary = salary;
  }

  public String getAddress() {
    return address;
  }

  public void setAddress(String address) {
    this.address = address;
  }

  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 Integer getAge() {
    return age;
  }

  public void setAge(Integer age) {
    this.age = age;
  }

  @Override
  public String toString() {
    return "Student{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", salary=" + salary + ", address='"
        + address + '\'' + '}';
  }
}

而後service:

package com.zhengyu.datajpaservice;

import com.zhengyu.model.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.math.BigDecimal;
import java.util.List;

/**
 * Created by niezy on 2017/7/26.
 */
public interface StudentRepository extends JpaRepository<Student, Long> {

  Student findByName(String name);

  List<Student> findListByName(String name);

  Student findByNameAndAge(String name, Integer age);

  @Query("from Student  where name=:name")
  Student findStudent(@Param("name") String name);

  List<Student> findByNameOrderBySalaryDesc(String name);

  List<Student> findBySalary(BigDecimal salary);

}

 

測試:
package com.zhengyu;


import com.zhengyu.datajpaservice.StudentRepository;
import com.zhengyu.model.Student;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;

/**
 * Created by niezy on 2017/7/26.
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringdatajpaTest {
  @Autowired
  private StudentRepository studentRepository;

  // @Before
  // public void setUp() {
  // // 準備工做
  // studentRepository.deleteAll();
  //
  // }

  @Test
  @Transactional(propagation = Propagation.REQUIRED)
  public void test() throws Exception {

    // 建立10條記錄
    studentRepository.save(new Student("AAA", 10, new BigDecimal(20000), "shanghai"));
    studentRepository.save(new Student("BBB", 20, new BigDecimal(50000), "beijing"));
    studentRepository.save(new Student("CCC", 30, new BigDecimal(20000), "shanghai"));
    studentRepository.save(new Student("DDD", 40, new BigDecimal(50000), "beijing"));
    studentRepository.save(new Student("EEE", 50, new BigDecimal(20000), "shanghai"));
    studentRepository.save(new Student("EEE", 60, new BigDecimal(50000), "beijing"));
    studentRepository.save(new Student("EEE", 70, new BigDecimal(20000), "shanghai"));
    studentRepository.save(new Student("FFF", 60, new BigDecimal(50000), "beijing"));
    studentRepository.save(new Student("III", 90, new BigDecimal(20000), "shanghai"));
    studentRepository.save(new Student("JJJ", 100, new BigDecimal(50000), "beijing"));

    // 測試findAll, 查詢全部記錄
    Assert.assertEquals(10, studentRepository.findAll().size());
    // 測試findByName, 查詢姓名爲FFF的User
    Assert.assertEquals(60, studentRepository.findByName("FFF").getAge().longValue());
    // 測試findUser, 查詢姓名爲FFF的User
    Assert.assertEquals(60, studentRepository.findStudent("FFF").getAge().longValue());
    // 測試findByNameAndAge, 查詢姓名爲FFF而且年齡爲60的User
    Assert.assertEquals("FFF", studentRepository.findByNameAndAge("FFF", 60).getName());
    // 測試刪除姓名爲AAA的User
    studentRepository.delete(studentRepository.findByName("AAA"));
    // 測試findAll, 查詢全部記錄, 驗證上面的刪除是否成功
    Assert.assertEquals(9, studentRepository.findAll().size());

    // List<Student> stuList = studentRepository.findByNameOrderBySalaryDesc("EEE");
    List<Student> stuList = studentRepository.findBySalary(new BigDecimal(20000));
    for (Student stu : stuList) {
      System.out.println(stu.toString());
    }

    List<Student> stuList2 = studentRepository.findListByName("EEE");
    for (Student stu : stuList2) {
      System.out.println(stu.toString());
    }


  }
}

application.properties加上:

spring.jpa.properties.hibernate.hbm2ddl.auto=create-drop

關於hbm2ddl:

這個屬於hibernate知識點了,我這裏選擇create-drop。

關於spring-data-jpa,確實很輕量很給力

在實際開發過程當中,對數據庫的操做無非就「增刪改查」。就最爲廣泛的單表操做而言,除了表和字段不一樣外,語句都是相似的,開發人員須要寫大量相似而枯燥的語句來完成業務邏輯。

爲了解決這些大量枯燥的數據操做語句,咱們第一個想到的是使用ORM框架,好比:Hibernate。經過整合Hibernate以後,咱們以操做Java實體的方式最終將數據改變映射到數據庫表中。

爲了解決抽象各個Java實體基本的「增刪改查」操做,咱們一般會以泛型的方式封裝一個模板Dao來進行抽象簡化,可是這樣依然不是很方便,咱們須要針對每一個實體編寫一個繼承自泛型模板Dao的接口,再編寫該接口的實現。雖然一些基礎的數據訪問已經能夠獲得很好的複用,可是在代碼結構上針對每一個實體都會有一堆Dao的接口和實現。

因爲模板Dao的實現,使得這些具體實體的Dao層已經變的很是「薄」,有一些具體實體的Dao實現可能徹底就是對模板Dao的簡單代理,而且每每這樣的實現類可能會出如今不少實體上。Spring-data-jpa的出現正可讓這樣一個已經很「薄」的數據訪問層變成只是一層接口的編寫方式。

Spring-data-jpa的能力遠不止本文提到的這些,因爲本文主要以整合介紹爲主,對於Spring-data-jpa的使用只是介紹了常見的使用方式。諸如@Modifying操做、分頁排序、原生SQL支持以及與Spring MVC的結合使用等等內容就不在本文中詳細展開

 


 

 




 

@Transactional(isolation = Isolation.DEFAULT)
相關文章
相關標籤/搜索