Spring Boot、Hibernate、JPA、SQL Server简单demo用例

使用Spring Boot你可以不用或者只使用很少的Spring配置搭建项目,

可以以最小化的依赖开始spring应用,

Spring Boot可以以jar包的形式独立运行,他可以根据类路径中的jar包、类、为jar包里的类自动配置Bean,这样极大减少我们要使用的配置。

 

以下内容有不对的地方,还请告知,感谢!

 

    demo结构图

    

 

一、首先new一个maven项目

    pom.xml文件(因有些标签属性不是很懂,就加了一些注释在里面,可删除)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <!-- 根目录 -->
    <!-- 项目或者组织的唯一标志,并且配置时生成路径也是由此生成,如org.myproject.mojo生成的相对路径为:/org/myproject/mojo -->
    <groupId>com.sec.demeter</groupId>
    <!-- 项目的通用名称 -->
    <artifactId>demeter-demo</artifactId>
    <!-- 项目的版本 -->
    <version>1.0-SNAPSHOT</version>
    <!-- 打包机制,如pom,jar,maven-plugin,ejb,war,ear,rar,par -->
    <packaging>jar</packaging>

    <!-- POM关系:主要为依赖(dependencies),继承(parent),合成 -->
    <!-- 继承于该jar包 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.2.RELEASE</version>
        <relativePath/>
    </parent>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <!--<java.version>1.8</java.version>-->
    </properties>
    <repositories>
        <repository>
            <id>spring-snapshots</id>
            <url>http://repo.spring.io/libs-snapshot</url>
        </repository>
    </repositories>
    <!-- 配置仓库 -->
    <pluginRepositories>
        <pluginRepository>
            <id>spring-snapshots</id>
            <url>http://repo.spring.io/libs-snapshot</url>
        </pluginRepository>
    </pluginRepositories>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <!-- 构建设置 -->
    <dependencies>
        <dependency> <!-- 属性, type:默认为jar类型,常用的类型有:jar,ejb-client,test-jar... || scope:是用来指定当前包的依赖范围,maven的依赖范围
                                || optional:设置指依赖是否可选,默认为false,即子项目默认都继承,为true,则子项目必需显示的引入,与dependencyManagement里定义的依赖类似
                                || exclusions:如果X需要A,A包含B依赖,那么X可以声明不要B依赖,只要在exclusions中声明exclusion
                                || exclusion:是将B从依赖树中删除,如上配置,alibaba.apollo.webx不想使用com.alibaba.external  ,但是alibaba.apollo.webx是集成了com.alibaba.external,r所以就需要排除掉 -->
            <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>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- JPA全称 JavaPersistence API.JPA通过JDK5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <!-- 引入Hibernate依赖包 -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>4.3.7.Final</version>
        </dependency>
        <!-- SQLSERVER -->
        <dependency>
            <groupId>net.sourceforge.jtds</groupId>
            <artifactId>jtds</artifactId>
            <version>1.2.4</version>
        </dependency>
    </dependencies>
</project>

 

二、创建Application类【启动类,有两种方式,可以参考注释中的简要说明】

package com.springBoot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

/**
 * Created by Lisa.Li on 2016/11/7.
 * <p>
 * 运行方式
 * 1:通过在Application中添加@EnableAutoConfiguration标签 开启自动配置,
 * ---然后通过SpringApplication.run(Application.class, args) 运行这个控制器
 * ---这种方式只运行了一个控制器比较方便。
 * ---需要在浏览器中输入http://localhost:8080/hello 就会在页面上展示 Hello World, Hello Spring boot
 * <p>
 * 2:通过@SpringBootApplication + @ComponentScan 开启注解扫描并自动注册相应的注解Bean
 * ---运行Application类即可发布整个应用
 */
// 方式1
// @Controller
// @EnableAutoConfiguration
// public class Application {
//
//     @RequestMapping(value="/hello", method= RequestMethod.GET)
//     @ResponseBody
//     String index() {
//         return "Hello World, Hello Spring boot";
//     }
//
//     public static void main(String[] args) throws Exception {
//         SpringApplication.run(Application.class, args);
//     }
// }

