【问题标题】:Auto generate id in Spring MVC在 Spring MVC 中自动生成 id
【发布时间】:2016-07-23 04:24:55
【问题描述】:

我正在尝试将 JSP 页面收集的数据保存在数据库 (Postgres) 中。起初我尝试在表单中手动插入任何值(包括id),并且将数据保存在我的数据库中没有问题。现在我正在尝试自动生成id 值,但我对如何正确执行它有点困惑。

我的模型 - 产品

public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String description;
    private double price;
    @DateTimeFormat(pattern = "dd/MM/yyyy")
    private Date date;

    public Product() { }

    public Product(Long id, String description, double price, Date date) {
        this.id = id;
        this.description = description;
        this.price = price;
        this.date = date;
    }
    //getters and setters
}

我的控制器 - DBConnection

@Controller
public class DBConnection {

    @Autowired
    private ProductDao prDao;

    @RequestMapping(value = "/newproduct", method = RequestMethod.GET)
    public ModelAndView showForm() {
        Product product = new Product();
        return new ModelAndView("newproduct", "product", product);
    }

    @RequestMapping(value = "/newproduct", method = RequestMethod.POST)
    public ModelAndView submitForm(@ModelAttribute("product") Product product) {
        ModelAndView mav = new ModelAndView();

        prDao.addProduct(product.getId(), product.getDescription(), product.getPrice(), product.getDate());
        mav.setViewName("product");
        mav.addObject("product", product);
        return mav;
    }
}

ProductDaoImpl

public class ProductDaoImpl implements ProductDao {
    private DataSource dataSource;
    private JdbcTemplate jdbcTemplate;

    @Override
    public void setDataSource(DataSource ds) {
        this.dataSource = ds;
        this.jdbcTemplate = new JdbcTemplate(dataSource);

    }

    @Override
    public void addProduct(Long id, String description, double price, Date date) {
        jdbcTemplate.update("INSERT INTO products values(?, ?, ?, ?)", id, description, price, date);
    }
}

我在 newproduct.jsp 中的表单

<form:form method="POST" action="newproduct" modelAttribute="product">
    <table>
        <tr>
            <td><form:label path="description">Description</form:label></td>
            <td><form:input path="description" /></td>
        </tr>
        <tr>
            <td><form:label path="price">Price</form:label></td>
            <td><form:input path="price" /></td>
        </tr>
        <tr>
            <td><form:label path="date">Date (dd/mm/yyyy)</form:label></td>
            <td><form:input path="date" /></td>
        </tr>
        <tr>
            <td><input type="submit" value="Submit" /></td>
        </tr>
    </table>
</form:form>

提交表单时出错

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; SQL [INSERT INTO products values(?, ?, ?, ?)]; ERROR: null values in column "id" violates not-null constraint
  Detail: The row contains error (null, nnvfe, 10.00, 2010-10-10).; nested exception is org.postgresql.util.PSQLException: ERROR: null values in column "id" violates not-null constraint
  Detail: The row contains error (null, nnvfe, 10.00, 2010-10-10).

我认为问题出在addProduct 方法中:当我尝试获取id 值时,它尚未创建。

如何实现自动生成的 ID? JPA 注释是做那件事的正确方法吗?

【问题讨论】:

  • 您似乎在混合 JPA 和 JDBC。任选其一。
  • 是的,因为我总是将 JPA 与 JSF 一起使用。我是 Spring 新手,很困惑。现在我解决了我的问题,感谢阿里的回答

标签: java spring postgresql jpa


【解决方案1】:

现在我正在尝试自动生成 id 值,但我有点 对如何正确执行感到困惑

如果你想自动生成id,那就不要提供,即使是null。因此,从addProduect 方法中删除id

@Override
public void addProduct(String description, double price, Date date) {
    jdbcTemplate.update("INSERT INTO products values(?, ?, ?)", description, price, date);
}

另外,将您的id 字段设为auto-increment,就像在这个question 中一样。

或者,更改addProduct 方法并使用EntityManager#persist 方法:

@Override
public void addProduct(Product product) {
    entityManager.persist(product);
}

关于错误:

错误:“id”列中的空值违反了非空约束

由于您的表单没有从客户端获取 id 值,因此 /newproduct 端点将有一个 Productnull 作为其 id 值:

@RequestMapping(value = "/newproduct", method = RequestMethod.POST)
public ModelAndView submitForm(@ModelAttribute("product") Product product) { ... }

然后你将这个null 值作为参数传递给addProduct 方法:

prDao.addProduct(product.getId(), ...)

最后addProduct 会尝试将null 值保存为主键 的值,它有一个Non-Null 约束,所以你'重新得到那个错误。

此外,使用 Entity 对象作为与客户端通信的手段,例如Product,不是一个好习惯。尝试定义一些辅助抽象,如 Forms 或 DTO,并将它们用于表单处理或响应组装。

【讨论】:

  • 哦是的..不要使用JdbcTemplate,除非您将 db 字段配置为自动增量。使用Session的保存方法。
  • 我已经尝试过这个解决方案但不起作用..我收到这个错误:请求处理失败;嵌套异常是 org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback;错误的 SQL 语法 [INSERT INTO products values(?, ?, ?)];嵌套异常是 org.postgresql.util.PSQLException:错误:“id”列的类型为 bigint,但表达式的类型为字符变 似乎它试图将描述字段放入 id 字段中。感谢您提供有关实体对象的提示。
  • INSERT INTO products values(?, ?, ?) 只有在 Postgre 中将 id 定义为 autoincrement 时才会起作用。
  • 谢谢,已修复!我也必须更改我的 addProduct 方法:jdbcTemplate.update("INSERT INTO products(description, price, date) values(?, ?, ?)", description, price, date);
  • Spring Boot 只是一个伞形项目,在底层使用了 Data JPA、Security 等。因此,我强烈建议您查看 Spring Boot 并将其用于您的新项目
猜你喜欢
  • 2017-03-27
  • 1970-01-01
  • 2016-11-05
  • 2012-04-24
  • 1970-01-01
  • 2011-01-11
  • 1970-01-01
  • 2017-08-25
相关资源
最近更新 更多