How to Annotate MySQL Autoincrement Field with JPA Annotations

What is the Java annotation in Hibernate used to auto increment a MySQL Primary Key - @Id

Although you could use GenerationType.AUTO, it's not a very good idea for MySQL and Hibernate 5 because it will default to the TABLE generator which is bad for performance.

So, although [it will disable JDBC batch inserts][3], you should use IDENTITY:

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

or you can use native identifier generator which falls back to IDENTITY on MySQL:

@Id
@GeneratedValue(
strategy= GenerationType.AUTO,
generator="native"
)
@GenericGenerator(
name = "native",
strategy = "native"
)
private Long id;

how to implement auto increment in jpa

If you have a a id which needs to be auto incremented then ,

@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;

Is it possible specify to set an id auto increment not null primary key into a @ManyToMany relationship mapping using Hibernate?

You cannot add an auto increment property to your @ManyToMany annotation directly, instead you should add an auto increment ID to your joined database table and add a @GeneratedValue annotation with an Identity generation type as follows:

@Entity
@Table(name = "portal_user_user_type")
public class PortalUserUserType{

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

...

JPA: how to make a field auto increment

I just want an auto-increment field for 1 entity.

Yes, I get that, this is what you wrote in your question. But it can be interpreted in several ways and repeating the same thing without clarifying doesn't help much :)

So does Pascal's way work or I have to do what Bytecode suggest, query select (max) counter + 1 from MyEntity, to get the next value, then set it to the design field, the persist?

If you want to increment a field per entity record (e.g. a "counter" for Order with id=1, another one for Order with id=2), what I suggested would work.

If you want a behavior similar to a primary key (i.e. an auto-incremented column), it won't. And in that case, standard JPA doesn't offer any particular facility (standard JPA only allows GenereatedValue on Id annotated field). The only way I can think of would be to insert another dedicated entity just to get the primary key from it.


Your exact requirement is unclear but I'm assuming you're talking about a random field, not the primary key. In that case, you could maybe use life cycle callbacks methods:

@Entity
public class MyEntity {
...
private int counter;
...

@PrePersist
@PreUpdate
protected void increment() {
counter = counter + 1;
}
}

JPA @Id @GeneratedValue annotations vs DB primary key?

I assume you are using autonumbers in MySQL and these are autogenerated.

The following code will do what you require:

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "table_id")

Notice the GenerationType.IDENTITY strategy? This tells JPA to use the autogenerated database values.

How do I make JPA entity field truly write-only

Lazy loading attributes

Hibernate can load attribute lazily, but you need to enable byte code enhancements:

  1. First you need to set the property hibernate.enhancer.enableLazyInitialization to true

  2. Then you can annotate the field with @Basic( fetch = FetchType.LAZY ).
    Here's the example from the documentation:

    @Entity
    public class Customer {

    @Id
    private Integer id;

    private String name;

    @Basic( fetch = FetchType.LAZY )
    private UUID accountsPayableXrefId;

    @Lob
    @Basic( fetch = FetchType.LAZY )
    @LazyGroup( "lobs" )
    private Blob image;

    //Getters and setters are omitted for brevity
    }

You can also enable this feature via the Hibernate ORM gradle plugin

Named Native queries

You could also decide to not map it and save/read it with a named native query. It seems a good trade off for a single attribute - it will just require an additional query to save the json.

Example:

@Entity
@Table(name = "MyEntity_table")
@NamedNativeQuery(
name = "write_json",
query = "update MyEntity_table set json_column = :json where id = :id")
@NamedNativeQuery(
name = "read_json",
query = "select json_column from MyEntity_table where id = :id")
class MyEntity {
....
}

Long id = ...
String jsonString = ...
session.createNamedQuery( "write_json" )
.setParameter( "id", id )
.setParameter( "json", jsonString )
.executeUpdate();

jsonString = (String)session.createNamedQuery( "read_json" )
.setParameter( "id", id )
.getSingleResult();

In this case, schema generation is not going to create the column, so you will need to add it manually (not a big deal, considering that there are better tools to update the schema in production).

MappedSuperclass

You can also have two entities extending the same superclass (this way you don't have to copy the attributes). They have to update the same table:

@MappedSuperclass
class MyEntity {

@Id
Long id;
String name
...
}

@Entity
@Table(name = "MyEntity_table")
class MyEntityWriter extends MyEntity {

String json
}

@Entity
@Table(name = "MyEntity_table")
class MyEntityReader extends MyEntity {
// No field is necessary here
}

Now you can use MyEntityWriter for saving all the values and MyEntityReader for loading only the values you need.

I think you will have some problems with schema generation if you try to create the tables because only one of the two will be created:

  • If MyEntityWriter is the first table created, then no problem
  • If MyEntityWriter is the second table created, the query will fail because the table already exist and the additional column won't be created.

I haven't tested this solution though, there might be something I haven't thought about.



Related Topics



Leave a reply



Submit