// 方式2
@SpringBootApplication
@ComponentScan(basePackages
        = {
        "com.springBoot.controller",
        "com.springBoot.model",
        "com.springBoot.dao"
})
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
        System.out.println("******************** starting success!");
    }
}

 

三、集成Hibernate持久层框架

  1. pom.xml文件需要引入依赖包,刚才贴的pom.xml已经加了hibernate的依赖,
  2. 添加application.properties配置文件,此外还配置了server的端口号和contextPath
#----------- SQL SERVER ------
spring.datasource.url = jdbc:jtds:sqlserver://xxx.xx.xx.xxx:xxxx/数据库名
spring.datasource.username = xx
spring.datasource.password = xxx
spring.datasource.initialize = false
spring.jpa.show-sql = true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.SQLServerDialect

jdbc.initialSize = 1
jdbc.maxActive = 20
jdbc.maxIdle = 10
jdbc.maxWait = 120000
hibernate.dialect = org.hibernate.dialect.SQLServerDialect
hibernate.show_sql = true
hibernate.jdbc.batch_size = 20
hibernate.connection.pool_size = 20

#----------- Server Config ------
server.port = 8080
server.contextPath = /demo

#----------- Logger Config ------
logging.level.org.springframework.web = DEBUG
#the log level for all demeter package.
logging.level.com.movitech.demeter = DEBUG

 

四、写实体类【建表SQL语句写在 CreateModel_userInfo.sql 中】

package com.springBoot.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * Created by Lisa.Li on 2016/11/10.
 */
@Entity
@Table(name = "test_user_info")
public class UserInfo {

    private Integer id;
    private String userName;
    private String passWord;
    private String userType;
    private String realName;
    private String qq;
    private String email;
    private String tel;
    private Boolean valid;
    private String createUser;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @Column(name = "user_name")
    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    @Column(name = "pass_word")
    public String getPassWord() {
        return passWord;
    }

    public void setPassWord(String passWord) {
        this.passWord = passWord;
    }

    @Column(name = "user_type")
    public String getUserType() {
        return userType;
    }

    public void setUserType(String userType) {
        this.userType = userType;
    }

    @Column(name = "real_name")
    public String getRealName() {
        return realName;
    }

    public void setRealName(String realName) {
        this.realName = realName;
    }

    @Column(name = "qq")
    public String getQq() {
        return qq;
    }

    public void setQq(String qq) {
        this.qq = qq;
    }

    @Column(name = "email")
    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Column(name = "tel")
    public String getTel() {
        return tel;
    }

    public void setTel(String tel) {
        this.tel = tel;
    }

    @Column(name = "valid")
    public Boolean getValid() {
        return valid;
    }

    public void setValid(Boolean valid) {
        this.valid = valid;
    }

    @Column(name = "create_user")
    public String getCreateUser() {
        return createUser;
    }

    public void setCreateUser(String createUser) {
        this.createUser = createUser;
    }

    public String toString() {
        return "UserInfo [id=" + id + ",userName=" + userName + ",passWord=" + passWord + ",userType" + userType + ",realName=" + realName +
                ",qq=" + qq + ",email=" + email + ",tel=" + tel + ",valid=" + valid + ",createUser=" + createUser + "]";
    }
}

 

五、写Dao【数据访问层】,使用Spring Data JPA建立数据访问层十分简单,只需要定义一个继承JpaRepository的接口即可,默认已经有了最基本的CRUD

package com.springBoot.dao;

import com.springBoot.model.UserInfo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * Created by Lisa.Li on 2016/11/10.
 */
public interface UserInfoDao extends JpaRepository<UserInfo, Long> {

    // @Query("SELECT id,user_name,pass_word,user_type FROM UserInfo WHERE user_name = :userName")
    UserInfo findUserByUserName(String userName);

    List<UserInfo> findAll();

    @Transactional
    @Modifying
    @Query("UPDATE UserInfo SET valid = 0 WHERE id = :id")
    void delete(@Param("id") Integer id);
}

 

六、添加Controller层【暴露API接口给前端】

package com.springBoot.controller;

import com.springBoot.model.UserInfo;
import com.springBoot.dao.UserInfoDao;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * Created by Lisa.Li on 2016/11/10.
 */
@RestController
public class UserInfoController {

    Log log = LogFactory.getLog(this.getClass());

    @Autowired
    private UserInfoDao userInfoDao;

    @RequestMapping(value = "hello")
    String index() {
        return "Hello World! Hello Spring boot!";
    }

    /**
     * 添加用户
     *
     * @param userInfo user
     * @return UserInfo
     */
    @RequestMapping(value = "user/addUser", method = RequestMethod.POST)
    public UserInfo addUser(@RequestBody UserInfo userInfo) {
        log.debug("******************** add user");
        return userInfoDao.save(userInfo);
    }

    /**
     * 更新用户(调用save接口,传id)
     *
     * @param userInfo user
     * @return UserInfo
     */
    @RequestMapping(value = "user/updateUser", method = RequestMethod.PUT)
    public UserInfo updateUser(@RequestBody UserInfo userInfo) {
        log.debug("******************** update user, id" + userInfo.getId());
        return userInfoDao.save(userInfo);
    }

    /**
     * 逻辑删除用户
     *
     * @param id 主键
     */
    @RequestMapping(value = "user/invalidUser/{id}", method = RequestMethod.DELETE)
    public void invalidUser(@PathVariable("id") Integer id) {
        log.debug("******************** invalid user, id: " + id);
        userInfoDao.delete(id);
    }

    /**
     * 查询user by XX
     *
     * @param name userName
     * @return UserInfo
     */
    @RequestMapping(value = "user/getUserByName/{name}", method = RequestMethod.GET)
    public UserInfo getUserByName(@PathVariable("name") String name) {
        log.debug("******************** get User by name:" + name);
        UserInfo userInfo = userInfoDao.findUserByUserName(name);
        log.debug(userInfo);
        return userInfo;
    }

    /**
     * find all users
     *
     * @return List<UserInfo>
     */
    @RequestMapping(value = "user/findAll", method = RequestMethod.GET)
    public List<UserInfo> findAll() {
        log.debug("******************** get all users");
        List<UserInfo> userInfos = userInfoDao.findAll();
        return userInfos;
    }
}

 

七、启动项目,使用启动类【Application.java】中方式二, P.S. 上传的图片有点失真,请见谅。

        启动成功会在控制台输出Started.......

        此时可以调用UserInfoController中的API了,

       【此demo项目的contextPath被我配置成  /demo,所以访问接口时请添加 /demo 】,

        P.S. 我一般使用IDEA中Rest Client工具进行访问【前提是IDEA中的Database连接正常】

        也可以使用Google Chrome 插件Advanced REST client进行访问,

        这样最基本的CRUD功能就实现了。

 

八、遇到的问题

  1. 若不配置server的端口号,默认是8080;
  2. 若不配置srever的contextPath默认是“/”;
  3. 第一次写dao层时,在findUserByUserName方法用注解的方式写SQL语句报错,
@Query("SELECT id,user_name,pass_word,user_type FROM UserInfo WHERE user_name = :userName")

        原因是蓝色部分我第一次写成表名test_user_info了,应该写成表对应的实体类的名字。

    4. 再后来发现dao层继承JpaRepository接口之后,对于查询可以有以下实现方法

        4.1. 根据属性名查询,Spring Data JPA支持通过定义在Repository接口中的方法来定义查询,而方法名是根据实体类的属性名确定的,

                如:findByUserName、findByUserNameLike、findByUserNameAndTel等

                    

    5. 调用update方法时,若没有定义某些字段的值,则会被更新成null,

         解决方法参考博客:http://www.cnblogs.com/seed_lee/archive/2011/02/15/1955631.html

    6. 写invalid接口时,override源生delete方法,

        6.1. 第一次没有添加@Modifying标签,报错Not supported for DML operations [UPDATE com.springBoot.model.TestUserInfo SET valid = 0 WHERE id = :id]
        6.2. 第二次加了标签报错:Executing an update/delete query; nested exception is javax.persistence.TransactionRequiredException: Executing an update/delete query
              才发现需要添加注解@Transactional

 

 

后续真正开始项目时,肯定会遇到各种问题,会不定期更新此文......

 

转载于:https://my.oschina.net/niepanLs/blog/786489

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值